I have successfully established an xbee communication port through AT mode between my PC and Micro. I know this because I uploaded an example from the Arduino IDE called “Physical Pixel” and had success at altering the led state via xbee serial commands. XCTU was my terminal and sending ‘H’ and ‘L’ remotely turned on and off the onboard LED of the Arduino Micro. Success! Now, time to implement FastLED, but here is where I run into Serial communication problems with the Xbee and FastLED, I have posted the adapted example code below. I can visually confirm the xbee received data thru the RSSI indicator LED, but the Arduino will not respond to the changes sent thru serial. After running setup() and calling mode 0, I see red, and nothing but red on the UCS1903’s. Can someone help pin down what exactly is my problem here?
#include <FastLED.h>
#define LED_PIN 5
#define NUM_LEDS 20
#define COLOR_ORDER RGB
#define CHIPSET UCS1903B
#define BRIGHTNESS 32
CRGB leds[NUM_LEDS];
int mode = 0;
int incomingByte;
void setup() {
Serial1.begin(9600);
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness( BRIGHTNESS );
}
void loop() {
int serialREAD();
switch(mode){
case 0: fill_solid(leds, NUM_LEDS, CRGB::Red); break;
case 1: fill_solid(leds, NUM_LEDS, CRGB::Blue); break;
case 2: fill_solid(leds, NUM_LEDS, CRGB::Green); break;
}
FastLED.show();
// FastLED.delay(200);
}
int serialREAD(){
if (Serial1.available() > 0) {
incomingByte = Serial1.read();
if (incomingByte == ‘H’) { mode++; if(mode > 2){ mode = 2; } }
if (incomingByte == ‘L’) { mode–; if(mode <= 0){ mode = 0; } }
return mode;
}
}
Debugging suggestion, pretty self explanatory. Note the difference between Serial1 and Serial.
int serialREAD() {
if (Serial1.available() > 0) {
Serial.println(“I got some!”);
incomingByte = Serial1.read();
Serial.print("incomingByte: ");
Serial.println(incomingByte, DEC);
if (incomingByte == ‘H’) {
mode++;
if (mode > 2) mode = 2;
}
if (incomingByte == ‘L’) {
mode–;
if (mode <= 0) mode = 0;
}
Serial.print("mode: ");
Serial.println(mode);
return mode;
}
}
Avoid writing multi-statements single line code like you have with your if statements. It may not matter now but you’re just asking for trouble and it’s hard to debug later. One condition check is fine, multiples not so much.
After inserting your code snippet @Ashley_M_Kirchner_No , I get nothing on both Serial and Serial1 output. I am still sending the data through the xbees successfully, however the Micro is not processing it.
Could this be a problem with how often am calling LED.show()?
So the way I debug stuff like that is to systematically go through each step. For that, you do not need FastLED yet. Remove it altogether from your code, start fresh. Get the BT signaling working first. Print back to the console what you are actually receiving from the module. You may be sending one thing, the Micro may be receiving a whole different thing and you won’t know it. This is why I sprinkle Serial.println() all over my code when I’m debugging. Once you have that and you know it’s working correctly, then you can move on to the next step and add FastLED and test again. Don’t do anything fancy yet, just set led[0] and call it done. Step by step, till you find where the failure is.
The failure is when I add FastLED, that is my point here.
The other thing you might want to do (when you are further along and have it all working), is to add a condition check around .show(). There is no reason to update the string if nothing has changed. So use the data you received from the BT to keep track of the current state:
volatile byte incomingByte;
volatile byte prev_incomingByte;
if (incomingByte != prev_incomingByte) {
LEDS.show();
prev_incomingByte = incomingByte;
}
Now .show() only gets called if incomingByte has changed from its previous state.
Actually, stick the entire switch case in there too. No need to constantly evaluating that.
Make the changes above, put the entire switch case as well as calling .show() inside of a condition check. See what happens.
I’m working my way up to getting serial data to populate an array, that the leds use, but I can’t even reach that point yet. It seems that no matter how I have tried programming for these UCS1903’s, there is no way around the fact that FastLED blocks serial data interrupts too often causing missed data. As I mentioned earlier, a ‘stock’ Arduino example “Physical Pixel” worked great with my setup. 2 Arduino Micros through Xbees, transmitted serial data successfully. @Ashley_M_Kirchner_No I will try the code snippet you just posted as I was writing this and get back on it. I think that is the solution I am looking for. And possibly the fact that I wasn’t using the ‘volatile byte’ in my sketch. Thanks for the guidance as usual!
This is why I like running the main loop as fast it can without getting interrupted. Things like pattern updates only happen once every 5 to 10 ms, leaving plenty of time for a short burst over serial. It would mean rethinking how you write your code and how to conditionally call parts of it, in other words, only when needed.
As far as Arduino goes, declaring a variable volatile is not necessary. However, proper c++ would say you should. You can just declare it as byte incomingByte; and call it a day.
I was able to confirm that data is reaching the Micro from the Xbee thru debugging, however when I type in an ‘H’ into XCTU terminal, Arduino terminal says it == 72 and a ‘L’ == 76. Knowing these values, I tried to use this code with no success, I don’t even reach the mode part of my code:
void loop() {
if (Serial1.available() > 0) {
incomingByte = Serial1.read();
Serial.print("incomingByte: ");
Serial.println(incomingByte, DEC);
void serialREAD();
}
}
void serialREAD() {
if (incomingByte != prev_incomingByte) {
if (incomingByte == 72) {
mode++;
Serial.print("mode; ");
Serial.println(mode);
if (mode > 2) mode = 2;
}
if (incomingByte == 76) {
mode–;
Serial.print("mode; ");
Serial.println(mode);
if (mode <= 0) mode = 0;
}
switch(mode){
case 0: fill_solid(leds, NUM_LEDS, CRGB::Red); break;
case 1: fill_solid(leds, NUM_LEDS, CRGB::Blue); break;
case 2: fill_solid(leds, NUM_LEDS, CRGB::Green); break;
}
LEDS.show();
prev_incomingByte = incomingByte;
}
}
And that would be because you’re comparing apples and oranges. You need to figure out what exactly are you transmitting. It is a single byte? Is it a series of bytes? Does it have a terminating character at the end? Then, looking at the receiving end, what data type are you trying to stuff that in? Are you reading the full stream accordingly?
These are all things you need to figure out before you can finally get to your switch case.
Got it! Whew, what a pain. Look at line 6 of the code, in previous posts above, I had it set to void. The only way it would work with Fast LED is to have it return parse(). I don’t quite exactly understand why it works this way, but it just does. Xbees are controlling a remote LED install. LET THE FUN BEGIN!
void loop() {
if (Serial1.available() > 0) {
incomingByte = Serial1.read();
}
if (incomingByte != prev_incomingByte) {
return parse(); //changed from void to return and walla, lights work
prev_incomingByte = incomingByte;
}
}
void parse() {
mode = incomingByte;
switch(mode){
case ‘0’: fill_solid(leds, NUM_LEDS, CRGB::Red); break;
case ‘1’: fill_solid(leds, NUM_LEDS, CRGB::Blue); break;
case ‘2’: fill_solid(leds, NUM_LEDS, CRGB::Green); break;
}
LEDS.show();
}
In your loop(), get rid of the ‘return’ that’s before parse(). What you’re doing is exiting the if statement that way. You need it to continue running to set the prev_incomingByte.
That’s my point EXACTLY. This code block only works when return parse() is used not void parse().
prev_incomingByte is working correctly despite the ‘return’. It is counter intuitive and goes against the Arduino reference, it should do what you say @Ashley_M_Kirchner_No but it is not. Could this be specific for the Micro? I’ll try and test this on my Uno a bit later tonight.
It should just read parse(), with nothing else before it. You are not declaring a function in your loop, that’s done outside of the loop. Adding void infront of it will not work, ever, not inside of the loop.
void loop() {
if (Serial1.available() > 0) {
incomingByte = Serial1.read();
}
if (incomingByte != prev_incomingByte) {
parse();
prev_incomingByte = incomingByte;
}
}
I’m an idiot. Thanks for the help.
Another tidbit: Serial.available() will either return 0, or the number of bytes available to read. So it’s either 0, or a positive value. That simplifies things as you don’t have to compare it with 0, either it’s 0 or >0:
if (Serial1.available()) { … } // works just fine