I've got a problem with one last instruction through the serial port.
I developed a program that sends the encoding of a color (in RGB format) via the serial port. The information is passed in the following format: xxxyyyzzz (all of which are numerical digits). XXX is the color information red, green YYY and ZZZ Blue.
I'm having trouble separating these numbers in Arduino, Arduino do understand that the first three are the variable Red and so on.
I thought I'd turn into Array (googled enough before putting message here) but I can not imagine how to concatenate this information to transform back into a number.
Yes, all the data are consistent and have the same 9 digits, even if they are all 0.
As for the post you indicated, was unable to identify which of them could help me. Several were posted and I could not understand much ... Sorry
Robin2:
Post your own code and explain what it is intended to do and what it actually does.
...R
/*
Author: Tiago Baroni, 31/08/2014
This code is based on the sample PhysicalPixel
*/
const int red = 9; // the pin that the Red LED is attached to
const int green = 10; // the pin that the Red LED is attached to
const int blue = 11; // the pin that the Red LED is attached to
int vlRed = 0;
int vlGreen = 0;
int vlBlue = 0;
int incomingByte; // a variable to read incoming serial data into
void setup() {
// initialize serial communication:
Serial.begin(9600);
// initialize the LED pin as an output:
pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);
}
void loop() {
// see if there's incoming serial data:
if (Serial.available() > 0) {
// read the oldest byte in the serial buffer:
incomingByte = Serial.read();
//At that moment the variable incomingByte has the color code in the format xxxyyyzzz
//Here I need a code that caught the xxx content and pass the variable to vlRed;
//Here I need a code that caught the yyy content and pass the variable to vlGreen;
//Here I need a code that caught the zzz content and pass the variable to vlBlue;
analogWrite(red,vlRed);
analogWrite(green,vlGreen);
analogWrite(blue,vlBlue);
}
}
I wa refering to what I wrote in reply #3 of that link, but if the data IS always 9 characters long then a simple counter and the uses of the module operator will be perfect for your solution.
See if the serial buffer(Serial.available() ) has first collected 9 chars, then once it has read them in one at a time and increment a counter. You can use an array to store the 3 chars and use atoi() to convert the chars into an actual integer. Then using if(counter % 3) you can change to the next variable.
First, if you are sure of the format and that it is always terminated with a newline character ('\n', click clicking Enter in the Serial monitor), you can capture all of your data at once:
void loop() {
byte red, green, blue;
char buff[10];
int bytesReceived;
if (Serial.available() > 0) {
// read the oldest byte in the serial buffer:
bytesReceived= Serial.readBytesUntil('\n', buff, 9); // Stay here and read all of the input data
buff[bytesReceived] = '\0'; // Make it a string
red = GetAColor(buff); // Pick off first three bytes...
green = GetAColor(&buff[3]); // ...the next three...
blue = GetAColor(&buff[6]); // ...the last three...
{
}
byte GetAColor(char str[])
{
char temp[4];
strncpy(temp, str, 3);
return (byte) atoi(temp);
}
I haven't tested this out, but at least it's a starting point.
The best starting point is to working on the simplest way to decode your data, then work on sending the data in that format. As to decoding, sending the data to the arduino with a data delimiter then capturing the whole data packer makes parsing the data into individual components easier. Below is basic parsing test code that shows the basic concept.
//zoomkat 11-12-13 String capture and parsing
//from serial port input (via serial monitor)
//and print result out serial port
//copy test strings and use ctrl/v to paste in
//serial monitor if desired
// * is used as the data string delimiter
// , is used to delimit individual data
String readString; //main captured String
String angle; //data String
String fuel;
String speed1;
String altidude;
int ind1; // , locations
int ind2;
int ind3;
int ind4;
void setup() {
Serial.begin(9600);
Serial.println("serial delimit test 11-12-13"); // so I can keep track of what is loaded
}
void loop() {
//expect a string like 90,low,15.6,125*
//or 130,hi,7.2,389*
if (Serial.available()) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == '*') {
//do stuff
Serial.println();
Serial.print("captured String is : ");
Serial.println(readString); //prints string to serial port out
ind1 = readString.indexOf(','); //finds location of first ,
angle = readString.substring(0, ind1); //captures first data String
ind2 = readString.indexOf(',', ind1+1 ); //finds location of second ,
fuel = readString.substring(ind1+1, ind2+1); //captures second data String
ind3 = readString.indexOf(',', ind2+1 );
speed1 = readString.substring(ind2+1, ind3+1);
ind4 = readString.indexOf(',', ind3+1 );
altidude = readString.substring(ind3+1); //captures remain part of data after last ,
Serial.print("angle = ");
Serial.println(angle);
Serial.print("fuel = ");
Serial.println(fuel);
Serial.print("speed = ");
Serial.println(speed1);
Serial.print("altidude = ");
Serial.println(altidude);
Serial.println();
Serial.println();
readString=""; //clears variable for new input
angle="";
fuel="";
speed1="";
altidude="";
}
else {
readString += c; //makes the string readString
}
}
}
Something like this is all that is needed. Not tested and more is needed to be added in for a full working code. I am not home to complete this, so could someone else finish this? Thank you.
byte Red=0, Green=0, Blue=0, Counter = 0;
void setup()
{
Serial.begin(115200);
}
void loop()
{
if(Serial.available() >= 9)
{
char Tmp = Serial.read();
Counter++;
switch( Counter / 3) //changed
{
case 0:
Red = Red * 10 + (Tmp - '0');
break;
case 1:
Green = Green * 10 + (Tmp - '0');
break;
case 2:
Blue = Blue * 10 + (Tmp - '0');
break;
}
}
else
Counter = 0;
/* write a piece that resets the colors back to zero for the next sent string */
}
This is almost certainly wrong, and would result in the RGB values being interpreted as interleaved in the data, rather than sequential.
Why go through all the trouble of string parsing to begin with? You have control of the program used to send data, don't you? Modify it to send the raw byte value, then you only need to send 3 bytes + a delimiter instead of 9.
// read the oldest byte in the serial buffer:
incomingByte = Serial.read();
//At that moment the variable incomingByte has the color code in the format xxxyyyzzz
//Here I need a code that caught the xxx content and pass the variable to vlRed;
//Here I need a code that caught the yyy content and pass the variable to vlGreen;
//Here I need a code that caught the zzz content and pass the variable to vlBlue;
This is if the data you're sending is sent as individual chars and not just bytes.
byte Red=0, Green=0, Blue=0, Counter = 0;
void setup()
{
Serial.begin(115200);
}
void loop()
{
if(Serial.available() >= 9) // see if 9 chars are in the buffer
{
Counter = 0; // make sure the counter is set to 0
Red = Green = Blue = 0; // reset the color variables
while(Counter <= 9) // while the counter is less than or equal to 9, read the chars from the buffer
{
char Tmp = Serial.read(); // read chars from buffer
switch( Counter / 3) //changed
{
case 0:
Red = Red * 10 + (Tmp - '0'); // convert the chars into integers
break;
case 1:
Green = Green * 10 + (Tmp - '0');
break;
case 2:
Blue = Blue * 10 + (Tmp - '0');
Serial.print(Red);Serial.print(Green);Serial.println(Blue);
break;
}
Counter++; // increment the counter
}
}
}
const int red = 9; // the pin that the Red LED is attached to
const int green = 10; // the pin that the Red LED is attached to
const int blue = 11; // the pin that the Red LED is attached to
int colour[3];
int myInt[3];
//
void setup()
{
Serial.begin(9600);
pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);
}
//
void loop()
{
if (Serial.available() > 8)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
myInt[j] = Serial.read() - '0';
}
colour[i] = myInt[0] * 100 + myInt[1] * 10 + myInt[2];
if (colour[i] > 255) colour[i] = 255;
}
}
analogWrite(red,colour[0]);
analogWrite(green,colour[1]);
analogWrite(blue,colour[2]);
}
Using the considerations, I've begotten a code that worked perfectly.
I thank everyone for their help and understanding.
For the record, if anyone has any questions (even after the excellent explanations of colleagues), my code looked like this:
/*
Author: Tiago Baroni, 31/08/2014
This code is based on the sample PhysicalPixel
*/
const int red = 9; // the pin that the Red LED is attached to
const int green = 10; // the pin that the Red LED is attached to
const int blue = 11; // the pin that the Red LED is attached to
int incomingByte; // a variable to read incoming serial data into
byte GetAColor(char str[])
{
char temp[4];
strncpy(temp, str, 3);
return (byte) atoi(temp);
}
void setup() {
// initialize serial communication:
Serial.begin(9600);
// initialize the LED pin as an output:
pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);
}
void loop() {
// The code below was generated with the help of user "econjack" of Arduino Forum: http://forum.arduino.cc/index.php?topic=264383.0
// see if there's incoming serial data:
if (Serial.available() == 9) {
byte bRed, bGreen, bBlue;
char buff[10];
int bytesReceived;
// read the oldest byte in the serial buffer:
bytesReceived= Serial.readBytesUntil('\n', buff, 9); // Stay here and read all of the input data
buff[bytesReceived] = '\0'; // Make it a string
bRed = GetAColor(buff); // Pick off first three bytes...
bGreen = GetAColor(&buff[3]); // ...the next three...
bBlue = GetAColor(&buff[6]); // ...the last three...
analogWrite(red,bRed);
analogWrite(green,bGreen);
analogWrite(blue,bBlue);
}
}
Call this function with a NULL terminated string, and there is no need to copy it. Copy it this way, and there is no reason to assume that the result is a NULL terminated string. Calling atoi() with something other than a NULL terminated array of chars is not guaranteed to produce meaningful output.