В настоящее время я работаю над проектом, который требует последовательной связи между скомпилированной программой g ++ и Arduino ATMega2560 с использованием termios в качестве средства последовательной связи. Программа g ++ отправляет массив из 5 значений uint8_t, которые анализируются Arduino. Затем Arduino использует эти байты для включения определенного светодиода на полосе.
Вот код для программы C ++, скомпилированной с 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);
}
}
А вот и эскиз Arduino:
#включают
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 прекрасно берет первые два байта и правильно интерпретирует первый байт каждой группы из 5, отправляемый как 0x73 (также известный как ‘s’), но следующие байты в группе не читаются должным образом и интерпретируются окончательно Ардуино как значения 255.
Ожидаемый результат:
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, но это ничего не исправило.
Редактирование: Другая проблема заключается в том, что после четырех или пяти итераций установки светодиодов зеленый канал случайным образом выпадает, поэтому все, что получает Arduino, является еще более искаженным {‘s’, 255, 0, 255, 255}.
Ваш внутренний цикл while(true)
не оценивает Serial.available. Таким образом, он пытается прочитать, даже если нет данных. Это когда он получает 255 вместо ожидаемых значений. Есть много способов это исправить. Один из способов — заблокировать данные.
...
while (true) {
while (!Serial.available()) {}
...
Других решений пока нет …