Hallo zusammen,
ich habe gerade ein kleines Problem. Ich möchte eine LED Matrix über die
Serielle Schnittstelle steuern. Im folgendem erst mal der Arduino Code:
Wenn ich beispielsweise den String
"0,255,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,0,255,0,255,0,0,255,0,0
,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,0,0,255
,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,0,0,255,0,0,255,0,0,255,255,0,0
,255,0,0,255,0,0,255,0,0,255,0,0,0,0,255,255,0,0,255,0,0,255,0,0,255,0,0
,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,0,255,0,255,0,0,255,0,0
,255,0,0,255,0,0,255,0,0,0,255,0," sende, dann nehmen alle LEDs die
richtige Farbe an, soweit so gut.
Wenn ich aber nach kurzer Zeit denselben (oder einen anderen) String
abschicke, wird auf der Matrix nur noch ein Haufen Schwachsinn
angezeigt.
Auf dem seriellem Monitor kann ich zunächst nur (durch
Serial.println(i); ) die Zahlen 0-48 sehen, so wie es ja sein sollte,
aber nach wenigen Sekunden taucht noch eine "0" auf. Und wenn man bevor
die "0" auftaucht einen weiteren String abschickt geht das Bild kaputt,
wenn man wartet, bis die "0" erscheint, ist alles ok.
Jetzt frage ich mich wieso überhaupt noch etwas empfangen wird. Ich
beschäftige mich noch nicht lange mit Serieller Kommunikation, deswegen
ist es möglich, dass ein sehr "billiger" Fehler vorliegt, sorry im
Voraus für mein Unwissen ^^
Lg
Janik Sch.
Hallo,
ich halte Deine Auswertung der ankommenden Daten für etwas gewagt.
Wie schickst Du diese und stellst so sicher, daß alle umgehend versebdet
werden und die Anzahl immer stimmt (Tippfehler usw.)
Wenn das erste Zeichen auftaucht, läßt Du mit Serial.parseInt() nach
Integer suchen und auswerten.
Wer sagt Dir, daß überhaupt schon genug Zeichen im seriellen Buffer
angekommen sind?
Einlesen, bis ein Komma kommt, dannd en Wert parsen und übergeben könnte
gehen. Außerdem NewLine o.ä. als Ende-Zeichen, damit Du den Kram wieder
auf Start bekommst, wenn die Anzahl mal nicht stimmte.
Du hörst nach 48 gewandelten Werten auf.
Ob die wirklich Deinen getrennten Werten entsprechen oder z.B. aus
0,255, plötzlich ein 0 2 55 für die ersten drei Werte wird, hängt so nur
davon ab, wie schnell die Zeichen kommen und bearbeitet werden können.
Gelesene Daten einem String zuordnen, bis ein Komma kommt.
Wandeln in int und merken.
Wenn 3 Werte für die Farben da sind, setRGB aufrufen.
Wenn alle Werte da sind und das letzte Zeichen Dein Endezeichen war,
FastLED.show() aufrufen.
Jedes eingelesen Zeichen auf Dein Endezeichen prüfen, wenn das kommt und
nicht ausreichend Daten da sind, abbrechen und Fehlermeldung.
Gruß aus Berlin
Michael
Hi, danke für die Antwort!
Ich habe bereits mit verschiedenen Versionen getestet. Ich habe den
ganzen String auslesen lassen, aber festgestellt, dass es in C wohl
relativ kompliziert ist einen String in Integer zu splitten... Ich habe
es jedenfalls nicht hinbekommen, hättest du ein Code Ausschnitt, der mir
aus einem String wie "255,0,24" drei integer gibt? Dann bräuchte ich ja
bei Serial.readUntilString() das Zeichen einsetzen, welches dann immer
nach drei Zahlen kommt, und es müsste funktionieren. Oder kann ich
einfach die Serial.readUntilString(',') machen und den Wert in einer
globalen Variablen speichern (zuerst r, dann g, dann b) und eine weitere
globale, die mir sagt, on es eben gerade r, g oder b ist? Oder wäre das
so unschön, dass jeden erfahrenem Programmierer die Haare ausfallen
würde? :D
Es ist unwahrscheinlich, dass eine andere Anzahl als 49*3 Zahlen
ankommen, da der Code computergeneriert wird, trotzdem kann ich das
versuchen zu fixen, aber ich bräuchte vielleicht einen Ansatz. Also ein
Link oder ein Beispiel für mein Problem, wäre supi :)
Lg
Hallo,
natürlich kannst Du mit Serial.readUntilString(',') die Werte lesen.
Gahen wir mal davon aus, daß der Datenblock immer ok ist.
1
if (Serial.available())
2
{
3
for (char i=0; i<48; i++)
4
{
5
String rot = Serial.readStringUntil(',');
6
char rotwert = rot.toInt();
7
String gruen = Serial.readStringUntil(',');
8
char gruenwert = gruen.toInt();
9
String blau = Serial.readStringUntil(',');
10
char blauwert = blau.toInt();
11
12
leds[i].setRGB(rot, gruen, blau);
13
}
14
}
15
16
FastLED.show();
sollte als Ansatz so klappen.
readStringUntil() liest bis zum Endezeichen oder bis timeout, wenn
nichts kommt.
toInt() liefert auch 0 zurück, wenn nichts sinnvolles im String war.
Gruß aus Berlin
Michael
Hallo Janik,
denn sende doch keine Integer !
Ich würde mir bei solch einer Anforderung, in einer geeigneten
Programmiersprache, eine anderes Datenprotokoll definieren.
Auf jeden Fall werden die Nutzendaten <rgbN> binär gesendet.
Die <Kopfdaten> könnten einfach eine fortlaufende Nunmmer sein;
die <crc-16> ist eine binäre 16 Bit CRC Checksumme.
<Kopfdaten><rgbN>..<crc-16>
Hallo,
wenn er LED-Nummer, RGB, \n für jede LED schickt, ist es ohnehin
flexibler, man kann einfach einzelne LEDs oder Gruppen umfärben.
Eine Prüfsumme kann man sich sehr wahrscheinlich hier sparen, so
lebenswichtig dürfte eine falsche LED-Farbe icht sein und Fehler habe
ich z.B. bei 30cm Kabel im Drahtverhau mit 115200 zwischen ProMini und
USB-Adapter bisher keine.
Gruß aus Berlin
Michael.
Wo ist eigentlich das Problem, einfach gleich Binärwerte zu senden?
ICH mache das in einer etwas größeren Anwendung (Arduino Mega und
RGB-Matrix 32x64) so, dass ich immer zuerst 2Byte für die Anzahl der
Pixel sende, dann die Pixelwerte und dann auf ein OK vom Arduino warte.
Kommt das zu früh oder nicht, weiss ich, da ist was schief gelaufen und
sende ggf. einfach binäre Nullen, bis es kommt ...
So ein Minimum an Handshake macht das Leben bedeutend einfacher :-)
Anderer Ansatz: Der Wert 1-1-1 (RGB) ist übrigens so dunkel, dass man
getrost auf 0-0-0 verzichten kann um dieses quasi als Synchronzeichen zu
verwenden.
Hallo Janik,
rechne dir bitte auch den Baudraten-Fehler für 115200 Bit/s bei Fclk =
16MHz aus !
Siehe Datenblatt, da sieht man schon, dass das vorhaben nicht klappen
kann.
Fall a) mit Vorteiler 1:16
16MHz/16/8 ==> 125,000 kBit/s
16MHz/16/9 ==> 111,111 kBit/s
Fall b) mit Vorteiler 1:8
16MHz/8/17 ==> 117,647 kBit/s
relativer Fehler
error = (1 - 117,647 kBit/s /115,200 kBit/s) *100
error = +2,12%
Hallo,
rechnerisch alles richtig.
Praktisch lief bei mir bisher 115200 mit den üblichen USB-TTL-Adaptern
immer zuverlässig an einem 16MHz AVR.
1,5% sind sicher, praktisch verkraften UARTs mit Mehrfachabtastung der
Bitzeit bis nahe 6% ohne aus dem Tritt zu kommen.
Ich habe hier jetzt mit einem Nano und 115200 nicht einen Fehler in den
übertragenen Daten seit ca. 10 Minuten Laufzeit im Loop.
Verlorene Bytes passieren da schneller, wenn der AVR noch mehr zu tun
hat, dann reicht sein serieller Puffer gern mal nicht aus, wenn man
nicht aufpaßt im Programm.
Gruß aus Berlin
Michael
Michael U. schrieb:> if (Serial.available())> {> for (char i=0; i<48; i++)> {> String rot = Serial.readStringUntil(',');> char rotwert = rot.toInt();> String gruen = Serial.readStringUntil(',');> char gruenwert = gruen.toInt();> String blau = Serial.readStringUntil(',');> char blauwert = blau.toInt();> Serial.println(i - '0'); //Von mir hinzugefügt> leds[i].setRGB(rot, gruen, blau);> }> }>> FastLED.show();
Hallo Leute, danke für die ganze Hilfe, ich kann leider wegen meinen
geringen Kenntnissen nicht mit allem was anfangen, aber ich bemühe mich
:)
Den Code habe ich sofort mal ausprobiert und das Ergebnis ist dasselbe
wie vorher. Nachdem die LEDs alle so leuchten, werden trotzdem noch
Bytes zurückgegeben! Ich habe im Code ein Serial.println eingefügt und
bekomme nach der einen Übertragung ungefähr alle 2-3 Sekunden eine
Antwort, wieso?? Mein Serieller Monitor sieht so aus:
-48
-47
-46
-45
-44
-43
-42
-41
-40
-39
-38
-37
-36
-35
-34
-33
-32
-31
-30
-29
-28
-27
-26
-25
-24
-23
-22
-21
-20
-19
-18
-17
-16
-15
-14
-13
-12
-11
-10
-9
-8
-7
-6
-5
-4
-3
-2
-1
-48
-47
-46
-45
-44
-43
-42
-41
-40
-39
-38
-37
-36
-35
-34
-33
-32
-31
-30
-29
-28
-27
-26
-25
-24
-23
-22
-21
-20
-19
-18
-17
-16
-15
-14
-13
-12
-11
-10
-9
-8
-7
-6
-5
-4
-3
-2
-1
Die Daten werden alle doppelt übertragen? Und wieso zuerst "instant" und
beim zweiten Mal dann mit einem so großem Abstand? Ich versteh das
wirklich nicht, vielleicht hat ja jemand ne Idee, weil dann könnte ich
ja auch mit meinem Ursprünglichem Code arbeiten, wenn diese merkwürdigen
Übertragungen nach der geplanten Übertragung verschwinden würden.
Lg