Ultrasonic Sensor USB Serial Python

AJ-SR04M

How’s it going. I’m going to try and limit this for simplicity. I am a student studying EE. I have an UltraSonic Sensor connected using USB Serial Port CH340. I have tried to look for a python script that could give the distance but it seems it’s not possible. Any help or guidance is greatly appreciated. I’m just lost and don’t know where to turn to

See if it serves as a guide for you

1 Like

the AJ-SR04M has a automatic serial mode - you may be able to read bytes using pyserial
[/quote] and determine the distance reading

You have to install pyserial library and write a code like the following:

import serial
import time

# Set up the serial connection
ser = serial.Serial('COM3', 9600, timeout=1)  # Replace 'COM3' with your port, or '/dev/ttyUSB0' for Linux
time.sleep(2)  # Wait for the connection to initialize

def read_distance():
    if ser.in_waiting > 0:
        data = ser.readline().decode('utf-8').rstrip()  # Read the data from the sensor
        try:
            distance = float(data)  # Convert to float if valid
            print(f"Distance: {distance} cm")
        except ValueError:
            print("Invalid data received")  # Handle non-numeric data

try:
    while True:
        read_distance()
        time.sleep(0.1)  # Small delay between readings
except KeyboardInterrupt:
    print("Stopping...")
finally:
    ser.close()  # Close the serial connection

If you choose to use something simpler, you can try the ordinary HCSR04: Introduction to HC-SR04 (Ultrasonic Sensor) - The Engineering Projects

Hey, @MaximoEsfuerzo I did look into this I currently have it set up on Mode 5 as the guide and have it reading with a serial analyzer but when I use this script. It doesn't work

import serial
import time
import sys
ser = serial.Serial('/dev/ttyUSB0')  # open serial port
byte = b'\xff' # xff is the start byte
while True:
    x = ser.read()
    if x == byte: #starbyte found
        b1 = ser.read(1)
        b2 = ser.read(1)
        x1 = int.from_bytes(b1, sys.byteorder)
        dist = (((x1 << 8) + int.from_bytes(b2, sys.byteorder)) / 10) # some bitshift magic, no idea what's happening here
        print(dist - 5) # for some reason the distance value is 5cm off, remove them before printing the value
        clear = ser.read_all()
        ser.flushOutput()
    time.sleep(2)

Hey @horace so I have the AJ-SR04M set up in mode 5 from this article. But when I try to write the python code to read distance data it returns nothing. Not sure if my code is incorrect.

@aliarifat794 I already had PySerial installed. I also tried your code and it doesn't work but I also made my own script and it also doesn't work could it be I don't have the USB serial port configured correctly? I have this USB TTL HW597 from electrodes. I have attached the script I made

https://electrobes.com/product/ch-340-usb-to-ttl-serial-hw-597-converter-module/

import serial
import time
import sys
ser = serial.Serial('/dev/ttyUSB0')  # open serial port
byte = b'\xff' # xff is the start byte
while True:
    x = ser.read()
    if x == byte: #starbyte found
        b1 = ser.read(1)
        b2 = ser.read(1)
        x1 = int.from_bytes(b1, sys.byteorder)
        dist = (((x1 << 8) + int.from_bytes(b2, sys.byteorder)) / 10) # some bitshift magic, no idea what's happening here
        print(dist - 5) # for some reason the distance value is 5cm off, remove them before printing the value
        clear = ser.read_all()
        ser.flushOutput()
    time.sleep(2)

Your code is stuck with this command.

yes because it needs to read the distance continuously, that's why I have it there, and it does read the distance but the numbers are not accurate at all maybe like 2 out 20 reads are good.

I don't know why you ask questions here if you are not going to pay any attention to the advice you receive?

So I will not bother you again with advice and I am putting this thread on mute, so I will not see anything more you post.

Good luck with your project, and goodbye.

Topic moved !! Please do not post in "Uncategorized"; see the sticky topoics in https://forum.arduino.cc/c/using-arduino/uncategorized/184.

this is an example using ESP32 serial reading distance from a jsn_sr04m - may give you some ideas

// ESP32 serial2 reading jsn_sr04t ultrasonic transducer

// device is labled "RCWL-1655"
// https://makerhero.com/img/files/download/RCWL-1655-Datasheet.pdf

#define RXD2 16  // set default Serial2
#define TXD2 17

void setup() {
  Serial.begin(115200);
  //  setting pins is required - just using defaults does not work
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
  Serial.println("ESP32 jsn_sr04t ultrasonic transducer");
  Serial.println("Serial2 Txd is on pin: " + String(TXD2));
  Serial.println("Serial2 Rxd is on pin: " + String(RXD2));
  readInformation();    // display Device information
}

// display Device information
void readInformation(void) {                   //Choose Serial1 or Serial2 as required
  while (Serial2.available()) Serial2.read();  // flush Serial2 buffer
  Serial.println("Device information ");
  Serial2.print(char(0xF1));      // send command to read Device information
  delay(100);
  while (Serial2.available()) {   // display information
    Serial.print(char(Serial2.read()));
  }
}

// read continuous distance 
void loop() {
  while (Serial2.available()) Serial2.read();  // flush Serial2 buffer
  Serial2.write((0xA0));                       // read distance command
  delay(100);                                  // delay while it transmits and gets echo
  int h, w, l;                                 // read three bytes
  h = Serial2.read();
  w = Serial2.read();
  l = Serial2.read();
  int distance = ((h << 16) + (w << 8) + l) / 1000;  // calculate distance
  Serial.print("distance ");
  Serial.println(distance);
  delay(2000);
}

serial monitor output displays device information then distance to objects as I move the sensor around

ESP32 jsn_sr04t ultrasonic transducer
Serial2 Txd is on pin: 17
Serial2 Rxd is on pin: 16
Device information 
�����ճ�����RCWL-9631distance 1730
distance 1733
distance 1730
distance 1729
distance 1691
distance 536
distance 440
distance 352
distance 194
distance 296
distance 398
distance 515
distance 1725
distance 1729
distance 1728
distance 1728

photo

I think there are different versions of the jsn_sr04m which use different PCBs and data format

will see if I can implement a Python version

Python version running on Windows PC

# terminal.py - jsn_sr04t ultrasonic transducer

import serial
import sys
import msvcrt
import time
from time import sleep

serialPort = serial.Serial(
    port="COM24", baudrate=9600, bytesize=8, timeout=1, stopbits=serial.STOPBITS_ONE
)
serialPort.rtscts = False
serialPort.xonxoff = False
serialPort.dsrdtr = False 
sys.stdout.write("Python jsn_sr04t ultrasonic transducer\n")
# display Device information
sys.stdout.write("Device information ");
command = b'\xF1' # character in hex
serialPort.write(command)  # read Device information
sleep(0.1)     # delay 100mSec
while serialPort.in_waiting > 0:
         char = serialPort.read()
         #sys.stdout.write("\nreceived ")
         if ord(char) < 128:
             sys.stdout.write(str(char,'ASCII'))
# loop reading continuous distance 
print("\nreading distances")
while 1:
    sleep(1)
    command = b'\xA0'          # read distance command
    serialPort.write(command)  # read distance
    sleep(0.1)                 # delay 100mSec
    # read three bytes convert to integer
    h = int.from_bytes(serialPort.read())
    w = int.from_bytes(serialPort.read())
    l = int.from_bytes(serialPort.read())
    # calculate distance
    distance = ((h << 16) + (w << 8) + l) / 1000
    print(f'Distance {distance}');
;

shell displays

Python 3.11.1 (tags/v3.11.1:a7a450f, Dec  6 2022, 19:58:39) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.

= RESTART: F:/Ardunio/Networking/WiFi/ESP32/sensors/Ultrasonic sensor/terminal_3.py
Python jsn_sr04t ultrasonic transducer
Device information RCWL-9631
reading distances
Distance 1733.722
Distance 1733.722
Distance 1733.722
Distance 7954.742
Distance 478.734
Distance 440.99
Distance 430.88
Distance 434.924
Distance 520.522
Distance 651.952
Distance 495.584
Distance 562.984
Distance 423.466
Distance 291.362
Distance 391.788
Distance 1635.318
Distance 829.214
Distance 837.302
Distance 1737.092
Distance 1737.092
Distance 1737.092

jsn_sr04t connected to PC using a FTDI TTL-232R-3.3V cable

Hey @horace so I tried your code switched the COM to my respective port.

serialPort = serial.Serial(
    port="COM6", baudrate=9600, bytesize=8, timeout=1, stopbits=serial.STOPBITS_ONE
)

But I still get the inconsistent data I believe it might be a faulty sensor or a faulty set up

Python aj_sr04m ultrasonic transducer
Device information Gap=468mm

reading distances
Distance 4678.0
Distance 4011.061
Distance 3566.957
Distance 854.599
Distance 6385.725
Distance 3421.748

Here is my set up I have the sensor connected to the usb using wires connected to TX --> RXD and RX --> TXD. I also have the sensor on mode 5 per this forums instructions.

How to Communicate Waterproof Ultrasonic Sensor AJ-SR04M/JSN-SR04T with Arduino/ESP32 – Probots Blog

Is there anything I'm missing or anything going over my head. I'm not sure if it's the sensor or something I'm doing wrong. I tried it using a raspberry pico w and it worked so I don't believe it's the sensor. Any help is appreciated. Thank You all who have contributed

can you post the Pico code?

the sensor I am using is labeled RCWL-1655

I soldered a 10Kohm resistor across the R7 pads to enable the UART

I understand that there are different versions of the jsn_sr04m - the one I have uses a 24bit distance (3 bytes) but there are 16bit versions and 24bit versions which use 4byte (3data+checksum)

if yours has a checksum you need to read it otherwise you may read it as part of the next data bytes and get results like you have in post 14

do you have a link to your jsn_sr04m ?

I currently don't have a picture of the Raspberry Pico W with me because I left it at friend's house but it's just a standard one looks something like this. I used GPIO pins to connect trig and echo and copied and pasted sample ultrasonic sensor code to get the distance and it worked.
Pico-series Microcontrollers - Raspberry Pi Documentation

Here's the code I used to test the sensor:

from machine import Timer,Pin, PWM, ADC
#from machine import time_pulse_us
import time, array
import math

#This moves the servo to different angles

class Ultrasonic():
    # Define output(trig) and input(echo) pins.
    def __init__(self, trig, echo):
        self._trig = Pin(trig, Pin.OUT)
        self._echo = Pin(echo, Pin.IN)
    
    def get_distance(self):
        # Generate 10us square wave.
        self._trig.low()
        time.sleep_us(2)
        self._trig.high()
        time.sleep_us(10)
        self._trig.low()
        while self._echo.value() == 0:
            start = time.ticks_us()
        while self._echo.value() == 1:
            end = time.ticks_us()
        dis = (end - start) * 0.0343 / 2
        # round to two decimal places.
        return round(dis, 2)
    
if __name__ == '__main__':
    # Ultrasonic pins. trig:GPIO3, echo:GPIO2
    ultrasonic = Ultrasonic(4,5)
    while True:
        value = ultrasonic.get_distance()
        print("Distance: {:.2f}cm" .format(value))
        time.sleep(1)
        

Here is the datasheet/manual for the ultrasonic sensor. I'm using. ARDUINO AJ-SR04M Distance Measuring Transducer Sensor User Manual

I short circuit the R19 to get Mode 5: ASCII Code output (Minimum Power Consumption 20uA)

clearly your jsn_sr04m is different from mine
the document referenced in post 16 does not mention the serial format
it is probably 3data bytes + checksum
possibly you read a block of four bytes, calculate the checksum and if it is correct you have the distance if not discard first byte and calculate again

I believe I found what you are referring to. I'm not sure how I could write the data bytes to accurately reflect the distance in a python script

any idea what is the value of the start byte?
possibly print out 20 or 30 bytes (in HEX) to give us some idea of the format?

Edit: try

# print bytes in hex

import serial
import sys
import msvcrt
import time
from time import sleep

serialPort = serial.Serial(
    port="COM12", baudrate=9600, bytesize=8, timeout=1, stopbits=serial.STOPBITS_ONE
)
serialPort.rtscts = False
serialPort.xonxoff = False
serialPort.dsrdtr = False 
sys.stdout.write("Python jsn_sr04t ultrasonic transducer\n")
i=0
while i<30:
   while serialPort.in_waiting > 0:
         char = serialPort.read()
         hex_string = char.hex()
         print(hex_string)
         i=i+1

prints something like

21
21
4c
4e
a5
ab
ad
9a
2c
84
a5
e2
dd
00
01
02
03
04
05
06
1 Like

The code only printed out

Python jsn_sr04t ultrasonic transducer

but I did find this video which explains the bytes in hex. He said the start byte is #FF not sure if this helps

Distance Measurement / Ultrasonic Sensor / AJ-SR04M - YouTube