0
votes

I'm working on a home automation system, one part of which includes an Arduino Mega2560 connected via USB to a RaspberryPi 3 Model B. The Arduino receives two short, simple commands over serial from the Pi; the first command sets 'regions' of led lights, and the second sets colors on the regions previously described. Syntax is as follows for both commands, where bracketed items are single bytes, len+off are 3 ascii bytes interpreted as base-10, and r+g+b are 2 ascii bytes each interpreted as hex. The color set command supports a variable number of regions as shown:

Region Set Command

!c[regionId][stripId][len2][len1][len0][off2][off1][off0]\r

Color Set Command

!b[r1][r0][g1][g0][b1][b0][numRegions][regionId0]([regionId1]...)\r

Each command sends positive/negative acknowledgements so you'd think I'd be able to tell what's going wrong, but I get unexpected behavior when I try to set light colors with the second command, however, despite getting acknowledgements as expected. So far, the only reasonable conclusion I can come to is that for the global array regions discards changes and stays zero always. For example, this exchange results in no lights lit (comments are not in the actual exchange)

Pi sends: !c00144000\r  // create regionId 0 on stripId 0; length 144 offset 0
Pi recieves: O          // positive confirmation?
Pi sends: !b00009910\r  // set regionId 0 to color 0x000099 (blue)
Pi recieves: O          // positive confirmation, but no lights?
Pi sends: !x\r          // invalid command; triggers default in switch
Pi recieves: X          // as expected, all lights turn red

Here's the stripped down source for the Arduino:

#include "Arduino.h"
#include "FastLED.h"
#define WAIT while(!Serial.available()) ;; 

// Forward Declarations
const int max_strips = 2;
const int max_strip_length = 300;
const int max_leds = max_strips * max_strip_length;
CRGB leds[max_strips][max_strip_length];

const int max_regions = 20;
int regions[max_regions][3];

const int baud_rate = 9600;
unsigned char buffer[64];
unsigned char currentByte = 0;
unsigned char incommingByte;
unsigned char startChar = '!';
unsigned char endChar = '\r';
bool store = false;

// Helper Functions
void set(CRGB c) {
  for(int i = 0; i < max_strips; i++) {
      for(int j = 0; j < max_strip_length; j++) {
          leds[i][j] = c;
      }
  }
}

void set(int stripId, int length, int offset, CRGB c) {
    for(int i = offset; i < offset+length; i++) {
        leds[stripId][i] = c;
    }
}

void setup() {
  Serial.begin(baud_rate);
  for(int i = 0; i < max_strips; i++) {
      switch(i) {
          case 0: {
              FastLED.addLeds<WS2812B, 2, GRB>(leds[0], max_strip_length);
          } break;
          case 1: {
              FastLED.addLeds<WS2812B, 3, GRB>(leds[1], max_strip_length);
          } break;
      }
  }
  set(CRGB::Black);
}

void loop() {
    if(Serial.available() > 0) {
        unsigned char incomingByte = Serial.read();
        if(incomingByte == startChar) {
            currentByte = 0;
            store = true;
        }
        if(store) {
            if(incomingByte == endChar) {
                buffer[currentByte++] = incomingByte;
                store = false;
                switch(buffer[1]) {
                    case 'b': {
                        int red = (buffer[2] - '0')*16 + (buffer[3] - '0');
                        int green = (buffer[4] - '0')*16 + (buffer[5] - '0');
                        int blue = (buffer[6] - '0')*16 + (buffer[7] - '0');
                        int numRegions = buffer[8] - '0';

                        for(int i = 0; i < numRegions; i++) {
                            int regionId = buffer[9+i] - '0';

                            if(regionId >= max_regions) {
                                Serial.write('S');
                                return;
                            }

                            // Never sets anything
                            set(regions[regionId][0], regions[regionId][1], regions[regionId][2], CRGB(red, green, blue));
                        }

                        Serial.write('O');
                    } break;

                    case 'c': {
                        int regionId = buffer[2] - '0';
                        int stripId = buffer[3] - '0';
                        int length = (buffer[4] - '0')*100 + (buffer[5] - '0')*10 + (buffer[6] -'0');
                        int offset = (buffer[7] - '0')*100 + (buffer[8] - '0')*10 + (buffer[9] -'0');

                        if(regionId >= max_regions) {
                            Serial.write('R');
                            return;
                        }

                        if(stripId >= max_strips) {
                            Serial.write('S');
                            return;
                        }

                        regions[regionId][0] = stripId; // WE LOSE THESE VALUES??
                        regions[regionId][1] = length;  // ??
                        regions[regionId][2] = offset;  // ??

                        Serial.write('O');

                    } break;

                    default: {
                        set(CRGB::Red);
                        Serial.write('X');
                    } break;
                }
                currentByte = 0;
            }else if(currentByte > 64){
                store = false;
                currentByte = 0;
            } else {
                buffer[currentByte++] = incomingByte;
            }
        }
    }
    FastLED.show();
}

I'd appreciate any advice as to what I'm missing here, and regardless, thanks for reading this far!

1

1 Answers

0
votes

This was occurring because I have a lot of garbage showing up on the serial interface for the Arduino I'm testing on. Slowing the baud rate down to 2400bps resolves the issue on this device. Other Arduinos in the system do fine with much higher serial rates -- I suspect there's a hardware problem with the crystal on this particular Arduino so clock speeds aren't matching up correctly between the two sides of the serial connection.