A02YYUW Waterproof Ultrasonic Sensor

Does anyone know if there is a homemade Pi Pico library for this sensor?
The manufacturer has replied that they have not made a library for it.
The sensor is: A02YYUW Waterproof Ultrasonic Sensor from DFROBOT

EDIT: just noticed you wanted this for a Pi :astonished:. So the below info may only be useful as a reference for writing your own Pi version.

Then I found this on the wiki:


Didnā€™t find a library but you may not need one.

The wiki for this device is here: A02YYUW Waterproof Ultrasonic Sensor Wiki - DFRobot

The sample code on the wiki looks straightforward enough to get you going and create a base to modify from.

Here is some more help on using this sensor: Waterproof Ultrasonic Distance Sensors - JSN-SR04T & A02YYUW šŸ’§ā˜” - YouTube
This sensors section starts at about 21:15
The sketch used for this video is at: Waterproof Ultrasonic Distance Sensors with Arduino

Code from wiki:

/*
  *@File  : DFRobot_Distance_A02.ino 
  *@Brief : This example use A02YYUW ultrasonic sensor to measure distance
  *         With initialization completed, We can get distance value 
  *@Copyright [DFRobot](https://www.dfrobot.com),2016         
  *           GUN Lesser General Pulic License
  *@version V1.0           
  *@data  2019-8-28
*/

#include <SoftwareSerial.h>

SoftwareSerial mySerial(11,10); // RX, TX
unsigned char data[4]={};
float distance;

void setup()
{
 Serial.begin(57600);
 mySerial.begin(9600); 
}

void loop()
{
    do{
     for(int i=0;i<4;i++)
     {
       data[i]=mySerial.read();
     }
  }while(mySerial.read()==0xff);

  mySerial.flush();

  if(data[0]==0xff)
    {
      int sum;
      sum=(data[0]+data[1]+data[2])&0x00FF;
      if(sum==data[3])
      {
        distance=(data[1]<<8)+data[2];
        if(distance>30)
          {
           Serial.print("distance=");
           Serial.print(distance/10);
           Serial.println("cm");
          }else 
             {
               Serial.println("Below the lower limit");
             }
      }else Serial.println("ERROR");
     }
     delay(100);
}
3 Likes

ā€¦I am speechless, - thank you very much for your answer. I just started with my first Pi Pico Kit and feel like a little boy while my wife shakes her head mildly.
Iā€™m trying to make it work, it will be fine. I could get the included ultrasonic sensor from the set to show values on my display, but it does not run UART like the waterproof one I have trouble with.
Many thanks and I will report back. :+1:

1 Like

Note the RPi library above.

Iā€™ve been to this wiki before and have seen all the impressive videos, but all I find is only for the RPi and not for the RPi Pico. Another problem I have is that I have started my ā€œnew careerā€ with Micropython and cannot translate (yet) from other programming languages/systems. (I tried ChatGPT and am very impressed, but the translation to Micropython did not work as expected)
In the link to the RPi library it says that only Pi-1-2-3-4 is supported, nothing about Pico, unfortunately.

Iā€™ll have to wait until Iā€™ve gotten a little wiser with all the new programming :wink:

However, I greatly appreciate your kind help.

1 Like

Just for fun and learning, I asked Bard to create code for this sensor.

Note: I do not write MicroPython


Sure, here is some MicroPython code for the PI Pico that will read a A02YYUW Waterproof Ultrasonic Sensor:

import machine

# Define the pins for the ultrasonic sensor
trig_pin = 25
echo_pin = 26

# Initialize the ultrasonic sensor
sensor = machine.UltrasonicSensor(trig_pin, echo_pin)

# Start the main loop
while True:

    # Get the distance from the sensor
    distance = sensor.distance

    # Print the distance
    print("Distance:", distance)

    # Wait for a second
    machine.sleep(1)

I used ShatGPT and got several suggestions, but just like what you came up with, my AI suggestions donā€™t work either.
If I start from a normal HC-SR04, everything works fine. But generating the code to be able to use a A02YYUW Waterproof Ultrasonic Sensor instead fails. I think Iā€™m missing all that UART stuff and the necessary library.
At least I can hear that the sensor is working, only ā€œthe restā€ is missing :wink:
The library (GitHub - DFRobot/DFRobot_RaspberryPi_A02YYUW) for this sensor ā€œdoesnā€™t fitā€ my Pi Pico W with Thonny and Micropython.
And as I wrote a little before, I walk in the dark, just started with Lesson 10 from Paul McWhorter - YouTube. He is an interesting guy and does a very good job of explaining and teaching.
I hope that around lesson 50 I have understood the most important thingā€¦.

BTW, Iā€™ve been playing with ShatGPT quite a bit and donā€™t know if I should be more fascinated or scared.

I just noticed that Bard generated code for a HC-SRO4 style sensor not the A02YYUW style which is a serial output.
You should be able to reference any PiPico code that interfaces with a serial device and modify it to work with this sensor.

Thanks Don, thatā€™s the way I want to go. I will succeed one day. :wink:

1 Like

Looks like it sends 4 bytes of data on the serial bus continuously. Therefore one would look for the Header byte of 0xFF, then read the following 3 bytes, sum bytes 2 and 3 then check if the 4th byte is equal. if it is you have your data and can use the algorithm(Distance= Data_H*256+ Data_L=0X07A1;
) to calculate the result.

FROM the vendorā€™s page:

Header DATA_H DATA_L SUM
0xFF 0x07 0xA1 0xA7

Note: checksum only reserves the low 8-bits of the accumulated value.

SUM=(Header+Data_H+Data_L)&0x00FF
=(0XFF + 0X07 + 0XA1)&0x00FF
=0XA7;

Copy

Distance= Data_H*256+ Data_L=0X07A1;

Equal to 1953 when converted into decimal;

Represent the current measured distance is 1953mm.

2 Likes

Many thanks for your input, unfortunately I have to admit that it is beyond my (current) horizon.
I have hoped that the manufacturer will be able to supply a library for Micropython so that I could get started with this sensor, at my level, but they have written back that I must make the necessary library for Micropython myself and I cannot do that (yet) :wink:

ā€¦Iā€™m the type who buys a Kepler Kit for Raspberry Pi Pico W and uses all their nice and educational lessons to build amazing things, have a lot of fun doing it and get a little wiser. I donā€™t know if I will ever get to the heart of microprocessor programming, but I have already gained an understanding of many electronic components that I didnā€™t have half a year ago.

1 Like

I have a PiPico but not a sensor and will look for examples of serial port access and then will try to put together something which loops on the serial port reading the bytes as Iā€™d mentioned earlier and printing out the device data.

I donā€™t know microPython and can fumble my way through Python code so I should be able to get something which would get you data.

That sounds very generous, thank you very much.
On DFRobotā€™s homepage, their sensor is priced at approx. 16 USD, if it will help you to have it physically in your hands, to be able to make and test a program/library, I would like to assist with that.

I wish you all here on the forum a happy Easter.

1 Like

Looks like there are two UARTs on the RP2040 so I jumpered the output of uart0-tx to uart1-rx and sent some known good+junk out uart0 and read uart1 looking for 0xff. when it finds 0xff it reads the next bytes tests for checksum and if it matches it presents the sensor data.

Iā€™d left the default baudrate of 115200 but the sensor uses 9600. I tried changing both uarts to 9600 baud but it fails when I do that so maybe when only using one uart to read itā€™ll work.

uart1 = machine.UART(0, 9600)

If youā€™re up for hacking this into a loop on your system give it a whirl. if youā€™d like me to tweak it further let me know.

uart0_uart1_bytes.py.stl (1.3 KB)

I have ā€œuploadedā€ to Tonny and get the following message:

%run -C $ editor_content
(SYSNAME = ā€˜RP2ā€™, NODEAME = ā€˜RP2ā€™, RELEASE = ā€˜1.19.1ā€™, VERSION = ā€˜V1.19-966-G05BB26010 ON 2023-03-13 (GNU 12.1.0 MINSIZEREL)ā€™, Machine = 'Raspberry PI PICO W WITH RP2040 ')
Uart (0, baud rate = 115200, bits = 8, parity = none, stop = 1, tx = 0, rx = 1, txbuf = 256, rxbuf = 256, timeout = 0, timeout_char = 1, invert = none)
Uart (1, baud rate = 115200, bits = 8, parity = none, stop = 1, tx = 4, rx = 5, txbuf = 256, rxbuf = 256, timeout = 0, timeout_char = 1, invert = none)
Index = 0 = 0
Index = 1 = 0
Index = 2 = 0
Index = 3 = 0
sum = 0 bytes = 0x0
Traceback (Most Recent Call Last):
File ā€œā€, line 50, in
TypeError: OBJECT WITH BUFFER PROTOCOL REQUIRED

ā€¦ whether itā€™s because I read it wrong in to Tonny or ā€¦?

(The only thing I have changed is Given Line 9 Another PIN Address - ā€œLED_ONBOARD = MACHINE.PIN (25, MACHINE.PIN.OUT)ā€, GP25 which should be the one for LED on RPI Pico W)

If you bother, I will be plainly happy with your assistance :wink:

probably not. I tried changing both uart declarations to include 115200 and got that msg. Ended up working when only one uart was set using the constructor and even 9600 worked and both were set to that speed as the info output showed. So will need to dig into what that buffer protocol required msg is.

I still donā€™t know what that error is but I moved a few initializers around and made a loop which will keep writing simulated data and then read the simulated data to produce an output. To work with the real sensor, try commenting out the 6 lines at the beginning of the loop declaration so itā€™s only reading data on uart1.

test_A02YYUW.py.stl (1.7 KB)

Sorry, could not help myself from getting this working. And hereā€™s a link to the documentation I used to write the code: https://wiki.dfrobot.com/_A02YYUW_Waterproof_Ultrasonic_Sensor_SKU_SEN0311

import os
import utime
import machine
# for A02YYUW ultrasonic Sensor, loops and outputs mm distance measured
# with Rx on the sensor floating, it will output data ever 300mS and that's how this is used.
# So only connect up the Green/Tx output of the sensor to GPIO-5(Aux1 Rx)
# power should be what every your device supports(3.3V or 5V). I used the Grove conn power.

#print sys info
print(os.uname())

#indicate program found a valid start of a sensor measurement
led_onboard = machine.Pin(17, machine.Pin.OUT)
led_onboard.value(0)     # onboard LED OFF

#setup uarts
#uart0 = machine.UART(0) #,9600)
#uart0.init(9600, bits=8, parity=None, stop=1) # init with given parameters
uart1 = machine.UART(1,9600)#,9600)
#uart1.init(9600, bits=8, parity=None, stop=1) # init with given parameters

#print uart info
#print(uart0) # Grove port #1 of Maker Pi  Tx=GPIO0, Rx=GPIO1
print(uart1) # Grove Port #3 of Maker Pi, Tx=GPIO4, Rx=GPIO5

data = [0,0,0,0]

goodData = False;
while True:
    #
    # When using the real sensor COMMENT OUT the following 6 lines 
    #uart0.write(b'\xFF') #sensor start flag
    #uart0.write(b'\x07') #sensor data-H
    #uart0.write(b'\xA1') #sensor data-L
    #uart0.write(b'\xA7') #sensor checkSum
    #uart0.write("hello") #bunch of other stuff to skip
    #utime.sleep(0.1)

    #NOTE: with Rx floating on the sensor, data is sent every 300mS
    while uart1.any():
        dataRead=uart1.read(1)
        if dataRead == b'\xff':
            goodData = True
            data[0]=dataRead
            data[1]=uart1.read(1)
            data[2]=uart1.read(1)
            data[3]=uart1.read(1)
            led_onboard.value(1)
        else:
            led_onboard.value(0)
        
        #test 4 bytes of data read for validity
        for i in range(0,4):
            if type(data[i]) == type(None) : goodData=False; utime.sleep(0.1)
    if( goodData ) :        
        #debugging
        #for i in range(0,4):
        #    print("index=",i,"=",data[i])
        
        #validate the data
        dataSum = sum(bytes(data[0]+data[1]+data[2]))&0x00ff
        #debugging
        #print("sum = ", dataSum, "bytes =",hex(dataSum) )

        #checking if the calculated sum is the same as the last byte
        if dataSum is int.from_bytes(data[3],'big'):
            sensorReading = data[1] + data[2]
            print("sensor data=",int.from_bytes(sensorReading,'big'))
        utime.sleep(1)
        data = [0,0,0,0]
    goodData = False

print("should never get here")

Output:

%Run -c $EDITOR_CONTENT
(sysname=ā€˜rp2ā€™, nodename=ā€˜rp2ā€™, release=ā€˜1.19.1ā€™, version=ā€˜v1.19.1 on 2022-06-18 (GNU 11.2.0 MinSizeRel)ā€™, machine=ā€˜Raspberry Pi Pico with RP2040ā€™)
UART(1, baudrate=9600, bits=8, parity=None, stop=1, tx=4, rx=5, txbuf=256, rxbuf=256, timeout=0, timeout_char=2, invert=None)
sensor data= 1142
sensor data= 1147
sensor data= 1147
sensor data= 326
sensor data= 218
sensor data= 221
sensor data= 217
sensor data= 313
sensor data= 393
sensor data= 313
sensor data= 311

3 Likes

Hi Doug, Many thanks for your help/solution!!!
I donā€™t understand much of your code (yet;-)) - but it works just as I wanted it to.

# So only connect up the Green/Tx output of the sensor to GPIO-5(Aux1 Rx) ā€¦
How does the RPi ā€œreadā€ the value that comes back when the TX is ā€œmissingā€/not connected?..
ā€¦I have a lot to learn.

The next step in my little project is to redirect the output to a small display, and to calibrate the millimeters to my max and my min value of the tank.

Once again, thank you for your kind and patient help.

The rpi2040 Aux1 has both a Rx and a Tx connection, since the sensor is sending data it will send it out on its Tx(Transmit) connection and to read that data the rPi 2040 Aux1 port would need to connect the Rx(GPIO pin 5) to the sensor Tx(Green) wire.

The sensor just keeps sending out data at 300mS intervals when you leave its Rx(Blue) wire unconnected. Iā€™d read the sensor is more accurate at the 300mS interval vs anything faster which would require controlling the sensor Rx signal.

The microPython code just waits for data on the serial port(Aux 1) with the line

and then it processes the data. If it reads some junk( testing for ā€œNoneā€ type data ) it stops the loop and looks again for data and 0xff start-of-message byte.

So if you disconnect the sensorā€™s Tx wire there will be no data to work with and the code will keep looping and looking for data at uart1.any().

You could change the output from

to something like print(ā€œSensorData=ā€,int.from_bytes(sensorReading,ā€˜bigā€™))
or just print(int.from_bytes(sensorReading,ā€˜bigā€™))
for parsing by another application connected to the USB port of the rPi2040.

1 Like