Arduino - 读取串口数据

Arduino - Reading Serial Data

我正在尝试使用串行数据将信息发送到 Arduino Mega 2560,以控制 LED 像素条和传统圣诞灯串。我也在使用 VIXEN 灯光软件。

我可以在 Arduino loop() 函数中使用这段代码控制 Vixen 的一条 LED 像素;

          Serial.readBytes((char*)leds, NUM_LEDS * 3);//buffer to store things in, length (number of bytes to read)
          FastLED.show();//refresh the pixel LED's

我还可以使用此代码控制传统灯的一个继电器(或多个继电器);

#define CHANNEL_01 7 //Pin #7 on the Arduino Mega board

   void setup()
    {
      // Begin serial communication
      Serial.begin(BAUD_RATE);
      #define CHANNEL_COUNT 1 

    int channels[] = {CHANNEL_01}
    int incomingByte[16];
    // Define baud rate. This figure must match that of your profile configuration in Vixen!
    #define BAUD_RATE 9600 


      // Set up each channel as an output
      for(int i = 0; i < CHANNEL_COUNT; i++)
      {
        pinMode(channels[i], OUTPUT);
      }
    }

void loop()
{
  if (Serial.available() >= CHANNEL_COUNT)
  {
    // Read data from Vixen, store in array
    for (int i = 0; i < CHANNEL_COUNT; i++)
    {
      incomingByte[i] = Serial.read();
    }
    // Write data from array to a pin on Arduino
    for (int i = 0; i < CHANNEL_COUNT; i++)
    {
      digitalWrite(channels[i], incomingByte[i]);
    }
  }
}

问题是这两件事我都做不到。我可以将 150 字节的 LED 数据分配给 LED 灯条并且它工作正常,或者,我可以 运行 继电器并且它们工作正常。我一直无法弄清楚如何从串行数据中切出字节并将其发送到适当的引脚。例如,也许我想使用引脚 7 控制继电器,使用引脚 6 控制一条 LED 像素。

像素 LED 条消耗串行数据中的前 150 个字节数据。但是我怎样才能得到下一个字节来控制打开和关闭传统圣诞灯串的继电器呢?控制灯串的字节将是串行数据中的第 151 个字节。有没有办法指定第 151 个字节? Serial.read() 只是读取第一个字节(我认为)。用户如何遍历串行数据的字节并 select 只遍历他们想要的字节?

当您执行 Serial.readBytes((char*)leds, NUM_LEDS * 3); 时,您会读取前 150 个字节,假设您有 50 个 LED。因此,串行缓冲区中待处理的下一个字节将是第 151 个字节,因此,如果您在 Serial.readBytes((char*)leds, NUM_LEDS * 3); 之后调用 Serial.read(),您将获得该字节。 请注意,如果需要,您可以使用一个字节来控制 8 个继电器,每个继电器一位,使用 bitRead() 举个例子。

bool relayState[8];

Serial.readBytes((char*)leds, NUM_LEDS * 3);

byte relays = Serial.read();

for(byte i=0;i<8;i++){
  relayState[i] = bitRead(relays, i);
}

for(byte i=0;i<8;i++) {
  digitalWrite(relay[i], relayState[i]);
}

然后值为 1 将打开继电器 0,值为 2 将打开继电器 1,值为 3 将打开继电器 0 和继电器 1,依此类推

为了解决这个问题,我买了一个 Arduino Uno 来 运行 标准(非 LED)灯与 运行 Arduino MEGA 2560 上的 LED 灯分开。非 LED 灯在 Vixen Lights 软件中的一个控制器上 运行。控制器有 4 个输出(通道),一个用于每个非 LED 灯组。每个通道将控制固态继电器上的一条线路。 Arduino Uno 运行 使用此代码的继电器;

#define PIN1 7 //Pin number seven
#define PIN2 6 //Pin number six
#define PIN3 5 //Pin number five
#define PIN4 4 //Pin number four

#define BAUD_RATE 9600 //just running 4 relay switches so we don't need much speed
#define CHANNEL_COUNT 4 //there are 4 channels coming from the Vixen controller

int bt[4]; //a variable we will use in the loop section of code
int x; //another variable we will use in the loop section of code

void setup() {
    delay(1000); //a little delay to give Uno some time on startup
    Serial.begin(BAUD_RATE); //set the baud rate of the serial stream
    pinMode(PIN1, OUTPUT); //set the four pins on the Arduino Uno to output
    pinMode(PIN2, OUTPUT);
    pinMode(PIN3, OUTPUT);
    pinMode(PIN4, OUTPUT);

}

void loop() {
    if (Serial.available() >= CHANNEL_COUNT) { 
        for (X = 0; x < CHANNEL_COUNT; x++) { //for every channel...
            bt[x] = Serial.read(); //we read a byte from the serial stream buffer and store it in an array for later use
        }

        digitalWrite(PIN1, bt[0]);  //we tell the pins on the arduino what to do... 
        digitalWrite(PIN2, bt[1]);  //using the array of integers that holds the byte values from the serial stream...
        digitalWrite(PIN3, bt[2]); 
        digitalWrite(PIN4, bt[3]);

    }   

}

LED 的 运行 关闭 Vixen Lights 软件中的第二个控制器。我有两个 12 伏、50 像素的 WS2811 型 LED 灯条。 Arduino 使用可从 FastLED.io 免费下载的 FastLED 库。我发现 LED 灯条的串行流中有一个字节的垃圾数据,我必须越过该数据字节才能让 LED 接收正确的数据字节以控制它们的颜色、位置等我使用此代码 运行 我的 LED 关闭 Arduino MEGA 2560;

#include <FastLED.h> //include the FastLED library in the Arduino project
#define LED_PIN1 7 //I am going to run one strip of 50 LEDs off of pin 7 on the MEGA
#define LED_PIN2 6 //I am going to run a second strip of 50 LEDs off of pin 6 on the MEGA
#define BAUD_RATE 115200 
#define NUM_LEDS 50

//It took me some time to figure out that my two pixel strips are set 
//to different color codes. Why? I don't know, but they are.  
#define RGB_ORDER RGB //one of my pixel strips is set to use RGB color codes
#define BRG_ORDER BRG //the second strip came from the factory with BRG color codes

#define LED_TYPE WS2811 //what type of LEDs are they? Mine are WS2811, yours may be different.

//create an array to hold the FastLED CRBG code for each of the 50 pixels in the 
//first strip.
CRGB leds1[NUM_LEDS]; 

//create another array to hold the FastLED CRBG codes for each of the 50 pixels in 
//the second strip.
CRGB leds2[NUM_LEDS]; 

int g; //a variable we will use in the loop section

int bufferGarbage[1]; //THIS IS THE KEY TO MAKING THIS WHOLE THING WORK. WE NEED TO 
 //GET PAST THE FIRST MYSTERY BYTE THAT IS SENT TO THE ARDUINO MEGA FROM THE VIXEN 
 //LIGHTS SOFTWARE. So we create a variable we will use in the loop section of code. 

void setup() {
    delay(1000);
    Serial.begin(BAUD_RATE);
    pinMode(LED_PIN1, OUTPUT); //set our pins to output. PIN1 is pin 6 on the Arduino board.
    pinMode(LED_PIN2, OUTPUT); //set our pins to output. PIN2 is pin 7 on the Arduino board.

     //This line sets up the first pixel strip to run using FastLED
    FastLED<LED_TYPE, LED_PIN1, RGB_ORDER>(leds1, NUM_LEDS).setCorrection(TypicalLEDStrip); 

    //This line sets up the second pixel strip to run using FastLED
    FastLED<LED_TYPE, LED_PIN2, BRG_ORDER>(leds2, NUM_LEDS).setCorrection(TypicalLEDStrip); 
}

void loop() {
    if (Serial.available() >= 0) { //if there is data in the serial stream
           //bufferGarbage is to capture the first byte of garbage that comes across.
           //Without this the LED's are out of sync. 
           //In my case if I didn't capture this byte the first pixel on my 
           //second LED strip would match the color code that should be on the last 
           //pixel of the first strip. We don't do anything with this byte.
           //but we need to read it from the serial stream so we can move to the 
           //next byte in the stream.
           bufferGarbage[0] = Serial.read();  

        //then we need to populate the leds1 array so FastLED can tell the pixels what to do.
        //We have 50 pixels in the strip and each pixel has a CRGB property that uses 
        //a red, green, and blue attribute. So for each LED we need to capture 3
        //bytes from the serial stream. 50 LEDs * 3 bytes each means we need to read
        //150 bytes of data from the serial stream.
        for (g = 0; g < NUM_LEDS; g++) {
            Serial.readBytes( ( char*)(&leds1[g], 3);
        }
        for (g = 0; g < NUM_LEDS; g++) {//then we read the next 150 bytes for the second strip of LEDs
            Serial.readBytes( ( char*)(&leds2[g], 3);
        }

        FastLED.show(); //then we tell FastLED to show the pixels!

    }
}