Hallo, ich bin relativ neu, was Mikrocontroller angeht und ab mal ne Frage. Ich hab in C# ein Programm geschrieben, mit dem ich auf meinem Arduino eine LED an und aus schalten kann. Das mach ich in dem ich einen String verschicke der 0 und 1 beinhaltet. Wenn ich jetzt mehrer LED´s mit PWM ansteuern will geht das ja so nicht. Ich würd es in 2 Bytes machen, 1. Byte die Adresse der LED (z.B. 1) und im 2.Byte würde dann der PWM Wert stehen. Wird das so normaler Weise gemacht und wie realisiere ich das ? Woher weis das Arduino Board welches das erste und welches das zweite Byte ist, wenn die alle nacheinander verschickt werden, wird sowas mit einem Start und Stop Bit gemacht ? Wäre super wenn mir jemand das eben erklärt oder mir eine Seite mit nem Tutorial schickt.
:
Verschoben durch Admin
Hallo. Ich weiß jetzt nicht genau wie "man" das genau machen sollte... Aber ich würde es so machen: Ich würde den PWM-Wert von 0-255 gehen lassen (also genau 1 Byte), und dann einfach immer bei jeder Wertänderung immer 8 Bytes senden (wenn du 8 LEDs hast). Also wenn du nur die 3. LED mit dem Wert 128 ansteuern willst und die anderen bei 0 liegen sollen: 00000000, 00000000, 00000001, 00000000, 00000000, 00000000, 000000000, 00000000 Nein, ein Start bzw Stopbit brauchst du nicht. Du kannst ja sagen, sobald 8 Bit im Buffer liegen, soll er den Auslesen. Damit hast du die einkommenden Daten immer in der Reihenfolge, wie sie verschickt wurde, und zusätzlich noch in Bytes getrennt. lg
:
Bearbeitet durch User
Danke für die schnelle Antwort, meinst du nicht 10000000 ? Ich meine Start und Stop Bit, wenn jetzt ein interrupt oder so mal dazu kommt oder ein Byte "verschluckt" wird ist ja ALLES hinfällig, mir ist grad das DMX Protokoll in den Sinn gekommen, sowas wäre doch genau richtig oder nicht ? Ich hatte ja wie gesagt eigentlich vor nur bestimmte werte zu senden und nicht alle. Also am liebsten würde ich ja immer im 1.Byte die Adresse und im 2. Byte den PWM Wert verschicken, also nur das was immer gebraucht wird, kann mir dazu jemand ein Beispiel schicken/schreiben ?
Mach doch ne Art Midi, Datenbytes < 127 und Steuerbytes >= 127. Also Led1 wäre 127, LED2 128 usw. Verlierst halt ein bisschen Dynamik da du nur noch Werte bis 127 übertragen kannst, aber wenn dich das nicht stört... Gruß Jonas
Frederik Wayn schrieb: > Woher weis das Arduino Board welches das erste und welches das zweite > Byte ist, wenn die alle nacheinander verschickt werden, wird sowas mit > einem Start und Stop Bit gemacht ? Wenn du serielle Daten verschickst, sorgen Start- und Stop-Bits dafür, dass die einzelnen Bits richtig einem Byte zugeordnet werden. Zum Auseinanderhalten deiner Bytes brauchst du einen anderen Mechanismus. Üblicherweise verwendet man spezielle Vereinbarungen für die übertragenen Bytes, um die Synchronisation zwischen Sender und Empfänger sicher zu stellen. Bei Midi sind das die Aufspaltung der Werte für Adressen und Daten, bei Textübertragung z.B. die Beschränkung auf Buchstaben/Zahlen und Zeilenende (CR, LF), bei Binärübertragung von Blöcken ein fester Datenrahmen mit Synchronisationszeichenfolge, Blocklänge, Dateninhalt und Prüfsumme. Da sind deiner Phantasie keine Grenzen gesetzt. Du musst nur sicher stellen, dass der Empfänger, auch wenn er mal außer Tritt geraten ist, feststellen kann, wo eine neue Übertragung beginnt. Für deine LED-Steuerung könntest du z.B. auch immer ein Startzeichen senden (z.B. "$") und dann direkt hintereinander die Helligkeitswerte als Hexadezimalwerte, also bei 3 LEDs "$A01080" bei Helligkeiten 0xA0, 0x10 und 0x80. Das macht die Struktur sehr einfach, ist aber natürlich ineffizent, wenn du viele LEDs hast, die ihre Helligkeit nur selten ändern. Das hängt also auch von der Anwendung ab.
Danke für eure Antworten, Wolfgang, meinst du alles in einem Byte, Start, led Adresse und Helligkeit? Mir geht es hauptsächlich darum, mich mit der Seriellen Schnittstelle zu beschäftigen und deswegen will ich das nicht als String sondern als Byte, entweder als Hex oder Bin. Wäre super wenn du das noch mal genau erläutern könntest
Frederik Wayn schrieb: > und deswegen will ich das nicht als String sondern als Byte, entweder als > Hex oder Bin Wenn du die Daten in Bytes ohne Verwendung eines Datenrahmen übertragen möchtest, muss jedes Byte für sich vollständig vom Empfänger interpretierbar sein, z.B. indem von den 8 Bit die oberen 2 Bit die Adresse darstellen und die unteren 6 Bit die Helligkeit. Damit könnte man also gerade für 4 LEDs die Helligkeit in 64 Stufen übertragen. Oder bei 3 Adressbits blieben 5 Bits für 32 Helligkeitsstufen. Wenn man mehr als die 8 Bit braucht, damit der Empfänger weiss, was er damit anfangen soll, muss der die nacheinander gesendeten Bytes unterscheiden können, indem z.B. besondere Byte für Synchronisation reserviert sind, die in den Daten dann nicht auftreten können. DMX als Beispiel wurde oben schon genannt http://de.wikipedia.org/wiki/DMX_%28Lichttechnik%29#Zeitliches_Protokoll
Ich wollte mit 2 Byte´s arbeiten und einem Start Bit. -Startbit -Adressbyte (für die LED) -PWM Byte (für die Helligkeit) Ich hab nur absolut keine Ahnung wie ich das programmiertechnisch machen soll, muss ich das Startbit vorgeben oder macht das die Serielle Schnittstelle "Automatisch"? Ist ja eigentlich egal ob ich das Binär oder Hexadezimal mache oder ? Wie würde das in C# aussehen? Ich hab gestern einen Wert binär verschickt und testweise über einen Seriellen Monitor ausgelesen, dabei entstehen immer ASCII Zeichen wie "&". Das würde Arduino auch machen oder? Wieso zeigt er bei "00100110" dann nicht die Zahl 38 an?
Frederik Wayn schrieb: > Ich wollte mit 2 Byte´s arbeiten und einem Start Bit. > > -Startbit > -Adressbyte (für die LED) > -PWM Byte (für die Helligkeit) Du kannst über die serielle Schnittstelle keine einzelnen Bits übertragen, wenn du nicht schmutzige Tricks anwenden willst, die aber vom API auf dem PC dann (höchstwahrscheinlich) nicht unterstützt werden. Der UART sorgt (normalerweise) automatisch dafür, dass die 8 Bit eines Byts mit Start- und Stop-Bit umrahmt auf die Leitung gehen. http://de.wikipedia.org/wiki/UART
Samuel J. schrieb: > 00000000, 00000000, 00000001, 00000000, 00000000, 00000000, 000000000, > 00000000 > > Nein, ein Start bzw Stopbit brauchst du nicht. > Du kannst ja sagen, sobald 8 Bit im Buffer liegen, soll er den Auslesen. > Damit hast du die einkommenden Daten immer in der Reihenfolge, wie sie > verschickt wurde, und zusätzlich noch in Bytes getrennt. Und wenn eins verlorengeht oder der µC erst angeschlossen wird, wenn der PC schon sendet, ist bis auf weiteres alles komplett durcheinander. Natürlich braucht man eine Erkennung von Anfang und Ende. Und die Daten als String zu übertragen ist für's Debugging auch hilfreich. Ich würde als Trennzeichen einfach ein Newline nehmen. Frederik Wayn schrieb: > Ich wollte mit 2 Byte´s arbeiten und einem Start Bit. > > -Startbit > -Adressbyte (für die LED) > -PWM Byte (für die Helligkeit) Ein "Startbit" kannst du nicht übertragen. Sowas gibt's, wie schon gesagt wurde, nur innerhalb der Übertragung eines Bytes, und das läuft automatisch. Ein einzelnes Bit kannst du nicht senden. > Ich hab nur absolut keine Ahnung wie ich das programmiertechnisch machen > soll, muss ich das Startbit vorgeben oder macht das die Serielle > Schnittstelle "Automatisch"? > > Ist ja eigentlich egal ob ich das Binär oder Hexadezimal mache oder ? Was verstehst du unter "Hexadezimal"? Eine serielle Schnittstelle überträgt immer binär. > Wie würde das in C# aussehen? Ich hab gestern einen Wert binär > verschickt und testweise über einen Seriellen Monitor ausgelesen, dabei > entstehen immer ASCII Zeichen wie "&". Das würde Arduino auch machen > oder? Wenn du es deinen Arduino als Text anzeigen läßt, ja. Was er sonst "macht", hängt ganz und gar davon ab, was du ihm sagst, was er damit machen soll. Das "&" ist nichts weiter als die Interpretation des Bytes als ASCII-Zeichen. > Wieso zeigt er bei "00100110" dann nicht die Zahl 38 an? Weil dein serieller Monitor die ankommenden Daten offenbar als Text interpretiert.
Danke schon mal da waren viele nützliche Informationen bei, Das mit dem Startbit ist mir wichtig, das er weis das zuerst die Adresse kommt und dann der PWM Wert, wenn jetzt aus irgendeinem Grund das Aressbyte verloren geht und er fängt mit dem PWM Byte und dann kommt das AdressByte ist ja alles hinfällig bis ich den Port schließe und wieder öffne (ich meine wenn ein Byte verloren geht ist es ja dann so: 1.PWM-->2.Adresse. Es soll aber so sein: 1.Adresse-->2.PWM)
Frederik Wayn schrieb: > Das mit dem Startbit ist mir wichtig, Auch wenn du dich auf den Kopf stellst - ein einzelnes Startbit gibt es für die serielle Übertragung mit einem UART nicht. Da mußt du dir etwas anderes einfallen lassen. Du kannst z.B. festlegen, dass eine Sendepause von einer bestimmten Mindestlänge den Bytezähler auf 0 setzt, falls du dir das leisten kannst.
Ähnlich HDLC Protokoll mit Asynchronous framing, ohne Adresse und mit byte stuffing und für Control die Länge der Nutzdaten. Das sind relativ viele Bytes für eine einzelne LED, dafür kannst du alles senden. Und auf Empfängerseite kannst du herrlich die ungültigen Daten verwerfen, denn der Empfänger synchronisiert sich selbst. Wenn du so ein enkodiertes Paket geschnürt hast, müssen Sender und Empfänger noch die gleiche Sprache sprechen. D.h. gleiche Baudrate, 8 oder 9 Bit, ob Paritätsbit und wieviel Stopbits. Könnte z.B. 8n1 sein. Der Arduino hat demnach einen Ringpuffer, wo jedes eingehende Zeichen abgelegt wird. Kommt nun das Zeichen der Framekennung herein, kannst du im Ringspeicher schauen, ob dort eventuell ein gültiges Paket vorhanden ist. Dann könntest du weitere Schritte unternehmen. Ein Paket könnte dann zwei Nutzbytes enthalten. Das Erste bezeichnet die Led und das zweite den PWM-Wert.
Wenn die Anwendung wirklich nur LED PWM ist wäre eine direkte Umsetzung von DMX zu über legen, dann kannst du sogar echtes Equipment dranhängen bei Gelegenheit. Wenn es dir ums Lernen der UART Schnittstelle geht wurde ja schon viel gesagt: Einzelnes Bit am Anfang geht nicht, das Startbit heißt so weil es den Datenframe begrenzt. lt Wikipedia kann ein UART Frame bis zu 9 bit lang sein aber keine Ahnung ob das im uC einfach umzusetzen ist. Das einzige was du über tragen kannst sind ganze Bytes, die Interpretation ist dir freigestellt. Ich hab letztens was ähnliches programmiert und einfach ein Timeout als Synchronisation benutzt, also: Die meiste Zeit keine Daten. Sobald 1 Byte kommt als Befehl interpretieren. Manche Befehle sind 1 Byte lang, andere erwarten bis zu 16 byte Daten. Wenn die korrekte Anzahl Bytes innerhalb von der Zeit ankommt, interpretiere den Befehl und sende ein Acknowledge zurück, sonst sende einen Fehlercode. Das geht nur dann hypothetisch schief, wenn du beständig immer was sendest, dann ist das naturgemäß natürlich unmöglich die auseinander zu halten. Der einzig andere Weg Bytes auseinander zu halten ist wie bereits erwähnt über die erlaubten Werte die so eins annimmt. Bei ASCII Übertragung ist das einfach, bei Binärwerten musst du dir selbst was über legen, zB Verzicht auf eine PWM Stufe und damit höchste 1 nur bei steuerbytes. Was mir sonst gerade noch einfällt ist die Stückelung der Daten auf Nibbles: 1. Byte Steuerdaten 0b1111xxxx für adressnibble (0 bis 15) 2. Byte Steuerdaten 0b0011yyyy falls mehr Adressen gewünscht zweites adressnibble 3. Byte Daten 0b0001aaaa höhere 4 bit Daten 4. Byte Daten 0b0000bbbb niedere 4 bit Daten Zusammensetzen dann mit Addr= xxxx<<8 | yyyy; Data= aaaa<<8 | bbbb; In jedem Fall kannst du mit einem sinnvollen Antwortcode prüfen, was passiert ist Das Prinzip kannst du sogar erweitern um bis zu 12bit Daten und Adresse zu senden, da bei 4 Moglichkeiten nur 2 bit die Art des Bytes bestimmen müssen.
Lenny D. schrieb: > ..., bei Binärwerten musst du dir selbst was über legen, zB Verzicht > auf eine PWM Stufe und damit höchste 1 nur bei steuerbytes. Der Verzicht auf eine PWM Stufe muss natürlich nicht unbedingt sein. Vielfach wird, um das zu vermeiden, das oben erwähne Byte Stuffing verwendet. Dazu wird, falls das als Steuerbyte verwendete Byte in den zu übertragenden Daten auftritt, der Datenwert durch eine Sondersequenz (z.B. doppeltes Steuerbyte) ersetzt. Der Empfänger muss das erkennen und wieder rückgängig machen. Für erste Versuche auf der seriellen Schnittstelle ist das aber etwas unübersichtlich.
Frederik Wayn schrieb: > Ich wollte mit 2 Byte´s arbeiten und einem Start Bit. > > -Startbit > -Adressbyte (für die LED) > -PWM Byte (für die Helligkeit) Das geht nicht. Wenn du wirklich zwei Bytes (also je 8 Bits) für die Nutzdaten brauchst, mußt du entweder mit 9 Datenbits pro seriellem Datenwort arbeiten, wobei dann das höchstwertige Bit des Datenworts darüber entscheidet, ob es sich um eine Adresse oder einen PWM-Wert handelt oder du bleibst bei Datenwörtern mit 8 Datenbits, mußt dann aber drei davon für eine Nachricht verwenden. Dann hast du mehr als genug Bits im Datenstrom über, um die Framestruktur abzubilden und das Frame insgesamt ziemlich gut gegen Empfangsfehler zu sichern. z.B. (nur ein Vorschlag, es gibt 'zig andere mögliche Varianten) 1. Byte Bit7: immer gesetzt (Kennzeichen für "StartOfFrame") Bit0..6: oberste sieben Bit der Adresse 2. Byte Bit7: niemals gesetzt (kein SOF) Bit1..6: unterste sechs Bit des PWM-Werts Bit0: unterstes Bit der Adresse 3. Byte Bit7: niemals gesetzt (kein SOF) Bit5..6: oberste zwei Bits des PWM-Werts Bit0..4: CRC5-Prüfsumme über die 16 Nutzbits des Frames Damit kannst du beim Empfang eindeutig erkennen, wo ein Frame beginnt und nach drei empfangenen Bytes sehr zuverlässig entscheiden, ob das Frame vollständig und fehlerfrei empfangen wurde.
Danke für die ausführliche Beschreibung, ich glaub das ist doch ein bisschen zu hoch für mich, ich hab keine ahnung wie ich das in c# realisieren soll. Ich kann dann aber im 2.Byte den Wert 255 nicht erreichen oder ?
Wirf das Korn doch nicht in die Flinte... Ich denke da wäre eine FSM ganz nützlich. http://www.mikrocontroller.net/articles/Statemachine Du musst Dir nur mögliche/sinnvolle Zustände überlegen. Z.B. : 1. StartOfFrame erkannt. 2. erstes Datenbyte erkannt und abgelegt. 3. zweites Datenbyte erkannt und abgelegt. 4. Kommando erkannt und abgelegt. 5. Prüfsumme erkannt und abgelegt. 6. EndOfFrame erkannt und abgelegt. Und hier wären die Transitions : -Bei jeder Zustandsänderung muss ein Byte empfangen und abgelegt worden sein. -Start, EndOfFrame und Prüfsumme wären spezielle "Wörter". -Ist das 6. Byte kein EOF wird das Frame verworfen. -Wird kein SOF erkannt gibts auch keinen Frame. -Stimmt die Prüfsumme nicht ist das Frame ungültig. ... Baute man eine Variable länge ein, könnte man mehrere Lämpchenhelligkeiten in einem Frame übertragen. Setz Dich doch mal 15Min konzentriert hin und stelle sowas auf. Da kommt bestimmt was gutes raus !
:
Bearbeitet durch User
Frederik Wayn schrieb: > Danke für die ausführliche Beschreibung, ich glaub das ist doch ein > bisschen zu hoch für mich, ich hab keine ahnung wie ich das in c# > realisieren soll. Dann solltest du vielleicht einfach die Sprache lernen, die du verwenden willst? Stichwort: Bitoperationen. Die werden in C# praktisch genauso notiert wie C. Aber das kannst du auch nicht, stimmt's? > Ich kann dann aber im 2.Byte den Wert 255 nicht erreichen oder ? Im zweiten gesendeten Byte kannst du natürlich niemals 255 erreichen, aber das ist völlig unwichtig. Was wichtig ist: du kannst einen PWM-Wert von 255 übertragen, weil ein Teil davon im zweiten und der Rest im dritten Byte des Frame steckt. Du mußt die entsprechenden Bits bloß aus diesen beiden Bytes rausfischen und ordentlich zusammenbauen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.