Short question. I'v looked it up and this; the & before a identifier; should be a bitwise AND.
But i want to play with a UART ultrasonic distance sensor A02YYUW. I'v ordered the wrong one but i was dissecting the code a bit.
On this webpage that person states that the checksum = the sum fo the first 3 incomming bytes in the data buffer.
/*
JSN-SR04T-V3.0 Ultrasonic Sensor - Mode 1 Demo
srt04-mode1.ino
Uses JSN-SR04T-V3.0 Ultrasonic Sensor
Displays on Serial Monitor
Mode 1 is set by bridging "M1" pads on board
Also works with A02YYUW Ultrasonic Sensor
DroneBot Workshop 2021
https://dronebotworkshop.com
*/
// Include the Software Serial library
#include <SoftwareSerial.h>
// Define connections to sensor
int pinRX = 10;
int pinTX = 11;
// Array to store incoming serial data
unsigned char data_buffer[4] = {0};
// Integer to store distance
int distance = 0;
// Variable to hold checksum
unsigned char CS;
// Object to represent software serial port
SoftwareSerial mySerial(pinRX, pinTX);
void setup() {
// Set up serial monitor
Serial.begin(115200);
// Set up software serial port
mySerial.begin(9600);
}
void loop() {
// Run if data available
if (mySerial.available() > 0) {
delay(4);
// Check for packet header character 0xff
if (mySerial.read() == 0xff) {
// Insert header into array
data_buffer[0] = 0xff;
// Read remaining 3 characters of data and insert into array
for (int i = 1; i < 4; i++) {
data_buffer[i] = mySerial.read();
}
//Compute checksum
CS = data_buffer[0] + data_buffer[1] + data_buffer[2];
// If checksum is valid compose distance from data
if (data_buffer[3] == CS) {
distance = (data_buffer[1] << 8) + data_buffer[2];
// Print to serial monitor
Serial.print("distance: ");
Serial.print(distance);
Serial.println(" mm");
}
}
}
}
But in a other example found in the forum the first three bytes are added (sum) and that result is undergoing a bitwise AND with 0x00FF.
/*
*@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);
}
Is this adding a empty 'byte' of the sum to get a int?
if(sum==data[3])
..because sum is a int?
..does that mean that in the first sketch the sum of the first three unsigned char's in the data_buffer[] is 'overflowing'? So the most significant bits are automatically dumped to get unsigned char CS in 8 bits?
The ampersand (&0x00FF) masks (makes zero) the high byte of the int.
In the first example this is not needed because CS is an unsigned char (byte) and anything bigger than 0xFF is thrown away, in the second example it's sum is an int.
unint8 's are just added like normal but the 'adding' gets 'cut off' at 8 bits. I called it a overflow but it is just a stop in length and that's why the least significant bits stay the same as in the unint16 's.
thx
Actually in C++ the norm states that If a, b, and c are uint8_t, then when you do c = a + b;, both a and b are promoted to int, the addition is performed as a signed int, and the result is then implicitly converted back to uint8_t, which wraps around modulo 256.
➜ There is no way in standard C++ to force the addition a + b to be performed directly as uint8_t (i.e. as an 8-bit operation without promotion), because the language automatically promotes operands smaller than int before arithmetic.
This implicit type promotion is to be kept in mind when you do maths with bytes on a 16 bits MCU, esp if you multiply and overflow the positive int and intend to use the result as a parameter to a function that supports int as a type:
Try
uint8_t a = 200;
uint8_t b = 200;
uint8_t c = a * b;
Serial.println(a*b); // -25536 as print sees an int
Serial.println(c); // as expected 64
So don’t forget to store as a byte or mask the value to get rid of the higher bits and get the expected result, in the example above
Serial.println((a*b) & 0xFF); // as expected 64
Print still sees an int but you extracted the least significant byte.
it's actually called "wraparound". adding 1 2 to an 8-bit variable having a value of 255 doesn't remain at it's max of value of 255 or 0xff, it now becomes 1 which is the value of the lower 8 bits of the sum.
the same is also true when subtracting a larger unsigned value from a smaller unsigned value with the same # of bits. subtracting 250 from 1 results in 7.