Я использую стороннюю библиотеку SerialPort на основе WinAPI (SerialPort) в программе на C ++ для управления светодиодной полосой (iLED и цвет пикселя), но оказывается, что она работает только для одной команды - если я отправлюта же команда во второй раз, цвет этого пикселя принимает другой случайный цвет, и по какой-то причине первый светодиод тоже включается со случайным цветом.
Вот ссылка на видео о том, что происходит, когда запускается приведенный ниже упрощенный код, т. Е. Когда пикселям 3, 5 и 7 снова и снова выдается команда на красный, зеленый и синий цвета соответственно.https://drive.google.com/file/d/1RRAshnhPz96YGJtmETy3vuGi25QjxqJz/view?usp=drivesdk
Я подозревал, что Serial.read () не был синхронизирован, поэтому я добавил начальный байт, но, похоже, он тоже не работает, вот что делает код ниже.
Что происходит?
SerialPort.h (источник: https://blog.manash.me/serial-communication-with-an-arduino-using-c-on-windows-d08710186498)
#ifndef SERIALPORT_H
#define SERIALPORT_H
#define ARDUINO_WAIT_TIME 2000
#define MAX_DATA_LENGTH 255
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class SerialPort
{
private:
HANDLE handler;
bool connected;
COMSTAT status;
DWORD errors;
public:
SerialPort(char const *portName, unsigned long baudrate);
~SerialPort();
int readSerialPort(char *buffer, unsigned int buf_size);
bool writeSerialPort(char *buffer, unsigned int buf_size);
bool isConnected();
};
#endif // SERIALPORT_H
SerialPort.cpp (источник: https://blog.manash.me/serial-communication-with-an-arduino-using-c-on-windows-d08710186498)
#include "serialport.h"
SerialPort::SerialPort(char const *portName, unsigned long baudrate)
{
this->connected = false;
this->handler = CreateFileA(static_cast<LPCSTR>(portName),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (this->handler == INVALID_HANDLE_VALUE){
if (GetLastError() == ERROR_FILE_NOT_FOUND){
printf("ERROR: Handle was not attached. Reason: %s not available\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else {
DCB dcbSerialParameters = {0};
if (!GetCommState(this->handler, &dcbSerialParameters)) {
printf("failed to get current serial parameters");
}
else {
dcbSerialParameters.BaudRate = baudrate;
dcbSerialParameters.ByteSize = 8;
dcbSerialParameters.StopBits = ONESTOPBIT;
dcbSerialParameters.Parity = NOPARITY;
dcbSerialParameters.fDtrControl = DTR_CONTROL_ENABLE;
if (!SetCommState(handler, &dcbSerialParameters))
{
printf("ALERT: could not set Serial port parameters\n");
}
else {
this->connected = true;
PurgeComm(this->handler, PURGE_RXCLEAR | PURGE_TXCLEAR);
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
SerialPort::~SerialPort()
{
if (this->connected){
this->connected = false;
CloseHandle(this->handler);
}
}
int SerialPort::readSerialPort(char *buffer, unsigned int buf_size)
{
DWORD bytesRead;
unsigned int toRead;
ClearCommError(this->handler, &this->errors, &this->status);
if (this->status.cbInQue > 0){
if (this->status.cbInQue > buf_size){
toRead = buf_size;
}
else toRead = this->status.cbInQue;
}
if (ReadFile(this->handler, buffer, toRead, &bytesRead, NULL)) return bytesRead;
return 0;
}
bool SerialPort::writeSerialPort(char *buffer, unsigned int buf_size)
{
DWORD bytesSend;
if (!WriteFile(this->handler, (void*) buffer, buf_size, &bytesSend, 0)){
ClearCommError(this->handler, &this->errors, &this->status);
return false;
}
else return true;
}
bool SerialPort::isConnected()
{
return this->connected;
}
main.cpp
#include <iostream>
#include "serialport.h"
using namespace std;
int main()
{
SerialPort serial("COM3", 115200);
while(1) {
unsigned char buffer[] = {255,3, 254, 0, 0};
serial.writeSerialPort((char*)buffer, 4);
unsigned char buffer2[] = {255,5, 0, 254, 0};
serial.writeSerialPort((char*)buffer2, 4);
unsigned char buffer3[] = {255,7, 0, 0, 254};
serial.writeSerialPort((char*)buffer3, 4);
}
return 0;
}
Прошивка Arduino
#include <FastLED.h>
#define BAUDRATE 115200
#define N_BYTES_MSG 4
#define N_LEDS 120
#define DATA_PIN 6
CRGB leds[N_LEDS] = {0};
void setup() {
FastLED.addLeds<WS2811, DATA_PIN, BRG>(leds, N_LEDS); //I don't know why the colours are BRG on this strip
FastLED.show();
Serial.begin(BAUDRATE);
}
void loop() {
//Check for a quadruplet of bytes (iLED R G B) led by start byte
if(Serial.available() >= N_BYTES_MSG+1 && Serial.read() == 255) {
//Read message
unsigned char buf[N_BYTES_MSG] = {0};
for(unsigned char i=0; i < N_BYTES_MSG; i++) {
buf[i] = Serial.read();
}
if(buf[0] < N_LEDS) { //Valid ID
leds[buf[0]] = CRGB(buf[1],buf[2],buf[3]); //Update LED state in internal representation
FastLED.show(); //Refresh LEDs based on internal representation
}
}
}
Обратите внимание, что светодиодная лента, кажется, работает нормально сама по себе, так как я успешно проверил движение с постоянной скоростью на один пиксель.Самый простой путь отладки, который у меня есть, так как мне еще не удалось заставить readSerialPort () работать, и COM-порт перегружен программой, поэтому я не могу понять его (можем ли мы как-то это понюхать?).