#include <SoftwareSerial.h>
//GLOBAL VARIABLES
SoftwareSerial A02YYUWsensorSerial(11,10); // Initialize the RX & TX of the A02YYUW ultrasonic sensor on D11 & D10 respectively
//SETUP
void setup(){
Serial.begin(9600); // start the standard serial connection (e.g. for the serial monitor)
A02YYUWsensorSerial.begin(9600); // start the special serial connection for the A02YYUW ultrasonic sensor
Serial.println("Starting A02YYUW ultrasonic distance sensor... "); // this message is for debugging purposes only and can be deleted once the sensor is acertained to be working properly
}
// MEASURE DISTANCE TO A SURFACE WITH THE A02YYUW ULTRASONIC SENSOR
float DistanceToSurface() {
unsigned char SensorData[4]={}; // Array for the A02YYUW ultrasonic sensor data
int ReadAttempt = 0; // Used in the event that multiple read attempts are needed, e.g. at start-up or when sensor serial "send errors" occur
const int ReadAttemptMax = 5; // The maximum allowable number of read attempts
int DataLoop; // Used for reading and processing data from the A02YYUW ultrasonic sensor
const int Header = 0xff; // Header byte of the A02YYUW data "frame"
int CarryByte; // Used to "carry" the zeroeth byte when reordering the A02YYUW raw data
int ShiftArrayLeft; // Used to shift the SensorData[] array left by one element
float Distance; // Distance output measurement of the A02YYUW ultrasonic sensor
int Checksum; // Checksum byte of the A02YYUW data "frame"
while (ReadAttempt < ReadAttemptMax){ // Attempt to read the A02YYUW ultrasonic sensor (up to the permissable number of times)
//A02YYUWsensorSerial.flush(); // This command is specified in the DF Robot documentation for the A02YYUW ultrasonic sensor before enacting a A02YYUWsensorSerial.read()
// Prior to Arduino 1.0, serial.flush removed any buffered incoming serial data; but now it waits for the transmission of outgoing serial data to complete.
// I suspect this was intended to work in the pre-Arduino 1.0 meaning. So instead I'm using the next two lines to removed any buffered incoming serial data.
while(A02YYUWsensorSerial.available()){ // if there is data in the incoming A02YYUWsensorSerial buffer (from the A02YYUW ultrasonic sensor)
A02YYUWsensorSerial.read(); // flush any old incoming sensor data
}
delay(100); // wait for new data to arrive (it seems that the A02YYUW sends data every 90-ish milliseconds; using 100 ms to be safe)
for(DataLoop = 0 ; DataLoop < 4; DataLoop++){ // Read a 4-byte data "frame" (data on the A02YYUW is sent in 4-byte "frames")
SensorData[DataLoop] = A02YYUWsensorSerial.read(); // get a byte from the A02YYUW serial connection into the SensorData[] array
}
while (DataLoop > 0){ // Note that: DataLoop = 4 at the start of this "while" loop (due to the previous "for" loop)
if (SensorData[0] != Header){ // if the first array element is NOT the expected Header byte, i.e. if the A02YYUW data is not in the correct order
CarryByte = SensorData[0]; // temporarily store SensorData[0] in the CarryByte variable
for (ShiftArrayLeft = 0; ShiftArrayLeft < 3; ShiftArrayLeft++){ // reorder the data by moving each array element to the left
SensorData[ShiftArrayLeft] = SensorData[ShiftArrayLeft + 1]; // move SensorData[] array left by one element
}
SensorData[3] = CarryByte; // move the original SensorData[0] left (all the way around) to SensorData [3]
DataLoop--; // decrement the DataLoop variable
}
else{
DataLoop = 0; // the A02YYUW data is in the correct order (since it begins with the expected Header byte) therefore exit the "while" loop
}
}
if(SensorData[0] == Header) // if the raw sensor data contained a header byte (Note that: occasionally the A02YYUW will miss sending a data byte)
{
Checksum=(SensorData[0] + SensorData[1] + SensorData[2]) & 0x00FF; // Calculate the expected checksum using the header and distance data (High 8-bits plus Low 8-bits)
if(Checksum==SensorData[3]) // if the expected checksum is the same as the Checksum byte that was received
{
Distance = (SensorData[1] << 8) + SensorData[2]; // calculate the distance measurement from the distance data (High 8-bits and Low 8-bits)
if(Distance > 30){ // if the calculated distance data is more than 30 mm, i.e. if it is greater than the minimum measureable distance
return Distance; // return the calculated distance measurement (in millimetres)
}
else{
Serial.println("Below the lower limit!"); // this message is for debugging purposes only and can be deleted once the sensor is acertained to be working properly
return 0; // return zero (to indicate that distance is less than minimum measurement range)
}
ReadAttempt = ReadAttemptMax + 1; // Set the ReadAttempt value to one greater than the maximum allowable to indicate a successful read, i.e. so that a failed read attempt can be easily differentiated
}
else{ // if the Checksum byte was incorrect
Serial.println("Failed read attempt (Checksum)"); // this message is for debugging purposes only and can be deleted once the sensor is acertained to be working properly
ReadAttempt++; // increment to the next read attempt
}
}
else{ // if the Header byte was not found
Serial.println("Failed read attempt (Header)"); // this message is for debugging purposes only and can be deleted once the sensor is acertained to be working properly
ReadAttempt++; // increment to the next read attempt
}
}
if (ReadAttempt == ReadAttemptMax){ // if the permissible number of read attempts was exceeded
Serial.println("A02YYUW SENSOR READ ERROR"); // then a read error has occurred
return 999999; // return 999999 to indicate that no useful measurement could be obtained
}
}
// MAIN LOOP
void loop()
{
Serial.print("distance = ");
Serial.print(DistanceToSurface()); // print the tank level (in millimetres) measured by the A02YYUW ultrasonic sensor
Serial.println(" mm");
delay(500); // wait half a second (or any other desired period) before taking the next reading
}