Good day guys & gals,
Ive been working to interface an A02YYUW Ultrasonic sensor with my ESP32. The RX/TX pins are connected to Pins 12 and 14, and I cannot change this in order to use Hardware serial, so i've been trying to make SoftwareSerial work.
The issue I'm having is, that my UART readout is 255 for all of the 4 bits. As such, I am not getting a good reading from the sensor. I've verified my connections to the best of my abilities, so I suspect it's a code issue. Any help in this manner would be appreciated. Thanks!
// Import required libraries
#include <Arduino.h>
#include <SoftwareSerial.h>
#define MYPORT_TX 12
#define MYPORT_RX 14
unsigned char data[4]={};
float distance;
EspSoftwareSerial::UART myPort;
void setup()
{
Serial.begin(115200); // Standard hardware serial port
myPort.begin(9600, EspSoftwareSerial::SWSERIAL_8N1, MYPORT_RX, MYPORT_TX, false);
if (!myPort) { // If the object did not initialize, then its configuration is invalid
Serial.println("Invalid EspSoftwareSerial pin configuration, check config");
while (1) { // Don't continue with invalid configuration
delay (1000);
}
}
}
void loop() {
do{
for(int i=0;i<4;i++)
{
data[i]=myPort.read();
}
}while(myPort.read()==0xff);
Serial.print("Data 0 =");
Serial.println(data[0]);
delay(500);
Serial.print("Data 1 =");
Serial.println(data[1]);
delay(500);
Serial.print("Data 2 =");
Serial.println(data[2]);
delay(500);
Serial.print("Data 3 =");
Serial.println(data[3]);
delay(500);
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");
}
myPort.flush();
delay(500);
}
but you can define any pins as a hwSerial pair. Mind you, those particular pins may cause some issues, but how about you just try to use them for UART2
I did not know this. I thought HW serial was limited to pins 1&3 as seen below, however i tried to compile as you suggested and did not get any issues.
By default TX0 & RX0 are 1 & 3, but those are also the pins that the USB to TTL interface is connected to, resulting in no reception on the RX pin, so if you'd want to use UART0 without USB, you should already re-define those pins. UART2 has 17 & 16 by default, that actually works on those pins.
UART1 has pins 9 & 10, but those are also used by the flash, and not recommended (causes a run-time error)
so those should be re-defined if you want to use that UART.
Just wondering now, if i set both GPIO 1 & 3 to 'INPUT' one should be able to connect to the USB-TTL while bypassing the ESP's UART, but this is of course a completely different matter.
Thank you for the insight. I was under the misconception that the UART pins (all 3 sets) were rigid and could not be reassigned, however, it is very useful to see that this is not the case.
It's a do while loop. A pretty dodgy one at that. But yes, it would need the semicolon because of the do.
This do while will lock everything up until there is something available on the serial line. I would think working the other way and checking for myport.available() would be a better option. You could even wait for myport.available() to be 4 and know that you can just read in all four values back to back.
Im not exactly sure what you mean by this, but will look into the .available() command to see if i can improve. That section of the code was shamelessly copied from the DF robot example as a (theoretically) "working" starting point.
EDIT: @Delta_G, Would this be an appropriate implementation of the myPort.(available) as you sugested?
// reply only when you receive data:
if (myPort.available() == 4) {
// read the incoming bytes:
data[] = Serial.read();
The delay isn't necessary. This just creates blocking code. Do it like you did in reply 13 and just wait until 4 bytes are available but allow for the possibility that there may be more than four byte.
if (myPort.available() >= 4) {
// read the incoming bytes:
for(int i = 0; i<4; i++){
data[i] = myPort.read();
}
}
I tried this, and still no reading. Interesting to see that now all bits are 0 instead of 255. Ive verified the HW wiring (TX, RX, GND all good, sensor receiving 3.4V) And trying to probe with the oscilloscope now.
Again, want to thank you @Delta_G for your time and effort in this manner
You understand that 255 is what you get when you read the port when there's nothing there to be read right. That's the source of 255.
Try this and see if it is ever getting four bytes to read and going into the if statement. This is how we debug, stick a print in there to see if things are happening.
if (myPort.available() >= 4) {
Serial.println("Got some serial data!");
// read the incoming bytes:
for(int i = 0; i<4; i++){
data[i] = myPort.read();
Serial.print("data[");
Serial.print(i);
Serial.print("] = ");
Serial.println(data[i]);
}
}
those 2 ms we can spare, reception of a byte at 9600 takes just over 1 ms.
What i did forget (and you missed as well)
if (i == 4) { // only then was the transmission complete, otherwise you may still be looking at old data.
That can be done in your method as well (just to be clear, yes my code is blocking in a sense, but this is not the issue the OP is having, it can be optimized later once reception has been confirmed)
Keep in mind that you are transmitting more bytes than you are receiving and although you are transmitting at a higher speed, you transmit up to 10 bytes for every byte received + the notification) Once the TX buffer is full, Serial.print() becomes blocking automatically (basically the program will wait until there is space in the TX-buffer) So you debug code is just as blocking as mine.
btw. Thanx for the help though.
@zach3d How about first you verify that those pins are actually working as a tx/rx pair by sending Serial data from the TX pin (and receive them with a different device i guess you will have an arduino lying around somewhere) and receive from the RX-pin and send that output to the USB-serial.