#include <SoftwareSerial.h>
SoftwareSerial Serial1(2, 3);
#include <FastLED.h>
#define LED_PIN 4
#define NUM_LEDS 120
CRGB leds[NUM_LEDS];
String comdata = "";
void setup()
{
Serial1.begin(9600);
unsigned char hexdata[7] = {0x04,0x00,0x00,0x00,0x00,0x0D,0x0A};
Serial1.write(hexdata,7);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
LEDS.showColor(CRGB(32, 0, 0));
delay(250);
LEDS.showColor(CRGB(0, 32, 0));
delay(250);
LEDS.showColor(CRGB(0, 0, 32));
delay(250);
LEDS.showColor(CRGB(32, 32, 32));
delay(250);
LEDS.showColor(CRGB(0, 0, 0));
}
void loop()
{
String comdata;
comdata=Serial1.readString();
for(int i = 0; i < comdata.length(); i++){
if ((comdata[i-1] == 0x0D)&&(comdata[i] == 0x0A)){
if (comdata[i-6] == 0x04){
if ((comdata[i-5] >= 0)&&(comdata[1] <= NUM_LEDS)){
leds [comdata[i-5]*3+1] = CRGB(comdata[i-4], comdata[i-3], comdata[i-2]);
FastLED.show();
leds [comdata[i-5]*3+2] = CRGB(comdata[i-4], comdata[i-3], comdata[i-2]);
FastLED.show();
leds [comdata[i-5]*3+3] = CRGB(comdata[i-4], comdata[i-3], comdata[i-2]);
FastLED.show();
}
if (comdata[i-5] == 0x7F){
fill_solid(leds, NUM_LEDS, CRGB(comdata[i-4], comdata[i-3], comdata[i-2]));
FastLED.show();
}
Serial1.print(comdata[i-6]);
Serial1.print(comdata[i-5]);
Serial1.print(comdata[i-4]);
Serial1.print(comdata[i-3]);
Serial1.print(comdata[i-2]);
Serial1.print(comdata[i-1]);
Serial1.print(comdata[i]);
}
}
}
comdata = "";
}
//定义D2、D3为软串口,实际接TTL转RS485模块
#include <SoftwareSerial.h>
SoftwareSerial Serial1(2, 3);
#include <FastLED.h>
#define LED_PIN 4
#define NUM_LEDS 120
CRGB leds[NUM_LEDS];
String comdata = “”;
void setup()
{
Serial1.begin(9600);
//开机在串口发送一串HEX字符串,04为假的RS485地址,0D 0A为结束符
unsigned char hexdata[7] = {0x04,0x00,0x00,0x00,0x00,0x0D,0x0A};
Serial1.write(hexdata,7);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
//LED自检
LEDS.showColor(CRGB(32, 0, 0));
delay(250);
LEDS.showColor(CRGB(0, 32, 0));
delay(250);
LEDS.showColor(CRGB(0, 0, 32));
delay(250);
LEDS.showColor(CRGB(32, 32, 32));
delay(250);
LEDS.showColor(CRGB(0, 0, 0));
}
void loop()
{
//串口接收字符串,实际使用效果很好,可以接收很长的连续字符串也不会丢数据,默认阻断时间是1000ms,可以通过修改C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino\Stream.h,Stream() {_timeout=1000;}这个参数实现阻断时间调节
String comdata;
comdata=Serial1.readString();
for(int i = 0; i < comdata.length(); i++){
//如果接收到0D 0A,就开始判断
if ((comdata[i-1] == 0x0D)&&(comdata[i] == 0x0A)){
//如果comdata[i-6] 即开头为04,假的RS485地址
if (comdata[i-6] == 0x04){
if ((comdata[i-5] >= 0)&&(comdata[1] <= NUM_LEDS)){
//每三个灯为一段,0号灯实际使用经常不正常工作,这里舍弃不用仅当信号中继
leds [comdata[i-5]*3+1] = CRGB(comdata[i-4], comdata[i-3], comdata[i-2]);
FastLED.show();
leds [comdata[i-5]*3+2] = CRGB(comdata[i-4], comdata[i-3], comdata[i-2]);
FastLED.show();
leds [comdata[i-5]*3+3] = CRGB(comdata[i-4], comdata[i-3], comdata[i-2]);
FastLED.show();
}
//不知为何这里的取值范围是-128 - 127,所以这里就用7F作为全开全关命令
if (comdata[i-5] == 0x7F){
fill_solid(leds, NUM_LEDS, CRGB(comdata[i-4], comdata[i-3], comdata[i-2]));
FastLED.show();
}
//打印已经处理的字节,可作为命令执行成功的标志
Serial1.print(comdata[i-6]);
Serial1.print(comdata[i-5]);
Serial1.print(comdata[i-4]);
Serial1.print(comdata[i-3]);
Serial1.print(comdata[i-2]);
Serial1.print(comdata[i-1]);
Serial1.print(comdata[i]);
}
}
}
comdata = “”;
}
实际使用结果不错,串口不会因为字符串太长丢失数据
最后附上调试开灯命令
04 01 0F 1F 3F 0D 0A
0x04=假RS485地址 01-7F
0x01=灯号 00-7F 7F为全部
0x0F=红色 00-FF 00为关
0x1F=绿色 00-FF 00为关
0x3F=红色 00-FF 00为关
0x0D,0x0A为命令结束标志
全开
04 7F 00 1F 1F 0D 0A
全关
04 7F 00 00 00 0D 0A
04 00 00 1F 1F 0D 0A
04 01 1F 00 00 0D 0A
04 02 00 1F 00 0D 0A
04 03 00 00 1F 0D 0A
04 04 00 0F 1F 0D 0A
04 05 1F 00 0F 0D 0A
04 06 00 1F 1F 0D 0A
04 07 1F 00 00 0D 0A
04 08 00 1F 00 0D 0A
04 09 00 00 1F 0D 0A
04 0A 00 0F 1F 0D 0A
04 0B 1F 00 0F 0D 0A
04 0C 00 1F 1F 0D 0A
04 0D 1F 00 00 0D 0A
04 0E 00 1F 00 0D 0A
04 0F 00 00 1F 0D 0A
04 10 00 0F 1F 0D 0A
04 11 1F 00 0F 0D 0A
04 12 00 1F 1F 0D 0A
04 13 1F 00 00 0D 0A
04 14 00 1F 00 0D 0A
04 15 00 1F 1F 0D 0A
04 16 1F 00 00 0D 0A
04 17 00 1F 00 0D 0A
04 18 00 00 1F 0D 0A
04 19 00 0F 1F 0D 0A
04 1A 1F 00 0F 0D 0A
04 7F 00 00 00 0D 0A