SoftwareSerial ist für Arduino/AVR auf 57600 Bd begrenzt:
- On Arduino or Genuino 101 boards the current maximum RX speed is 57600bps.
Jedenfalls gemäß dieser Doku https://docs.arduino.cc/learn/built-in-libraries/software-serial/
Ist aber ziemlich egal, da man den kompletten Led-Kettenstatus in 8 Byte unterbringen kann, die bei 57600 Bd mit 5760 Byte/s übertragen werden können, also alle 1,4 ms oder theoretisch(!!) 720 mal pro Sekunde. Das wird nicht benötigt.
Ich habe mal eine Testumgebung mit einem UNO und einem NANO und einer 60er-Led-Kette hergestellt, wobei der UNO den Status der 60 Leds binär festlegt, per SoftwareSerial mit 57600 Bd an den NANO überträgt und der NANO die Umsetzung zu den WS2812B-Leds umsetzt.
Beide zusätzlich mit dem Hardware-Signal verbunden, das der NANO setzt, während er Daten zu den Leds schauffelt. Klappt bei mir problemlos:
Sketche und Verdrahtung
Sketch UNO:
#include <SoftwareSerial.h>
constexpr byte SIGNAL_PIN{ 4 };
constexpr byte rxPin{ 5 };
constexpr byte txPin{ 6 };
constexpr int NUM_LEDS{ 60 };
byte ledStates[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int noOfBytes = sizeof(ledStates) / sizeof(ledStates[0]);
SoftwareSerial mySerial(rxPin, txPin);
void setup() {
pinMode(SIGNAL_PIN,INPUT);
Serial.begin(115200);
Serial.println("Control Leds Via SoftwareSerial");
mySerial.begin(57600);
}
void loop() {
runEvery(10);
}
void runEvery(unsigned long interval) {
static unsigned long lastEvent = 0;
static int count = 0;
if (millis() - lastEvent > interval) {
lastEvent = millis();
while (digitalRead(SIGNAL_PIN) == LOW) { delayMicroseconds(50); };
for (int i = 0; i < noOfBytes; i++) {
mySerial.write(ledStates[i]);
}
clearLeds();
setLedNo(count);
setLedNo(NUM_LEDS-count-1);
count++;
if (count >= NUM_LEDS) {
count = 0;
}
}
}
void setLedNo(int num) {
if (num < NUM_LEDS) {
int index = num / 8;
int actBit = num - index * 8;
byte actByte = ledStates[index];
ledStates[index] = actByte | (0x01 << actBit);
}
}
void clearLeds() {
for (int i = 0; i < noOfBytes; i++) {
ledStates[i] = 0;
}
}
Sketch NANO
#include <FastLED.h>
#include <SoftwareSerial.h>
constexpr int NUM_LEDS {60};
constexpr byte DATA_PIN { 3};
constexpr byte SIGNAL_PIN { 4};
constexpr byte rxPin { 5};
constexpr byte txPin { 6};
// SoftwareSerial object
SoftwareSerial mySerial (rxPin, txPin);
CRGB leds[NUM_LEDS];
constexpr int noOfBytes = 8;
byte ledStates[noOfBytes];
int no = 0;
void setup() {
pinMode(SIGNAL_PIN,OUTPUT);
digitalWrite(SIGNAL_PIN, HIGH);
Serial.begin(57600);
Serial.println("LedStrip_Timing");
mySerial.begin(57600);
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
}
byte count = 0;
void loop() {
evaluateMySerial();
}
void evaluateMySerial(){
if (mySerial.available()){
char c = mySerial.read();
ledStates[no] = c;
no++;
if (no >= noOfBytes){
while (mySerial.available()){char c = mySerial.read();}; // Clear Buffer after 8 bytes to remove CR/LF/NL
no = 0;
setLeds();
}
}
}
void setLeds() {
int startPos = 0;
for (int i = 0; i < noOfBytes;i++){
byte actByte = ledStates[i];
for (int j = 0; j < 8;j++){
int ledIndex = startPos+j;
if (ledIndex < NUM_LEDS){
if (actByte & 0x01 == 0x01) {
leds[ledIndex] = CRGB::Green;
} else {
leds[ledIndex] = CRGB::Black;
}
actByte = actByte >> 1;
}
}
startPos += 8;
}
digitalWrite(SIGNAL_PIN, LOW);
FastLED.show();
digitalWrite(SIGNAL_PIN, HIGH);
}
Das kann man sicher noch wesentlich(!) geschickter programmieren, hat mir aber als Test so genügt. Das Update der Led-Kette wird vom UNO alle 10 ms angestoßen, soweit der NANO nicht gerade "beschäftigt" ist. Die Anzahl der Leds ist durch die 8 Bytes auf 64 beschränkt, das ließe sich aber ebenfalls leicht anpassen, falls benötigt.
Für einen realen Einsatz würde man sicherlich auch noch eine Start-Synchronisierung der SoftwareSerial-Daten implementieren, um definierte Startbedingungen für beide Controller sicherzustellen.
Der Vorteil der Übertragung des Bitfeldes ist es, dass nur einer (in diesem Fall der UNO) den aktuell gewünschten Stand der leuchtenden bzw. nichtleuchtenden Led kennen muss. Der zweite Controller (hier der NANO) braucht sich für das nächste Update nichts zu merken, da bei jedem Update immer alle Zustände übertragen werden.
Gruß
ec2021


