Hi all!
I am currently struggling to receive a 4 byte array, containing 3 values and a sync byte (S, or 0x53). All values stay at 0, even though it is receiving serial data... I'm sending this byte array every 10ms.
Here below is my code:
byte RGB[3] = {0, 0, 0};
boolean newData = false;
void setup() {
Serial.begin(9600);
Serial.println("<Arduino is ready>");
}
void loop() {
if (Serial.available() > 0) {
byte val = Serial.read();
if (val == 'S') {
while (!Serial.available())
RGB[0] = Serial.read();
while (!Serial.available())
RGB[1] = Serial.read();
while (!Serial.available())
RGB[2] = Serial.read();
}
Serial.println(RGB[0]);
}
}
I already figured that, doesn't seem like the best approach to this, I'm experimenting with the Serial.readBytes() function, but no results so far, will post the code i have once i get better results
So I made a new program from scratch... But with, so far, no good results.
The data being sent to is is as following:
0x52, [R value], 0x47, [G value], 0x42, [B value]
And here's the code i have come up with:
byte RGB[3];
void setup() {
Serial.begin(9600);
}
void loop() {
byte d = 0;
int state = 0;
while (state == 0){
if (Serial.available() > 0){
d = Serial.read();
//"R" found
if (d == 0x52){
state = 1;
}
//"G" found
if (d == 0x47){
state = 2;
}
//"B" found
if (d == 0x42){
state = 3;
}
Serial.println(state);
}
while (Serial.available() < 0){ // keep looping until data available
}
}
//"R" Found!
while (state == 1){
d = Serial.read();
if ((d != 0x52) && (d != 47) && (d != 42)){
RGB[0] = d;
}
if (d == 0x52){
state = 1;
}
if (d == 0x47){
state = 2;
}
if (d == 0x42){
state = 3;
}
Serial.println(RGB[0]);
}
//"G" Found!
while (state == 2){
d = Serial.read();
if ((d != 0x52) && (d != 47) && (d != 42)){
RGB[1] = d;
}
if (d == 0x52){
state = 1;
}
if (d == 0x47){
state = 2;
}
if (d == 0x42){
state = 3;
}
}
//"B" Found!
while (state == 3){
d = Serial.read();
if ((d != 0x52) && (d != 47) && (d != 42)){
RGB[2] = d;
}
if (d == 0x52){
state = 1;
}
if (d == 0x47){
state = 2;
}
if (d == 0x42){
state = 3;
}
}
}
It appears you are connected to the serial monitor as you have Serial.print statements... so is the input coming from the monitor? or are you expecting it from somewhere else?
Your code is WAY more complicated than it needs to be.
Thanks for the reply!
It's coming from a C# program, using a usb to serial (5V) adapter. I already checked using a serial port monitor program, and the bytes are being sent correctly.
I'm using an Uno, it has only one serial port, and i just thought about it as well, if i send any text using "Serial.writeln" it will probably mess up the entire system, if my thinking is correct
Okay so, after reading through the link @sterretje gave, i came accross a similar program to what i want to achive. I based myself off that to understand the workings of this serial stuff... And as a huge surprise the test program i made almost intstantly worked!!
I can now receive the R, G, B and sync bytes and display them on their respective led (except for the sync one of course)!
Below here is the code i got, so far i don't see any room for significant improvement, feel free to prove me wrong!
//Define led pins
#define Rpin 3
#define Gpin 5
#define Bpin 6
//The end marker is 255, the max value of the received R, G and B byte has been reduced to 254!!
//A single bit lower than maximum is barely noticable
#define EndMarker 255
//Define received and temp buffer, and the amount of received bytes
byte dataRec[4];
byte tempBuffer[4];
byte bytesRec = 0;
void setup() {
//Start serial monitor
Serial.begin(57600);
//Set the pins for the R, G and B led as output (PWM)
pinMode(Rpin, OUTPUT);
pinMode(Gpin, OUTPUT);
pinMode(Bpin, OUTPUT);
}
void loop() {
getData();
}
//Method to read the incoming data
void getData() {
if (Serial.available() > 0) {
byte x = Serial.read();
//If the end marker has been received
if (x == EndMarker) {
//Put all temp bytes in the received buffer
for (byte n = 1; n < bytesRec; n++) {
dataRec[n] = tempBuffer[n];
}
//Executed method to use received data as pwm
SendToLeds();
}
//Put received bytes into temp buffer
tempBuffer[bytesRec] = x;
bytesRec ++;
}
}
//If data has been put in the received buffer, set them on the correct led, and reset received bytes
void SendToLeds() {
analogWrite(Rpin, dataRec[1]);
analogWrite(Gpin, dataRec[2]);
analogWrite(Bpin, dataRec[3]);
bytesRec = 0;
}
The very first time that you receive a 'packet', data will be in tempBuffer[0..2] and tempBuffer[3] will contain the end marker. All successive times, the data will be in tempBuffer[1..3] and tempBuffer[0] will contain the end marker.
Possible improvements
Fix above
Hardening; what happens if you send more than 4 bytes accidentally or on purpose? Your application might show undefined behaviour.
Full separation of receive and led control (don't call SendToLeds() in getData(), don't reset bytesRec in SendToLeds()).
Thanks for the feedback!
I don't really get how the end marker can be last in the tempBuffer , but first in the dataRec buffer, since the tempBuffer gets compied exactly as it is into the dataRec buffer in the for loop.
After a call to SendToLeds(), bytesRec is set to 0. Next you do tempBuffer[bytesRec] = x; So where is the end marker.
There must be a reason why you start with 1 in for (byte n = 1; n < bytesRec; n++) and why you use elements 1, 2 and 3 in the SendToLeds() function and not 0, 1 and 2 which would be more usual.