我有2个不同的LED环。(一个有16个LED,另一个有24个)我想从处理IDE中制作一个界面,在那里我可以选择一种颜色并将这种颜色发送到选定的环。这是arduino代码:
#include <FastLED.h>
#define LED_PIN1 3
#define LED_PIN2 12
#define NUM_LEDS1 16
#define NUM_LEDS2 24
CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];
int r,g,b;
boolean state = false;
void setup() {
FastLED.addLeds<WS2812, LED_PIN1, GRB>(leds1, NUM_LEDS1);
FastLED.addLeds<WS2812, LED_PIN2, GRB>(leds2, NUM_LEDS2);
Serial.begin(9600);
}
void loop() {
String returnedInput = rgbInput();
String red = returnedInput.substring(0,3); //get 3 values like 255
String green = returnedInput.substring(4,7);
String blue = returnedInput.substring(8,11);
Serial.println(red);
Serial.println(green);
Serial.println(blue);
int r = red.toInt();
int g = green.toInt();
int b = blue.toInt();
if (Serial.available()){
char val = Serial.read();
if(val == '2') { //selects the second LED ring
if(state == false) {
state = true;
for(int i = 0 ; i < 24 ; i++ ){
leds2[i] = CRGB(r, g, b); //turn on all the LEDs on the ring to the selected color
FastLED.show();
FastLED.clear();
FastLED.show();
}}}
}}
String rgbInput() {
//prompt for input
Serial.println("ready");
while(!Serial.available()) {
//if 0, it keeps waiting for the user to enter sth.
}
String userInput = Serial.readStringUntil("\n");
return userInput;
}
我为第二个LED写了这个,如果我可以管理这个,我会为另一个做同样的事情,但它不起作用。
这是处理代码:
import controlP5.*; //import ControlP5 library
import processing.serial.*;
Serial port;
ControlP5 cp5; //create ControlP5 object
PFont font;
PFont font2;
color col;
Serial serialMonitor;
String prompt;
ColorPicker cp;
void setup(){ //Same as setup in arduino
size(900, 900); //Window size, (width, height)
port = new Serial(this, "COM4", 9600); //Change this to your port
cp5 = new ControlP5(this);
font = createFont ("Georgia Bold", 20);
font2 = createFont ("Georgia Bold",15);
cp = cp5.addColorPicker("PICKER")
.setPosition(500,100)
.setColorValue(color(255,128,0,128))
;
Group configGroup = cp5.addGroup("CONFIGURATION")
.setPosition(90,100)
.setWidth(150)
.setHeight(30)
.setFont(font2)
.setBackgroundColor(color(0,0))
;
cp5.addButton("PICK_ALL") // The button
.setPosition(10, 10) // x and y relative to the group
.setSize(160, 150) // (width, height)
.setFont(font)
.setGroup(configGroup) // add it to the group
;
cp5.addButton("PICK_ONE") // The button
.setPosition(10, 200) // x and y relative to the group
.setSize(160, 150) // (width, height)
.setFont(font)
.setGroup(configGroup) // add it to the group
;
}
void draw(){ //Same as loop in arduino
background(150, 0 , 150); //Background colour of window (r, g, b) or (0 to 255)
}
public void controlEvent(ControlEvent c){
if(c.isFrom(cp)){
int r = int(c.getArrayValue(0));
int g = int(c.getArrayValue(1));
int b = int(c.getArrayValue(2));
int a = int(c.getArrayValue(3));
col = color(r,g,b,a);
}
}
void keyPressed(){
while(serialMonitor.available() > 0)
{
prompt = serialMonitor.readStringUntil (10);
}
println(keyCode);
String sendColor = nf(int(red(col)),3) + "," + nf(int(green(col)),3) + "," + nf(int(blue(col)),3);
println(sendColor);
serialMonitor.write(sendColor);
}
void PICKER(){
port.write('2');
}
void PICK_ALL(){
port.write('t');
}
void PICK_ONE(){
port.write('l');
}
我不完全知道如何获取 RGB 值并在 CRGB 函数中使用它们。使用使用 3 个引脚的单个 RGB LED 时要容易得多。但我无法将其实现到仅使用 1 个引脚的 LED 环上。
这是颜色拾取的处理界面。我可以选择颜色,但Arduino上的LED戒指没有任何变化。
可靠的串行通信并不简单。理想情况下,您可以使用自己的二进制通信协议设置一个字节包,其中包含一个标头,描述有多少后续字节实际具有数据,甚至可能还有校验和。
字符串可以开始使用,使用nf()
使数据更易于解析非常好。
一个潜在的陷阱可能是将字符串放在一起(rgbInput()
)和一次读取一个char(char val=Serial.read();
)之间的切换。
我建议将问题分解为更小的更简单的部分,测试/调试每个部分,然后一次将这些部分放回一起,以避免集成错误。
例如,主要的挑战似乎是串行通信,所以我会写一个处理和Arduino草图,以确保在添加LED控制之前可靠地工作。
让我们选择\n终止字符串的选项,即使它发送了一个多余的额外字符(例如port.write("2\n");
),它会使缓冲更简单:
trim()
换行符的字符串这是一个基本的Arduino草图,它使用了上述想法(以及一些代码;)):
void setup() {
Serial.begin(9600);
}
void loop() {
// check if there are at least two characters to receive
if(Serial.available() > 1){
// buffer the full string until a new line character
String returnedInput = Serial.readStringUntil('\n');
// remove white space (new line char)
returnedInput.trim();
// if it's a single command
if(returnedInput.length() == 1){
char state = returnedInput.charAt(0);
switch(state){
case '2':
Serial.println("parsed 2 command");
break;
case 't':
Serial.println("parsed t command");
break;
case 'l':
Serial.println("parsed l command");
break;
default:
Serial.print("unknown state:");
Serial.println(state);
break;
}
}
// if it's a RGB triplet
else if(returnedInput.length() == 11){
String redString = returnedInput.substring(0, 3); //get 3 values like 255
String greenString = returnedInput.substring(4, 7);
String blueString = returnedInput.substring(8, 11);
int r = redString.toInt();
int g = greenString.toInt();
int b = blueString.toInt();
// constrain values to bytes
r = constrain(r, 0, 255);
g = constrain(g, 0, 255);
b = constrain(b, 0, 255);
// do something with the values (e.g. store globally, etc.)
Serial.print("parsed RGB: #");
Serial.print(r, HEX);
Serial.print(g, HEX);
Serial.print(b, HEX);
Serial.println();
}
// otherwise error message ?
else{
Serial.print("Uknown command: ");
Serial.println(returnedInput);
}
}
}
这应该使用新的行终止符处理字符串消息,并根据修剪后的长度解析单个字符命令和 11 个字符的 RRR,GGG,BBB 字符串。
您可以直接使用Arduino的串行监视器进行测试。
在您的处理草图中,不清楚为什么有两个串行端口(端口
和串行监视器
)。
下面是您的处理草图的一个稍微修改的版本,它发送两个单字符命令或颜色字符串:
import controlP5.*; //import ControlP5 library
import processing.serial.*;
PFont font;
PFont font2;
// Arduino serial port
Serial port;
// colour picker values to send to Arduino
int r;
int g;
int b;
// GUI variables
ControlP5 cp5; //create ControlP5 object
ColorPicker cp;
void setup() { //Same as setup in arduino
size(900, 900); //Window size, (width, height)
try {
port = new Serial(this, "/dev/tty.usbserial-A104WS3R", 9600); //Change this to your port
// buffer until new line: this plugs in nicely with serialEvent()
port.bufferUntil('\n');
}catch(Exception e) {
println("error opening serial");
e.printStackTrace();
}
cp5 = new ControlP5(this);
font = createFont ("Georgia Bold", 20);
font2 = createFont ("Georgia Bold", 15);
cp = cp5.addColorPicker("PICKER")
.setPosition(500, 100)
.setColorValue(color(255, 128, 0, 128))
;
Group configGroup = cp5.addGroup("CONFIGURATION")
.setPosition(90, 100)
.setWidth(150)
.setHeight(30)
.setFont(font2)
.setBackgroundColor(color(0, 0))
;
cp5.addButton("PICK_ALL") // The button
.setPosition(10, 10) // x and y relative to the group
.setSize(160, 150) // (width, height)
.setFont(font)
.setGroup(configGroup) // add it to the group
;
cp5.addButton("PICK_ONE") // The button
.setPosition(10, 200) // x and y relative to the group
.setSize(160, 150) // (width, height)
.setFont(font)
.setGroup(configGroup) // add it to the group
;
}
void draw() { //Same as loop in arduino
background(150, 0, 150); //Background colour of window (r, g, b) or (0 to 255)
}
public void controlEvent(ControlEvent c) {
if (c.isFrom(cp)) {
r = int(c.getArrayValue(0));
g = int(c.getArrayValue(1));
b = int(c.getArrayValue(2));
}
}
void keyPressed() {
if(port == null){
println("no serial, ignoring");
return;
}
String sendColor = nf(r, 3) + "," + nf(g, 3) + "," + nf(b, 3) + '\n';
println("sending to Arduino:", sendColor);
port.write(sendColor);
}
void PICKER() {
println("PICKER");
if (port != null) port.write("2\n");
}
void PICK_ALL() {
println("PICK_ALL");
if (port != null) port.write("t\n");
}
void PICK_ONE() {
println("PICK_ONE");
if (port != null) port.write("l\n");
}
void serialEvent(Serial s){
println("from Arduino:", s.readString());
}
总体注意错误检查位:使用Serial时总是一个好主意:)
一旦按预期工作,您就可以组合FastLED
控件。
这里有个建议:
#include <FastLED.h>
#define LED_PIN1 3
#define LED_PIN2 12
#define NUM_LEDS1 16
#define NUM_LEDS2 24
CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];
// ring 1 color
int r1,g1,b1;
// ring 2 color
int r2,g2,b2;
// toggle wether to update r1,g1,b1 or r2,g2,b2 when a new colour arrives
boolean updateRing1 = true;
void setup() {
// setup serial
Serial.begin(9600);
// setup LEDs
FastLED.addLeds<WS2812, LED_PIN1, GRB>(leds1, NUM_LEDS1);
FastLED.addLeds<WS2812, LED_PIN2, GRB>(leds2, NUM_LEDS2);
}
void loop() {
handleSerial();
driveLEDRings();
}
void handleSerial(){
// check if there are at least two characters to receive
if(Serial.available() > 1){
// buffer the full string until a new line character
String returnedInput = Serial.readStringUntil('\n');
// remove white space (new line char)
returnedInput.trim();
// if it's a single command
if(returnedInput.length() == 1){
char state = returnedInput.charAt(0);
switch(state){
case '2':
Serial.println(F("parsed 2 command"));
break;
case 't':
Serial.println(F("parsed t command: switching to ring #1"));
updateRing1 = true;
break;
case 'l':
Serial.println(F("parsed l command: switching to ring #2"));
updateRing1 = false;
break;
default:
Serial.print(F("unknown state:"));
Serial.println(state);
break;
}
}
// if it's a RGB triplet
else if(returnedInput.length() == 11){
String redString = returnedInput.substring(0, 3); //get 3 values like 255
String greenString = returnedInput.substring(4, 7);
String blueString = returnedInput.substring(8, 11);
int r = redString.toInt();
int g = greenString.toInt();
int b = blueString.toInt();
// constrain values to bytes
r = constrain(r, 0, 255);
g = constrain(g, 0, 255);
b = constrain(b, 0, 255);
// do something with the values (e.g. store globally, etc.)
Serial.print(F("parsed RGB: #"));
Serial.print(r, HEX);
Serial.print(g, HEX);
Serial.print(b, HEX);
Serial.println();
// handle ring colour update
if(updateRing1){
r1 = r;
g1 = g;
b1 = b;
}else{
r2 = r;
g2 = g;
b2 = b;
}
}
// otherwise error message ?
else{
Serial.print("Uknown command: ");
Serial.println(returnedInput);
}
}
}
void driveLEDRings(){
//update ring 1
for(int i = 0 ; i < NUM_LEDS1; i++){
leds1[i] = CRGB(r1, g1, b1);
}
//update ring 2
for(int i = 0 ; i < NUM_LEDS2; i++){
leds2[i] = CRGB(r2, g2, b2);
}
// display
FastLED.show();
}
注意:上面的代码没有经过有线RGB LEDs的测试,所以它可能不工作,但希望它说明了这个想法。(您应该仔细检查波特率、引脚、RGB颜色通道等。)
如果使用串行监视器上述工作正常,您可以返回测试处理接口草图。
另外bare in mind 9600是一个相当低的波特率。您应该使用更高的波特率(例如115200、57600)进行测试,如果稳定,则使用这些波特率来避免在缓冲串行数据时驱动led的延迟。一般来说,尽可能避免/最小化阻塞(while)循环。
总的来说,这个想法是删除/删除代码中不需要的任何东西来深入研究问题:孤立地解决它。一旦调试并可靠地工作,每次添加一位新代码,在每次添加后进行测试(否则您可能会引入更多错误,而不是更难发现/修复的错误)。