From 21736e9fa1300772d1a8db22e27cb75543751dcb Mon Sep 17 00:00:00 2001 From: vickash Date: Sun, 3 Nov 2024 20:33:41 -0400 Subject: [PATCH] Driver for JSN-SR04T waterproof ultrasonic sensor --- HARDWARE.md | 3 +- examples/sensor/jsnsr04t.rb | 15 ++++++++++ lib/denko/sensor.rb | 1 + lib/denko/sensor/jsnsr04t.rb | 53 ++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 examples/sensor/jsnsr04t.rb create mode 100644 lib/denko/sensor/jsnsr04t.rb diff --git a/HARDWARE.md b/HARDWARE.md index 4eb6a75..01628c5 100644 --- a/HARDWARE.md +++ b/HARDWARE.md @@ -128,7 +128,7 @@ Polling and reading follow a call and response pattern. | 7 Segment Display | :yellow_heart: | Digital Out | `LED::SevenSegment` | No decimal point | 8x8 LED (MAX7219) | :heart: | SPI | `LED::MAX7219` | | TM1637 | :heart: | BitBang SPI | `LED::TM1637` | 4x 7 Segment + Colon -| Neopixel / WS2812B | :yellow_heart: | Adafruit Library | `LED::WS2812` | Not working on RP2040 +| Neopixel / WS2812B | :green_heart: | Adafruit Library | `LED::WS2812` | | Dotstar / APA102 | :green_heart: | SPI | `LED::APA102` | ### Displays @@ -226,6 +226,7 @@ Polling and reading follow a call and response pattern. | :--------------- | :------: | :-------- | :--------------- |------ | | HC-SR04 | :green_heart: | Digi In/Out | `Sensor::HCSR04` | Ultrasonic, 20-4000mm | RCWL-9620 | :green_heart: | I2C | `Sensor::RCWL9260` | Ultrasonic, 20-4500mm +| JSN-SR04T | :green_heart: | UART | `Sensor::JSNSR04T` | Mode 2 ONLY. Use HC-SR04 driver for mode 0 or 4. | VL53L0X | :heart: | I2C | `Sensor::VL53L0X` | Laser, 30 - 1000mm | GP2Y0E03 | :heart: | I2C | `Sensor::GP2Y0E03` | Infrared, 40 - 500mm diff --git a/examples/sensor/jsnsr04t.rb b/examples/sensor/jsnsr04t.rb new file mode 100644 index 0000000..7d3dcd1 --- /dev/null +++ b/examples/sensor/jsnsr04t.rb @@ -0,0 +1,15 @@ +# +# Example of reading a JSN-SR04T ultrasonic sensor, in mode 2. +# +require 'bundler/setup' +require 'denko' + +board = Denko::Board.new(Denko::Connection::Serial.new) +uart = Denko::UART::Hardware.new(board: board, index: 1, baud: 9600) +ultrasonic = Denko::Sensor::JSNSR04T.new(board: board, uart: uart) + +ultrasonic.poll(1) do |distance| + puts "Distance: #{distance} mm" +end + +sleep diff --git a/lib/denko/sensor.rb b/lib/denko/sensor.rb index 8c92269..cafb0de 100644 --- a/lib/denko/sensor.rb +++ b/lib/denko/sensor.rb @@ -14,6 +14,7 @@ module Sensor autoload :QMP6988, "#{__dir__}/sensor/qmp6988" autoload :RCWL9620, "#{__dir__}/sensor/rcwl9620" autoload :HCSR04, "#{__dir__}/sensor/hcsr04" + autoload :JSNSR04T, "#{__dir__}/sensor/jsnsr04t" autoload :GenericPIR, "#{__dir__}/sensor/generic_pir" end end diff --git a/lib/denko/sensor/jsnsr04t.rb b/lib/denko/sensor/jsnsr04t.rb new file mode 100644 index 0000000..2b8476c --- /dev/null +++ b/lib/denko/sensor/jsnsr04t.rb @@ -0,0 +1,53 @@ +module Denko + module Sensor + # + # For JSN-SR04T sensor in mode 2 ONLY. + # + class JSNSR04T + include Behaviors::Component + include Behaviors::Lifecycle + include Behaviors::Poller + + UART_CLASSES = [Denko::UART::Hardware, Denko::UART::BitBang] + TIMEOUT = 0.500 + MATCHER = /(\d*)mm/ + + attr_reader :uart + + after_initialize do + unless (params[:uart] && UART_CLASSES.include?(params[:uart].class)) + raise ArgumentError, "JSN-SR04T driver only works in mode 2, and expects a UART in the :uart key" + end + + raise StandardError, "UART baud must be 9600 for JSN-SR04T" unless params[:uart].baud == 9600 + + @uart = params[:uart] + end + + def _read + # Trigger read + uart.write("U") + sleep 0.100 + + # Get line from UART + start = Time.now + line = nil + until line || (Time.now - start > TIMEOUT) + line = uart.gets + sleep 0.010 + end + + # Extract mm as integer + if line && match = line.match(MATCHER) + value = match[1].to_i + if value + self.update(value) + return value + end + else + return nil + end + end + end + end +end