0

私は現在、シリアル通信の手段として termios を使用して、g++ でコンパイルされたプログラムと Arduino ATMega2560 の間のシリアル通信を必要とするプロジェクトに取り組んでいます。g++ プログラムは、Arduino によって解析される 5 つの uint8_t 値の配列を送信します。次に、Arduino はこれらのバイトを使用して、ストリップ上の特定の LED をオンにします。

以下は、g++ でコンパイルされた C++ プログラムのコードです。

    #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);     
       }
    }

そして、これが Arduino のスケッチです: #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;
            }
          }
        }
      }  
    }

{}g++ プログラムの出力は、 の個別の呼び出しを示すために によってグループ化された一連のバイトとして表示できますwrite()

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

arduino は最初の 2 バイトを問題なく取得し、送信される 5 つのグループごとの最初のバイトを 0x73 (「s」とも呼ばれます) として適切に解釈しますが、グループ内の次のバイトは適切に読み取られず、解釈されてしまいます。 255の値としてArduinoによって。

予想される出力は次のとおりです。

    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

そして、これは実際の出力です:

    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

私のコードでこれを引き起こしている原因を知っている人はいますか? 最初はバスが飽和していると思ったので、ボーレートを 19600 に下げてみましたが、何も修正されませんでした。

編集: もう 1 つの問題は、LED の設定を 4 回または 5 回繰り返した後、緑のチャネルがランダムにドロップアウトするため、Arduino が取得するのはさらに不正確な {'s', 255, 0, 255, 255} だけになることです。

4

1 に答える 1

1

内部ループwhile(true)は Serial.available を評価しません。したがって、データが利用できない場合でも読み取ろうとします。これは、期待値ではなく 255 を取得した場合です。これを修正するには多くの方法があります。1 つの方法は、データが利用可能になるまでブロックすることです。

...
while (true) {
    while (!Serial.available()) {}
...
于 2013-10-19T10:55:06.720 に答える