문제

I'm currently working on a project that requires serial communication between a g++ compiled program and an Arduino ATMega2560 using termios as a means of serial communication. The g++ program sends an array of 5 uint8_t values that are parsed by the Arduino. The Arduino then uses these bytes to turn on a particular LED on a strip.

Here is the code for the C++ program compiled with g++:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <termios.h>
    #include <inttypes.h>
    #include <fcntl.h>
    #include <fstream>
    #include <iostream>

    #define BAUD B115200
    #define ARDUINO "/dev/ttyACM0"

    using namespace std;

    struct termios old_io, new_io;
    int arduinoFD, c, res;

    int main (int argc, char* argv[]) {

   arduinoFD = open(ARDUINO, O_RDWR | O_NOCTTY);
   if (arduinoFD < 0){perror(ARDUINO); exit(EXIT_FAILURE);}

   new_io.c_cflag = BAUD | CRTSCTS | CS8 | CLOCAL | CREAD;
   new_io.c_iflag = IGNPAR | ICRNL;
   new_io.c_oflag = 0;
   new_io.c_lflag = ICANON;
   cfsetospeed(&new_io, BAUD);
   cfsetispeed(&new_io, BAUD);
   tcflush(arduinoFD, TCOFLUSH);

       //Byte that tells the arduino to start parsing.
   uint8_t* STARTCMD = (uint8_t*)malloc(1);
   STARTCMD[0]=0x0A;
   write(arduinoFD, STARTCMD, 1);

       //Enable debugging.
   STARTCMD[0]=(uint8_t)'d';
   write(arduinoFD, STARTCMD, 1);

       while(true){
          //Allocate array for LED info.
          uint8_t* testWrite = (uint8_t*)malloc(5);
          for(uint8_t i = 0; i < 240; i++){
             //Loop through all LEDs, setting their (R,G,B) to (220,220,220).
             testWrite[0] = 0x73; // 's'
     testWrite[1] = 0xc8; // Red - 220
     testWrite[2] = 0xc8; // Green - 220
     testWrite[3] = 0xc8; // Blue - 220
     testWrite[4] = (uint8_t)i; // Led Address - i

             //Print out the values to stdout.
     char* outPrint = (char*)malloc(17);
     sprintf(outPrint, "R%03dG%03dB%03dL%03d\n",
         testWrite[1], testWrite[2], testWrite[3], testWrite[4]);
     fwrite(outPrint,17,1,stdout);

             //Send the values from the buffer to the arduino, then sleep for 24 milliseconds.
     write(arduinoFD, testWrite, 4);
     usleep(24*1000);
      }
          //Deallocate the buffer and reallocate a space to send the update value.
      free(testWrite);
      testWrite = (uint8_t*)malloc(1);
      testWrite[0] = (uint8_t)'z';
      write(arduinoFD, testWrite, 1);

          //Deallocate and sleep for 550ms.
      free(testWrite);
      usleep(550*1000);     
       }
    }

And here is the Arduino sketch: #include

    Adafruit_NeoPixel strip = Adafruit_NeoPixel(240, 6, NEO_GRB + NEO_KHZ800);

    int pinRangeStart = 0;
    int pinRangeStop = 0;
    char inByte;
    uint8_t* colorBytes;
    boolean debug = false;

    void setup(){
      Serial.begin(115200);
      while(!Serial);

      Serial.print("Desktop LED Ambience\n");

      strip.begin();
      strip.show();
    }

    void loop(){  
      while(Serial.available() > 0){
        while(Serial.read() != 0x0A);
        Serial.print("Start Byte read!");

        while(true){
          //inByte is the first of 5 bytes to be read. The other four are (R,G,B,L) where
         //R = Red
         //G = Green
         //B = Blue
         //L = LED Number.
          inByte = Serial.read();
          switch(inByte){
            case('r'): {
              for(int i = 0 ; i < strip.numPixels(); i++)
                strip.setPixelColor(i, strip.Color(0,0,0));
              strip.show();
              Serial.println("Reset!");
              Serial.flush();
              break;
            }
            case('d'): {
              Serial.print("Debugging ");
              debug =! debug;
              if(!debug)  
                Serial.println("DISABLED");
              else
                Serial.println("ENABLED");
              break;
            }
            case('s'): {
              colorBytes = new uint8_t[4];
              colorBytes[0] = Serial.read(); // Red
              colorBytes[1] = Serial.read(); // Green
              colorBytes[2] = Serial.read(); // Blue
              colorBytes[3] = Serial.read(); // LED Number
              if(debug){
                Serial.println("Set lights without updating.");
                Serial.print("R=");
                Serial.println(colorBytes[0]);
                Serial.print("G=");
                Serial.println(colorBytes[1]);
                Serial.print("B=");
                Serial.println(colorBytes[2]);
                Serial.print("LED=");
                Serial.println(colorBytes[3]);
              }
              uint32_t newColor = strip.Color(colorBytes[0], colorBytes[1], colorBytes[2]);
              strip.setPixelColor(colorBytes[3], newColor);
              break;
            }
            case('z'): {
              strip.show();
              Serial.println("Updating Lights");
              break;
            }
          }
        }
      }  
    }

The output of the g++ program can be shown as a set of bytes, grouped together by {} to signify separate calls to write().

    {0x0a}
    {0x64}
    {0x73 0xc8 0xc8 0xc8 0x00}
    {0x73 0xc8 0xc8 0xc8 0x01}
    {...}
    {0x73 0xc8 0xc8 0xc8 0xee}
    {0x73 0xc8 0xc8 0xc8 0xef}
    {0x7a}

The arduino picks up the first two bytes just fine and properly interprets the first byte of every group of 5 being sent as 0x73 (also known as 's'), but the following bytes in the group are not properly read and wind up being interpreted by the Arduino as values of 255.

The expected output is:

    Desktop LED Ambience
    Start Byte read!
    Debugging ENABLED
    Set lights without updating.
    R=200
    G=200
    B=200
    LED=0
    Set lights without updating.
    R=200
    G=200
    B=200
    LED=1
    ...
    Set lights without updating.
    R=200
    G=200
    B=200
    LED=238
    Set lights without updating.
    R=200
    G=200
    B=200
    LED=239
    Updating Lights

And this is the actual output:

    Desktop LED Ambience
    Start Byte read!
    Debugging ENABLED
    Set lights without updating.
    R=255
    G=255
    B=255
    LED=255
    Set lights without updating.
    R=255
    G=255
    B=255
    LED=255
    ...
    Set lights without updating.
    R=255
    G=255
    B=255
    LED=255
    Set lights without updating.
    R=255
    G=255
    B=255
    LED=255
    Updating Lights

Would anyone happen to know what's causing this in my code? At first I thought that the bus was being saturated, so I tried reducing my baud rate to 19600, but it didn't fix anything.

Edit: Another problem is that after four or five iterations of setting LEDs, the Green channel randomly drops out, so all the Arduino gets is an even more misrepresented {'s', 255, 0, 255, 255}.

도움이 되었습니까?

해결책

Your inner loop while(true) does not evaluate Serial.available. Thus it tries to read even if no data is available. This is when it gets 255 instead of the expected values. There are many ways to fix this. One way would be to block till data is available.

...
while (true) {
    while (!Serial.available()) {}
...
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top