lgpio 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84493ab6ca425d960887480b8f186a610fd9e41f0885657c79b5a4038a8a2035
4
- data.tar.gz: 705d88399e518bdbc167eca65cd795dea2d33936b919aaaf22a34c8be032a1a1
3
+ metadata.gz: 0ba4963055ec58ea685427a0c9395eedfbc20cf0159df764edbd3b735dd7ce40
4
+ data.tar.gz: b4149669d2ac089120582d09db4ab6d0e9bb45f8c93e22a62164272f9150c758
5
5
  SHA512:
6
- metadata.gz: 77f3c42ed9a94f8ea0c59acc2cb276efd400990099ac4272f06619645953f6014dbc4a9330d04ed154eee86fabba4791290fcd7201b326f2d6f4b2437a5d5812
7
- data.tar.gz: 7fd2aa6715e36f3e95d35248b1b13ffb141dca3c50b1ab7a5fbe2e420b67a3873d3de50a24b5eda460a50bd69133492043356715522b27cbe509e280c3174699
6
+ metadata.gz: 9e3397df71dadb44d9ebfb96d6732d9ba211f9dc5a530b96747e7ec2ee93e22b6412218f61938560864c10208fdc60609b93c18707ca67332c2a8800e880d21c
7
+ data.tar.gz: 7ebd239afcd78e16ea893943f1e226b06e68c9b0b2cf4c3a98acebe3f23a33e044fa51c1309b1779ac5415877be8512b78cff651e48a87fc0fe860ef2405531f
data/README.md CHANGED
@@ -1,34 +1,52 @@
1
1
  # lgpio
2
2
 
3
- Ruby bindings for the [lgpio (lg)](https://github.com/joan2937/lg) Linux library, running on single board computers (SBCs), like Raspberry Pi.
3
+ Ruby gem with bindings for the [lgpio (lg)](https://github.com/joan2937/lg) C library. This is for single-board-computers (SBCs) running Linux, such as Orange Pi, Raspberry Pi, etc. It provides low-level access to the GPIO, I2C, SPI, and PWM subsytems.
4
+
5
+ ## Standard LGPIO Features
4
6
 
5
- ## Standard LGPIO Functions
6
7
  - [x] GPIO Read/Write
7
8
  - [x] GPIO Group Read/Write
8
- - [x] GPIO Alerts / Callbacks
9
- - lg generates alerts at high speed, in a separate thread. In Ruby, they can be read from a queue as part of your application loop.
10
- - [x] PWM Output
11
- - Software timed on any pin. No interface for hardware PWM yet.
9
+ - [x] GPIO Alerts
10
+ - Alerts are generated by a separate thread, and can be read from a queue in Ruby.
11
+ - No real "callback" functionality.
12
+ - [x] Software PWM Output
13
+ - Timing not 100% precise, but works on any GPIO.
14
+ - Not recommended for servo motors, will jitter.
12
15
  - [x] Wave
13
- - Software timed on any pin, as with PWM.
14
- - [x] I2C
15
- - [x] SPI
16
+ - Software timed on any pin(s), as with PWM.
17
+ - [x] Hardware I2C
18
+ - [x] Hardware SPI
19
+
20
+ ## Extra Features (Built on LGPIO)
21
+
22
+ - [x] `LGPIO.gpio_read_ultrasonic` sends a pulse on a `trigger` pin, then measures a single pulse on a separate `echo` pin. Used for HC-SR04 or similar. See `examples/hcsr04.rb`.
23
+ - [x] `LGPIO.gpio_read_pulses_us` outputs a reset pulse on a pin, then polls for a sequence of input pulses. Used for DHT enviro sensors or similar. See `examples/dht.rb`.
24
+ - [x] Bit Bang I2C
25
+ - [x] Bit Bang SPI
26
+ - [x] Bit Bang 1-Wire
27
+ - [x] WS2812 addressable LEDs over hardware SPI
28
+ - Outputs on MOSI/PICO pin
29
+ - Must be able to set SPI clock frequency to 2.4 MHz
30
+
31
+ ## Hardware PWM Features
32
+
33
+ These use the sysfs PWM interface, not lgpio C, but are a good fit for this gem.
34
+
35
+ - [x] Hardware PWM Output
36
+ - [x] Servo (based on hardware PWM)
37
+ - [x] On-off Keying (OOK) Modulated Waves
38
+ - Carrier generated by hardware PWM. Software modulated with monotonic clock timing.
39
+ - Useful for sending infrared signals at 38kHz, for example.
16
40
 
17
- ## Extras
18
- - [x] WS2812 over SPI
19
- - Only outputs on a SPI MOSI pin. Must be able to set SPI clock frequency to 2.4 MHz.
20
- - [ ] Bit Bang SPI
21
- - [ ] Bit Bang I2C
41
+ **Note:** Once hardware PWM is used on a pin, it stays PWM until reboot. The associated GPIO won't work.
22
42
 
23
43
  ## Installation
24
44
  On Debian-based Linuxes (RaspberryPi OS, Armbian, DietPi etc.):
25
45
  ```bash
26
46
  sudo apt install swig python3-dev python3-setuptools
27
47
 
28
- # NOTE: There's a bug with GPIO numbers > 255.
29
- # If you need to use those, wget the second URL instead, until that fix is merged.
30
- wget https://github.com/joan2937/lg/archive/master.zip
31
- # wget https://github.com/vickash/lg/archive/refs/heads/master.zip
48
+ # Temporary fork of: wget https://github.com/joan2937/lg/archive/master.zip
49
+ wget https://github.com/vickash/lg/archive/refs/heads/master.zip
32
50
 
33
51
  unzip master.zip
34
52
  cd lg-master
@@ -39,17 +57,18 @@ gem install lgpio
39
57
  ```
40
58
 
41
59
  ## Enabling Hardware & Permissions
42
- Depending on your SBC and Linux distro/version, you may need to manually enable I2C and SPI hardware. You should use the setup or config tool that came with your distro for that.
60
+ Depending on your SBC and Linux distro/version, you may need to manually enable hardware I2C, SPI, and PWM. You should use the config tool that came with your distro for that, if possible.
43
61
 
44
- You may also not have permission to access the GPIO and peripherals. To run without `sudo`, you need read+write permission to some or all of the following devices:
62
+ Even when these are enabled, you may not have permission to access them. To run without `sudo`, you need read+write permission to some or all of the following:
45
63
  ```
46
- /dev/gpiochip* (For GPIO, example: /dev/gpiochip0)
47
- /dev/i2c-* (For I2C, example: /dev/i2c-1)
48
- /dev/spidev* (For SPI, example: /dev/spidev-0.1)
64
+ /dev/gpiochip* (For GPIO, example: /dev/gpiochip0)
65
+ /dev/i2c-* (For I2C, example: /dev/i2c-1)
66
+ /dev/spidev* (For SPI, example: /dev/spidev0.1)
67
+ /sys/class/pwm/pwmchip* (For PWM, example: /sys/class/pwm/pwmchip0)
49
68
  ```
50
69
 
51
70
  ## Documentation
52
- - See examples folder for demos of every implemented interface.
71
+ - See examples folder for demos of everything implemented.
53
72
  - Development was done on an Orange Pi Zero 2W. Your GPIO numbers may be different, so change them.
54
73
  - For more info, see the [lgpio C API docs.](https://abyz.me.uk/lg/lgpio.html)
55
74
  - As much as possible, the Ruby methods closely follow the C API functions, except:
data/examples/bench_in.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- PIN = 258
4
+ PIN = 260
5
5
  COUNT = 1000000
6
6
 
7
7
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- PIN = 260
4
+ PIN = 272
5
5
  COUNT = 1000000
6
6
 
7
7
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
data/examples/blink.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- LED = 260
4
+ LED = 272
5
5
  INTERVAL = 0.25
6
6
 
7
7
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
data/examples/dht.rb ADDED
@@ -0,0 +1,47 @@
1
+ require 'lgpio'
2
+
3
+ GPIO_CHIP = 0
4
+ DHT_PIN = 267
5
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
6
+ #
7
+ # Read a series of pulses input to a GPIO, with an (optional) reset output pulse at start.
8
+ # Arguments in order are:
9
+ # gpiochip handle
10
+ # GPIO number
11
+ # Starting (reset) output pulse time in microseconds (0 for no reset)
12
+ # Reset pulse level (0 or 1)
13
+ # Maximum number of pulses to read
14
+ # Timeout in milliseconds
15
+ #
16
+ data = LGPIO.gpio_read_pulses_us(chip_handle, DHT_PIN, 20_000, 0, 84, 100)
17
+
18
+ # Handle errors.
19
+ raise "error: DHT sensor not connected" unless data
20
+ raise "LGPIO error: #{data}" if data.class == Integer
21
+
22
+ # Discard unneeded pulses
23
+ data = data.last(81)
24
+ raise "error: incomplete DHT data" unless data.length == 81
25
+ data = data.first(80)
26
+
27
+ # Convert to bytes
28
+ bytes = []
29
+ data.each_slice(16) do |b|
30
+ byte = 0b00000000
31
+ b.each_slice(2) do |x,y|
32
+ bit = (y<x) ? 0 : 1
33
+ byte = (byte << 1) | bit
34
+ end
35
+ bytes << byte
36
+ end
37
+
38
+ # CRC
39
+ crc = bytes[0..3].reduce(0, :+) & 0xFF == bytes[4]
40
+ raise "error: DHT CRC check failed" unless crc
41
+
42
+ # Convert and display
43
+ temperature = ((bytes[2] << 8) | bytes[3]).to_f / 10
44
+ humidity = ((bytes[0] << 8) | bytes[1]).to_f / 10
45
+
46
+ puts "DHT Temperature: #{temperature} \xC2\xB0C"
47
+ puts "DHT Humidity: #{humidity} %"
data/examples/group_in.rb CHANGED
@@ -2,8 +2,8 @@
2
2
  require 'lgpio'
3
3
 
4
4
  GPIO_CHIP = 0
5
- BUTTONS = [258, 256]
6
- LEDS = [260, 267]
5
+ BUTTONS = [259, 267]
6
+ LEDS = [272, 258]
7
7
  INIT_STATE = [0, 0]
8
8
 
9
9
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- LEDS = [260, 267]
4
+ LEDS = [272, 258]
5
5
  INIT_STATE = [0, 0]
6
6
  INTERVAL = 250_000 # 250ms
7
7
  TIMES = 10
@@ -0,0 +1,32 @@
1
+ #
2
+ # Example showing an HC-S04 ultrasonic distance sensor.
3
+ #
4
+ # NOTE: Some versions of this sensor require 5V power to function properly.
5
+ # If using one of these, use a 5V to 3.3V level shifter between your board and
6
+ # the sensor, at least on the echo pin.
7
+ #
8
+ require 'lgpio'
9
+
10
+ GPIO_CHIP = 0
11
+ ECHO_PIN = 228
12
+ TRIGGER_PIN = 270
13
+ SPEED_OF_SOUND = 343.0
14
+
15
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
16
+
17
+ loop do
18
+ # Arguments in order are:
19
+ # chip handle, trigger pin, echo pin, trigger time (us)
20
+ #
21
+ # HC-SR04 uses 10 microseconds for trigger. Some others use 20us.
22
+ #
23
+ microseconds = LGPIO.gpio_read_ultrasonic(chip_handle, TRIGGER_PIN, ECHO_PIN, 10)
24
+
25
+ if microseconds
26
+ mm = (microseconds / 2000.0) * SPEED_OF_SOUND
27
+ puts "Distance: #{mm.round} mm"
28
+ else
29
+ puts "Cound not read HC-SR04 sensor"
30
+ end
31
+ sleep 0.5
32
+ end
@@ -1,6 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
- I2C_DEV = 2
3
+ I2C_DEV = 3
4
+ ADDRESS = 0x38
4
5
  POWER_ON_DELAY = 0.100
5
6
  RESET_DELAY = 0.020
6
7
  COMMAND_DELAY = 0.010
@@ -10,7 +11,7 @@ SOFT_RESET = [0xBA]
10
11
  INIT_AND_CALIBRATE = [0xE1, 0x08, 0x00]
11
12
  START_MEASUREMENT = [0xAC, 0x33, 0x00]
12
13
 
13
- aht10_handle = LGPIO.i2c_open(I2C_DEV, 0x38, 0)
14
+ aht10_handle = LGPIO.i2c_open(I2C_DEV, ADDRESS, 0)
14
15
 
15
16
  # Startup sequence
16
17
  sleep(POWER_ON_DELAY)
@@ -1,6 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
- I2C_DEV = 2
3
+ I2C_DEV = 3
4
+ ADDRESS = 0x38
4
5
  POWER_ON_DELAY = 0.100
5
6
  RESET_DELAY = 0.020
6
7
  COMMAND_DELAY = 0.010
@@ -10,7 +11,7 @@ INIT_AND_CALIBRATE = [5, 3, 0xE1, 0x08, 0x00, 0]
10
11
  START_MEASUREMENT = [5, 3, 0xAC, 0x33, 0x00, 0]
11
12
  READ_SIX = [4, 6, 0]
12
13
 
13
- aht10_handle = LGPIO.i2c_open(I2C_DEV, 0x38, 0)
14
+ aht10_handle = LGPIO.i2c_open(I2C_DEV, ADDRESS, 0)
14
15
 
15
16
  # Startup sequence
16
17
  sleep(POWER_ON_DELAY)
@@ -0,0 +1,40 @@
1
+ require 'lgpio'
2
+
3
+ POWER_ON_DELAY = 0.100
4
+ RESET_DELAY = 0.020
5
+ COMMAND_DELAY = 0.010
6
+ MEASURE_DELAY = 0.080
7
+ DATA_LENGTH = 6
8
+ SOFT_RESET = [0xBA]
9
+ INIT_AND_CALIBRATE = [0xE1, 0x08, 0x00]
10
+ START_MEASUREMENT = [0xAC, 0x33, 0x00]
11
+
12
+ GPIO_CHIP = 0
13
+ SCL_PIN = 228
14
+ SDA_PIN = 270
15
+ ADDRESS = 0x38
16
+
17
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
18
+ i2c_bb = LGPIO::I2CBitBang.new(chip_handle, SCL_PIN, SDA_PIN)
19
+
20
+ # Startup sequence
21
+ sleep(POWER_ON_DELAY)
22
+ i2c_bb.write(ADDRESS, SOFT_RESET)
23
+ sleep(RESET_DELAY)
24
+ i2c_bb.write(ADDRESS, INIT_AND_CALIBRATE)
25
+ sleep(COMMAND_DELAY)
26
+
27
+ # Read and close
28
+ i2c_bb.write(ADDRESS, START_MEASUREMENT)
29
+ sleep(MEASURE_DELAY)
30
+ bytes = i2c_bb.read(ADDRESS, DATA_LENGTH)
31
+
32
+ # Humidity uses the upper 4 bits of the shared byte as its lowest 4 bits.
33
+ h_raw = ((bytes[1] << 16) | (bytes[2] << 8) | (bytes[3])) >> 4
34
+ humidity = (h_raw.to_f / 2**20) * 100
35
+
36
+ # Temperature uses the lower 4 bits of the shared byte as its highest 4 bits.
37
+ t_raw = ((bytes[3] & 0x0F) << 16) | (bytes[4] << 8) | bytes[5]
38
+ temperature = (t_raw.to_f / 2**20) * 200 - 50
39
+
40
+ puts "#{Time.now.strftime '%Y-%m-%d %H:%M:%S'} - Temperature: #{temperature.round(2)} \xC2\xB0C | Humidity: #{humidity.round(2)} %"
@@ -0,0 +1,35 @@
1
+ require 'lgpio'
2
+
3
+ INIT_ARRAY = [0, 168, 63, 211, 0, 64, 161, 200, 218, 18, 164, 166, 213, 128, 219, 32, 217, 241, 141, 20, 32, 0, 175]
4
+ START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
5
+ PATTERN_1 = [64] + Array.new(1024) { 0b00110011 }
6
+ PATTERN_2 = [64] + Array.new(1024) { 0b11001100 }
7
+
8
+ GPIO_CHIP = 0
9
+ SCL_PIN = 228
10
+ SDA_PIN = 270
11
+ ADDRESS = 0x3C
12
+
13
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
14
+ i2c_bb = LGPIO::I2CBitBang.new(chip_handle, SCL_PIN, SDA_PIN)
15
+
16
+ i2c_bb.write(ADDRESS, INIT_ARRAY)
17
+ FRAME_COUNT = 400
18
+
19
+ start = Time.now
20
+ (FRAME_COUNT / 2).times do
21
+ i2c_bb.write(ADDRESS, START_ARRAY)
22
+ i2c_bb.write(ADDRESS, PATTERN_1)
23
+ i2c_bb.write(ADDRESS, START_ARRAY)
24
+ i2c_bb.write(ADDRESS, PATTERN_2)
25
+ end
26
+ finish = Time.now
27
+
28
+ LGPIO.chip_close(chip_handle)
29
+
30
+ fps = FRAME_COUNT / (finish - start)
31
+ # Also calculate C calls per second, using roughly 23 calls per byte written.
32
+ cps = (START_ARRAY.length + ((PATTERN_1.length + PATTERN_2.length) / 2) + 2) * 23 * fps
33
+ cps = (cps / 1000.0).round
34
+
35
+ puts "SSD1306 benchmark result: #{fps.round(2)} fps | #{cps}k C calls/s"
@@ -0,0 +1,40 @@
1
+ require 'lgpio'
2
+
3
+ POWER_ON_DELAY = 0.100
4
+ RESET_DELAY = 0.020
5
+ COMMAND_DELAY = 0.010
6
+ MEASURE_DELAY = 0.080
7
+ DATA_LENGTH = 6
8
+ SOFT_RESET = [0xBA]
9
+ INIT_AND_CALIBRATE = [0xE1, 0x08, 0x00]
10
+ START_MEASUREMENT = [0xAC, 0x33, 0x00]
11
+
12
+ GPIO_CHIP = 0
13
+ SCL_PIN = 228
14
+ SDA_PIN = 270
15
+ ADDRESS = 0x38
16
+
17
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
18
+ LGPIO.i2c_bb_claim(chip_handle, SCL_PIN, SDA_PIN)
19
+
20
+ # Startup sequence
21
+ sleep(POWER_ON_DELAY)
22
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, SOFT_RESET)
23
+ sleep(RESET_DELAY)
24
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, INIT_AND_CALIBRATE)
25
+ sleep(COMMAND_DELAY)
26
+
27
+ # Read and close
28
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, START_MEASUREMENT)
29
+ sleep(MEASURE_DELAY)
30
+ bytes = LGPIO.i2c_bb_read(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, DATA_LENGTH)
31
+
32
+ # Humidity uses the upper 4 bits of the shared byte as its lowest 4 bits.
33
+ h_raw = ((bytes[1] << 16) | (bytes[2] << 8) | (bytes[3])) >> 4
34
+ humidity = (h_raw.to_f / 2**20) * 100
35
+
36
+ # Temperature uses the lower 4 bits of the shared byte as its highest 4 bits.
37
+ t_raw = ((bytes[3] & 0x0F) << 16) | (bytes[4] << 8) | bytes[5]
38
+ temperature = (t_raw.to_f / 2**20) * 200 - 50
39
+
40
+ puts "#{Time.now.strftime '%Y-%m-%d %H:%M:%S'} - Temperature: #{temperature.round(2)} \xC2\xB0C | Humidity: #{humidity.round(2)} %"
@@ -0,0 +1,20 @@
1
+ require 'lgpio'
2
+
3
+ GPIO_CHIP = 0
4
+ SCL_PIN = 228
5
+ SDA_PIN = 270
6
+
7
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
8
+ LGPIO.i2c_bb_claim(chip_handle, SCL_PIN, SDA_PIN)
9
+
10
+ devices = LGPIO.i2c_bb_search(chip_handle, SCL_PIN, SDA_PIN)
11
+
12
+ if devices.empty?
13
+ puts "No devices found on I2C bus"
14
+ else
15
+ puts "I2C device addresses found:"
16
+ devices.each do |address|
17
+ # Print as hexadecimal.
18
+ puts "0x#{address.to_s(16).upcase}"
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ require 'lgpio'
2
+
3
+ INIT_ARRAY = [0, 168, 63, 211, 0, 64, 161, 200, 218, 18, 164, 166, 213, 128, 219, 32, 217, 241, 141, 20, 32, 0, 175]
4
+ START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
5
+ PATTERN_1 = [64] + Array.new(1024) { 0b00110011 }
6
+ PATTERN_2 = [64] + Array.new(1024) { 0b11001100 }
7
+
8
+ GPIO_CHIP = 0
9
+ SCL_PIN = 228
10
+ SDA_PIN = 270
11
+ ADDRESS = 0x3C
12
+
13
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
14
+ LGPIO.i2c_bb_claim(chip_handle, SCL_PIN, SDA_PIN)
15
+
16
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, INIT_ARRAY)
17
+ FRAME_COUNT = 400
18
+
19
+ start = Time.now
20
+ (FRAME_COUNT / 2).times do
21
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, START_ARRAY)
22
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, PATTERN_1)
23
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, START_ARRAY)
24
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, PATTERN_2)
25
+ end
26
+ finish = Time.now
27
+
28
+ LGPIO.chip_close(chip_handle)
29
+
30
+ fps = FRAME_COUNT / (finish - start)
31
+ # Also calculate C calls per second, using roughly 23 calls per byte written.
32
+ cps = (START_ARRAY.length + ((PATTERN_1.length + PATTERN_2.length) / 2) + 2) * 23 * fps
33
+ cps = (cps / 1000.0).round
34
+
35
+ puts "SSD1306 benchmark result: #{fps.round(2)} fps | #{cps}k C calls/s"
@@ -1,21 +1,22 @@
1
1
  require 'lgpio'
2
2
 
3
- I2C_DEV = 2
3
+ I2C_DEV = 3
4
+ ADDRESS = 0x3C
4
5
  INIT_ARRAY = [0, 168, 63, 211, 0, 64, 161, 200, 218, 18, 164, 166, 213, 128, 219, 32, 217, 241, 141, 20, 32, 0, 175]
5
6
  START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
6
- BLANK_ARRAY = [64] + Array.new(1024) { 0 }
7
- FILL_ARRAY = [64] + Array.new(1024) { 255 }
7
+ PATTERN_1 = [64] + Array.new(1024) { 0b00110011 }
8
+ PATTERN_2 = [64] + Array.new(1024) { 0b11001100 }
8
9
 
9
- ssd1306_handle = LGPIO.i2c_open(I2C_DEV, 0x3C, 0)
10
+ ssd1306_handle = LGPIO.i2c_open(I2C_DEV, ADDRESS, 0)
10
11
  LGPIO.i2c_write_device(ssd1306_handle, INIT_ARRAY)
11
12
  FRAME_COUNT = 100
12
13
 
13
14
  start = Time.now
14
15
  (FRAME_COUNT / 2).times do
15
16
  LGPIO.i2c_write_device(ssd1306_handle, START_ARRAY)
16
- LGPIO.i2c_write_device(ssd1306_handle, FILL_ARRAY)
17
+ LGPIO.i2c_write_device(ssd1306_handle, PATTERN_1)
17
18
  LGPIO.i2c_write_device(ssd1306_handle, START_ARRAY)
18
- LGPIO.i2c_write_device(ssd1306_handle, BLANK_ARRAY)
19
+ LGPIO.i2c_write_device(ssd1306_handle, PATTERN_2)
19
20
  end
20
21
  finish = Time.now
21
22
 
@@ -0,0 +1,22 @@
1
+ require 'lgpio'
2
+
3
+ FREQUENCY = 38_000
4
+
5
+ # NEC Raw-Data=0xF708FB04. LSBFIRST, so the binary for each hex digit below is backward.
6
+ CODE = [ 9000, 500, # Start bit
7
+ 560, 560, 560, 560, 560, 1690, 560, 560, # 0010 0x4 command
8
+ 560, 560, 560, 560, 560, 560, 560, 560, # 0000 0x0 command
9
+ 560, 1690, 560, 1690, 560,560, 560, 1690, # 1101 0xB command inverted
10
+ 560, 1690, 560, 1690, 560, 1690, 560, 1690, # 1111 0xF command inverted
11
+ 560, 560, 560, 560, 560, 560, 560, 1690, # 0001 0x8 address
12
+ 560, 560, 560, 560, 560, 560, 560, 560, # 0000 0x0 address
13
+ 560, 1690, 560, 1690, 560, 1690, 560, 560, # 1110 0x7 address inverted
14
+ 560, 1690, 560, 1690, 560, 1690, 560, 1690, # 1111 0xF address inverted
15
+ 560] # Stop bit
16
+
17
+ infrared = LGPIO::Infrared.new(0, 2, frequency: FREQUENCY)
18
+
19
+ loop do
20
+ infrared.transmit(CODE)
21
+ sleep 1
22
+ end
@@ -1,8 +1,8 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- BUTTON = 258
5
- LED = 260
4
+ BUTTON = 259
5
+ LED = 272
6
6
 
7
7
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
8
8
  LGPIO.gpio_claim_input(chip_handle, LGPIO::SET_PULL_UP, BUTTON)
@@ -0,0 +1,30 @@
1
+ require 'lgpio'
2
+
3
+ GPIO_CHIP = 0
4
+ PIN = 256
5
+ PARASITE = false
6
+
7
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
8
+ one_wire = LGPIO::OneWire.new(chip_handle, PIN)
9
+
10
+ one_wire.reset
11
+ # Skip ROM
12
+ one_wire.write([LGPIO::OneWire::SKIP_ROM], parasite: PARASITE)
13
+ # Start conversion
14
+ one_wire.write([LGPIO::OneWire::CONVERT_T], parasite: PARASITE)
15
+ # Wait for conversion
16
+ sleep(1)
17
+ # Reset
18
+ one_wire.reset
19
+ # Skip ROM
20
+ one_wire.write([LGPIO::OneWire::SKIP_ROM], parasite: PARASITE)
21
+ # Read 9 bytes from scratchpad
22
+ one_wire.write([LGPIO::OneWire::READ_SCRATCH], parasite: PARASITE)
23
+ bytes = one_wire.read(9)
24
+
25
+ # Temperature is the first 16 bits (2 bytes of 9 read).
26
+ # It's a signed, 2's complement, little-endian decimal. LSB = 2 ^ -4.
27
+ #
28
+ temperature = bytes[0..1].pack('C*').unpack('s<')[0] * (2.0 ** -4)
29
+
30
+ puts "DS18B20 reading: #{temperature} \xC2\xB0C"
@@ -0,0 +1,15 @@
1
+ require 'lgpio'
2
+
3
+ GPIO_CHIP = 0
4
+ PIN = 256
5
+
6
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
7
+ one_wire = LGPIO::OneWire.new(chip_handle, PIN)
8
+ one_wire.search
9
+
10
+ puts; puts "Found these 1-wire addresss (HEX) on the bus:"; puts
11
+
12
+ one_wire.found_addresses.each do |address|
13
+ puts address.to_s(16)
14
+ end
15
+ puts
data/examples/pwm.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- LED = 260
4
+ LED = 272
5
5
  PWM_FREQ = 500
6
6
  PWM_OFFSET = 0
7
7
  PWM_CYCLES = 0 # 0 = infinite
data/examples/reports.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- PIN = 76
4
+ PIN = 259
5
5
 
6
6
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
7
7
 
@@ -5,9 +5,9 @@
5
5
  require 'lgpio'
6
6
 
7
7
  GPIO_CHIP = 0
8
- PIN_A = 76
9
- PIN_B = 228
10
- PIN_SW = 226
8
+ PIN_A = 260
9
+ PIN_B = 76
10
+ PIN_SW = 259
11
11
 
12
12
  # Encoder state
13
13
  position = 0
@@ -5,10 +5,10 @@
5
5
  require 'lgpio'
6
6
 
7
7
  GPIO_CHIP = 0
8
- PIN_A = 76
9
- PIN_B = 228
8
+ PIN_A = 260
9
+ PIN_B = 76
10
10
 
11
- PIN_LED = 260
11
+ PIN_LED = 272
12
12
  PWM_FREQ = 500
13
13
  PWM_OFFSET = 0
14
14
  PWM_CYCLES = 0 # 0 = infinite
@@ -44,7 +44,7 @@ loop do
44
44
  elsif report[:gpio] == PIN_B
45
45
  delta = (report[:level] == state_a) ? -1 : 1
46
46
  state_b = report[:level]
47
-
47
+
48
48
  led_duty += delta
49
49
  led_duty = 0 if led_duty < 0
50
50
  led_duty = 100 if led_duty > 100
data/examples/servo.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'lgpio'
2
+ #
3
+ # Writing directly to a hardware PWM channel to control a servo.
4
+ # Arguments in order are:
5
+ # pwmchip index (X in /sys/class/pwm/pwmchipX/)
6
+ # PWM channel on the chip (Y in /sys/class/pwm/pwmchipX/pwmY)
7
+ # period: given in nanoseconds
8
+ # OR frequency: given in Hz
9
+ #
10
+ servo = LGPIO::HardwarePWM.new(0, 1, period: 20_000_000)
11
+ #
12
+ # Duty cycle is given in nanoseconds by default. Extra setter methods
13
+ # are provided for microseconds, and percent.
14
+ #
15
+ # servo.duty_percent = 2.5
16
+ # servo.duty_us = 500
17
+ servo.duty = 500_000
18
+
19
+ #
20
+ # Using the Servo class instead.
21
+ # Arguments in order are:
22
+ # pwmchip index (X in /sys/class/pwm/pwmchipX/)
23
+ # PWM channel on the chip (Y in /sys/class/pwm/pwmchipX/pwmY)
24
+ # Minimum servo duty cycle in microseconds
25
+ # Maximum servo duty cicle in microseconds
26
+ # Minimum servo angle
27
+ # Maximum servo angle
28
+ #
29
+ servo = LGPIO::PositionalServo.new(0, 1, 500, 2500, 0, 180)
30
+
31
+ angles = [0, 30, 60, 90, 120, 150, 180, 150, 120, 90, 60, 30]
32
+
33
+ angles.cycle do |angle|
34
+ servo.angle = angle
35
+ sleep 1
36
+ end