diff --git a/HARDWARE.md b/HARDWARE.md index 9c6f0e4..20df0a6 100644 --- a/HARDWARE.md +++ b/HARDWARE.md @@ -224,7 +224,7 @@ Polling and reading follow a call and response pattern. | Name | Status | Interface | Component Class | Notes | | :--------------- | :------: | :-------- | :--------------- |------ | -| HC-SR04 | :heart: | Digi In/Out | `Sensor::HCSR04` | Ultrasonic, 20-4000mm +| HC-SR04 | :green_heart: | Digi In/Out | `Sensor::HCSR04` | Ultrasonic, 20-4000mm | RCWL-9620 | :green_heart: | I2C | `Sensor::RCWL9260` | Ultrasonic, 20-4500mm | VL53L0X | :heart: | I2C | `Sensor::VL53L0X` | Laser, 30 - 1000mm | GP2Y0E03 | :heart: | I2C | `Sensor::GP2Y0E03` | Infrared, 40 - 500mm diff --git a/examples/sensor/hcsr04.rb b/examples/sensor/hcsr04.rb new file mode 100644 index 0000000..5ba64a0 --- /dev/null +++ b/examples/sensor/hcsr04.rb @@ -0,0 +1,14 @@ +# +# Example of reading an HC-SR04 ultrasonic sensor. +# +require 'bundler/setup' +require 'denko' + +board = Denko::Board.new(Denko::Connection::Serial.new) +hcsr04 = Denko::Sensor::HCSR04.new(board: board, pins: {trigger: 6, echo: 7}) + +hcsr04.poll(0.05) do |distance| + puts "Distance: #{distance} mm" +end + +sleep diff --git a/lib/denko/board/pulse.rb b/lib/denko/board/pulse.rb index 1d4b5d8..693c20c 100644 --- a/lib/denko/board/pulse.rb +++ b/lib/denko/board/pulse.rb @@ -22,5 +22,9 @@ def pulse_read(pin, reset: false, reset_time: 0, pulse_limit: 100, timeout: 200) value: settings, aux_message: aux end + + def hcsr04_read(echo_pin, trigger_pin) + write Message.encode(command: 20, pin: echo_pin, value: trigger_pin) + end end end diff --git a/lib/denko/sensor.rb b/lib/denko/sensor.rb index e844f41..3b2b028 100644 --- a/lib/denko/sensor.rb +++ b/lib/denko/sensor.rb @@ -14,6 +14,7 @@ module Sensor autoload :SHT3X, "#{__dir__}/sensor/sht3x" autoload :QMP6988, "#{__dir__}/sensor/qmp6988" autoload :RCWL9620, "#{__dir__}/sensor/rcwl9620" + autoload :HCSR04, "#{__dir__}/sensor/hcsr04" autoload :GenericPIR, "#{__dir__}/sensor/generic_pir" end end diff --git a/lib/denko/sensor/hcsr04.rb b/lib/denko/sensor/hcsr04.rb new file mode 100644 index 0000000..56a5cd4 --- /dev/null +++ b/lib/denko/sensor/hcsr04.rb @@ -0,0 +1,33 @@ +module Denko + module Sensor + class HCSR04 + # Speed of sound in meters per second. + SPEED_OF_SOUND = 343.0 + + include Behaviors::MultiPin + include Behaviors::Poller + + def initialize_pins(options={}) + proxy_pin :trigger, DigitalIO::Output + proxy_pin :echo, DigitalIO::Input + end + + def after_initialize(options={}) + super(options) + + # Receive values from echo pin. + echo.add_callback { |data| self.update(data) } + end + + def _read + board.hcsr04_read(echo.pin, trigger.pin) + end + + def pre_callback_filter(us) + # Data is microseconds roundtrip time. Convert to mm. + um = (us/2) * SPEED_OF_SOUND + mm = um / 1000.0 + end + end + end +end diff --git a/src/lib/Denko.cpp b/src/lib/Denko.cpp index 1ecaa31..96ee44d 100644 --- a/src/lib/Denko.cpp +++ b/src/lib/Denko.cpp @@ -122,7 +122,8 @@ void Denko::process() { #endif // Implemented in DenkoPulseInput.cpp - case 9: pulseRead (); break; + case 9: pulseRead (); break; + case 20: hcsr04Read (); break; // Implemented in DenkoServo.cpp #ifdef DENKO_SERVO diff --git a/src/lib/Denko.h b/src/lib/Denko.h index 6d483fc..ef59819 100644 --- a/src/lib/Denko.h +++ b/src/lib/Denko.h @@ -95,8 +95,9 @@ class Denko { void eepromRead (); //cmd = 7 void eepromWrite (); //cmd = 8 - // Included Libraries + // Pulse inputs (DHT and HC-SR04) void pulseRead (); //cmd = 9 + void hcsr04Read (); //cmd = 20 // Servos void servoToggle (); //cmd = 10 diff --git a/src/lib/DenkoPulseInput.cpp b/src/lib/DenkoPulseInput.cpp index 1a5e2f3..bc9925b 100644 --- a/src/lib/DenkoPulseInput.cpp +++ b/src/lib/DenkoPulseInput.cpp @@ -55,3 +55,34 @@ void Denko::pulseRead(){ } if (pulseCount == 0) stream->print('\n'); } + +// CMD = 20 +// +// pin : echo pin +// val (lower 8 bits) : trigger pin +// +void Denko::hcsr04Read(){ + // Store number of microseconds to return. + uint32_t us; + + // Ensure pins are correct direction. + // This is handled by modeling the sensor as a multipin component instead. + // pinMode(pin, INPUT); + // pinMode(val, OUTPUT); + + // Initial pulse on the triger pin. + digitalWrite(val, LOW); + microDelay(2); + digitalWrite(val,HIGH); + microDelay(10); + digitalWrite(val,LOW); + + // Wait for the echo, up to 25,000 microseconds. + us = pulseIn(pin, HIGH, 25000); + + // Send value. + stream->print(pin); + stream->print(':'); + stream->print(us); + stream->print('\n'); +}