Hallo zusammen!, ich habe folgendes Problem: Ich möchte gerne für eine Eisenbahnsteuerung eine PC-uC(AtMega32) Verbindung haben...soweit kein Problem. Der uC soll am Ausgang ein Taktsignal mit 0-30 Impulsen liefern. Die Impulse (Zustand 1) selber sollen 355ms lang sein, dazwischen 405ms pause (0). Nun werden je nach Befehl nur bestimmte Impulse freigegeben. Die Ersten zehn Impulse stllen die Adresse dar, die weiteren 20 die Aktion, welche der Aktor ausführen soll. Ich habe das bis jetzt so versucht zu realisieren, dass das Signal vom PC (C#) in ein Array auf dem uC geschrieben wird. Dieses Array hat dementsprechend so viele Zeilen wie das Singal in ms aufgeteilt ergibt. Sprich 22800 Zeilen. Nun habe ich auf dem uC den Timer0 entsprechend eingestellt, dass er jede ms in die ISR springt und einen Vergleich durchführt. Ist im Array an entsprechender Stelle eine 1 gesetzt wird der Ausgang 1 gesetzt, bei einer 0 an dieser Stelle bleibt der Ausgang auf 0. Nun habe ich allerdings das Problem, dass das Array nicht mit den 22800 Zeilen deklariert werden kann, da Speicher zu klein. Auch eine Aufteilung in Bytes kommt nicht in Frage, da Speicher zu gering. Vermutlich bin ich auch auf dem Holzweg und denke zu kompliziert. Hättet ihr einen Tipp für mich wie Ihr sowas realisieren würdet? Zusammengefasst: Auf dem PC wird ein Impulsmuster mit 1en und 0en berechnet, dieses Muster soll am uC Zeitdiskret ausgegeben werden. Die Übertragung ist kein Problem, sondern der Zeitdiskrete Ausgabe. Mit delays möchte ich nicht arbeiten...was aber so halbwegs funktionieren würde... Vielen Dank schonmal! PS. Ich erwarte keine Programmcodes.
Wozu brauchst du denn den PC? Und wozu brauchst du das Array? Und warum willst du nicht mit der delay Funktion arbeiten?
TheGee schrieb: > Die > Impulse (Zustand 1) selber sollen 355ms lang sein, dazwischen 405ms > pause (0). Das hab ich nicht verstanden. Pause ist das gleiche wie Zustand 0?
Nerd B schrieb: >> Impulse (Zustand 1) selber sollen 355ms lang sein, dazwischen 405ms >> pause (0). > > Das hab ich nicht verstanden. Pause ist das gleiche wie Zustand 0? Ich auch nicht, aber ich glaube bei Log.1 gibt es 355ms Zustand1 und dann 405ms Zustand0, bei Log.0 gibt es 760ms Zustand0. Ist das so ?
Wenn dein Signal aus 30 Impulsen besteht, warum schickst du dann nicht einfach diese 30 Bits vom PC zum uC? Oder der Einfachheit halber 32 Bits also 4 Bytes. Da brauch man doch nicht jede Millisekunde zu übertragen, wenn man weiß, wie lang Pausen und Signale sind.
Marc V. schrieb: > Ich auch nicht, aber ich glaube bei Log.1 gibt es 355ms Zustand1 und > dann 405ms Zustand0, bei Log.0 gibt es 760ms Zustand0. Dann braucht also ein Befehl 22,8 Sekunden?
Das Problem ist, dass das Signal zusammenhängend ausgegeben werden muss. Wenn ich nun über den PC sende und gleichzeitig ausgebe, unterbricht der PC wegen dem Multitasking (durch öffnen anderer Programme) die Sendung, bzw. sendet geringfügig verzögert. Deswegen wollte ich das Signal erst auf dem uC zwischenspeichern und dann per Befehl ausgeben. Da wird dann nixmehr unterbrochen. /Ich auch nicht, aber ich glaube bei Log.1 gibt es 355ms Zustand1 und dann 405ms Zustand0, bei Log.0 gibt es 760ms Zustand0. Ist das so ?/ Genau, so soll es sein.
Nerd B schrieb: > Wozu brauchst du denn den PC? Und wozu brauchst du das Array? Und > warum > willst du nicht mit der delay Funktion arbeiten? Über das PC Programm sollen die verschiedenen Befehle visuell gesteuert werden. Drückt man den Button "Beleuchtung ein" generiert das C# Programm das Bitmuster und sendet es an den Mikrocontroller. Dies ist natürlich auch direkt am uC möglich...das PC Programm soll aber mit der Zeit Umfangreicher werden und mehr Funktionen erhalten. Ich möchte dies nunmal gerne über Timer lösen, da ich so meiner Meinung nach flexibler bin für spätere Bitmuster-Anderungen
Nerd B schrieb: > Dann braucht also ein Befehl 22,8 Sekunden? TheGee schrieb: > Genau, so soll es sein. Was willst du denn auf deiner Modellbahn damit schalten? Mehr als das abendliche Einschalten der Straßenbeleuchtung kann man doch in diesem Tempo kaum machen. <nachdenk>
TheGee schrieb: > Deswegen wollte ich das Signal erst auf dem uC zwischenspeichern und > dann per Befehl ausgeben. Da wird dann nixmehr unterbrochen. 1 Byte PC==>uC mit 38400B dauert 260us. MEGA32 dekodiert diesen Byte und fuhrt entsprechende Aktion aus. Wozu diese 22.8s und diese Slowmotion Impulse gut sein sollen, ist mir absolut unklar.
:
Bearbeitet durch User
Marc V. schrieb: > 1 Byte PC==>uC mit 38400B dauert 260us. > > MEGA32 dekodiert diesen Byte und fuhrt entsprechende Aktion aus. Ja gut, dann hätte ich 1 Byte. Wenn die nächsten Bytes aber nicht Zeitdiskret übertragen werden, passt es wieder nicht. Oder meine Denkweise mit dem "Zwischenspeichern" im Array ist falsch. Da ich die Empfänger auch selber erstellen will, sollen die Impulse erstmal länger sein um sie für mich besser auswertbar zu machen. Keine Frage...es geht schneller und effizienter...für einen C Neuling ist dies aber noch zu hoch finde ich. Deswegen erstmal die langsamere Variante.
TheGee schrieb: > Der uC soll am Ausgang ein Taktsignal mit 0-30 Impulsen liefern. Die > Impulse (Zustand 1) selber sollen 355ms lang sein, dazwischen 405ms > pause (0). Sichher das das ms (Millisekunden) sind? Ich hätte hier Micro Sekunden (µs) erwartet. Aber selbst bei µs hat man noch genügent freie Taktzyklen für ein paar einfache Rechenaufgaben im Timer, d.h. Du erzeust die eigentlichen Signale erst im Timer Interrupt.
Jim M. schrieb: > TheGee schrieb: >> Der uC soll am Ausgang ein Taktsignal mit 0-30 Impulsen liefern. Die >> Impulse (Zustand 1) selber sollen 355ms lang sein, dazwischen 405ms >> pause (0). > > Sichher das das ms (Millisekunden) sind? Ich hätte hier Micro Sekunden > (µs) erwartet. > > Aber selbst bei µs hat man noch genügent freie Taktzyklen für ein paar > einfache Rechenaufgaben im Timer, d.h. Du erzeust die eigentlichen > Signale erst im Timer Interrupt. Bis jetzt habe ich in der ISR ja nur einen Vergleich zwischen Zählwert (welcher auch gleichzeitig der Zeitwert in ms ist) und ob in dem Array an dieser Stelle eine 1 oder 0 ist...dementsprechend wird der Ausgang in der ISR dann gesetzt. Das Problem dabei ist, dass ich den uC eigendlich universell gestallten will und dann bei Taktänderungen nicht umprogrammieren muss. Ich habe auch schon an die Variante gedacht einfach einen Zahlencode statt der einzellnen Bits zu senden, sprich es sollen zB die Bits 2,3,7,8,10 auf high gesetzt werden, dann sendet der PC nur diese Zahlen und in der ISR werden dann die entsprechenden Zeiten high gesetzt. Dies würde Speicherplatz-mäßig gehen...da harperts mir aber noch an der Umsetzung. Da ich gedanklich immer an der Umsetzung mit einem Array-Vergleich hänge...
TheGee schrieb: > Ja gut, dann hätte ich 1 Byte. Wenn die nächsten Bytes aber nicht > Zeitdiskret übertragen werden, passt es wieder nicht. > > Oder meine Denkweise mit dem "Zwischenspeichern" im Array ist falsch. Ja. Beispiel: Beleuchtung ein = 0x81 Beleuchtung aus = 0x01 (Bit 7 = 1 für ein und 0 für aus) Ventilator ein = 0x82 Ventilator aus = 0x02 (Bit 7 = 1 für ein und 0 für aus) Somit hast du 127 verschiedene Befehle mit nur einem Byte und praktisch ohne Verzögerung. Das sich etwas erst nach 23s ein- oder ausschaltet ist ein klein bisschen zu langsam, findest du nicht ?
@ TheGee Ich vermute, dass ist so ein Fall, in dem die Lösung komplizierter als nötig ist. Falls und soweit ich Deine Beschreibungen recht verstehe, dann ist folgendes: > Der uC soll am Ausgang ein Taktsignal mit 0-30 Impulsen liefern. Die > Impulse (Zustand 1) selber sollen 355ms lang sein, dazwischen 405ms > pause (0). > Nun werden je nach Befehl nur bestimmte Impulse freigegeben. Die Ersten > zehn Impulse stllen die Adresse dar, die weiteren 20 die Aktion, welche > der Aktor ausführen soll. so zu deuten. 1. Es werden "Telegramme" übertragen. D.h. es gibt eigenständige Teile, die für sich genommen vollständig sind. Nicht ein fortlaufender Bitstrom, der ständig vorliegen muss. 2. Die Telegramme bestehen aus Adresse und Kommando 3. Eine Adresse besteht aus 10 kleinsten Informationseinheiten. 4. Ein Kommando besteht aus 20 kleinsten Informationseinheiten. Und jetzt bin ich mir nicht sicher, ob ich Dich richtig verstehe: 5. Eine kleinste Informationseinheit dauert bei der Übertragung 355 + 405 = 760ms. Richtig? Es wird entweder. 760ms lang ein Low-Pegel übertragen oder 355ms lang ein High-Pegel gefolgt von 405 ms Low-Pegel. Richtig? Die kleinste Informationseinheit ist vermutlich entweder 0 oder 1. Die 0 wird vermutlich mit den 760ms Low-Pegel übertragen, die 1 vermutlich mit dem beschrieben Pegelwechsel. Richtig? Daraus folgt, dass es 2^10 verschiedene Adressen und 2^20 verschiedene Kommandos gibt. Siehst Du das auch so? Daraus scheint mir der, - zunächst naive -, Ansatz zu folgen: a) Es wird vom PC eine Folge von 2 Bytes für die Adresse übertragen. b) Es wird anschliessedn eine Folge von 3 Bytes für das Kommando übertragen. c) Der uC puffert Adresse und Kommando bis beides vorhanden ist. Evtl. puffert er auch mehrere solcher Tupel. d) Der uC erzeugt z.B. interruptgesteuert aus diesen beiden Daten, eine entsprechende Impulsfolge. Dabei wird nicht zunächst die Impulsfolge also Folge von 0 und 1 berechnet und gespeichert. Es ist nicht ganz klar ob eine gewisse Adresse, z.B. 0x17 auch in seiner binären Darstellung gerade die Bitfolge wiedergibt, aber das wäre der naheliegendste oder einfachste Fall. Das ganze liest sich bis auf das Timing wie eine einfache serielle Übertragung wie RS232 oder IIC oder so. Eigentlich nicht wirklich kompliziert zu machen. Wegen des Timings wird man das aber vermutlich wie einen Software-UART angehen. Also so: 1. Nimm das erste Bit mit einer Maske. 2.a. Ist es 1, erzeuge die 1-Folge der kleinsten Informationseinheit (also 355ms High und 405ms Low) 2.b. Ist es 0, erzeuge die 0-Folge (also 760ms lang Low-Pegel) 3. Falls noch nicht das letzte Bit (also 10 bzw. 20) erzeugt wurde, schiebe die Bitmaske eine Bit weiter und gehe zu 1. 4. Ende Nützt Dir das was?
Hanswurst schrieb: > @ TheGee > > Ich vermute, dass ist so ein Fall, in dem die Lösung komplizierter als > nötig ist. > > Also so: > > 1. Nimm das erste Bit mit einer Maske. > 2.a. Ist es 1, erzeuge die 1-Folge der kleinsten Informationseinheit > (also 355ms High und 405ms Low) > 2.b. Ist es 0, erzeuge die 0-Folge (also 760ms lang Low-Pegel) > 3. Falls noch nicht das letzte Bit (also 10 bzw. 20) erzeugt wurde, > schiebe die Bitmaske eine Bit weiter und gehe zu 1. > 4. Ende > > Nützt Dir das was? Ja genau, hast alles richtig verstanden. Das mit dem verschieben hilft mir weiter! Dann könnte ich die 30 Zustände in ein Array übertragen und diese mit der Maske nacheinander abfragen...je nachdem ob der Zustand dann high oder low sein soll wird dann das entsprechende Signal generiert. Da werde ich mich morgen gleich mal reinhängen...Vielen Dank!
TheGee schrieb: > Ja genau, hast alles richtig verstanden. Das mit dem verschieben hilft > mir weiter! Dann könnte ich die 30 Zustände in ein Array übertragen und > diese mit der Maske nacheinander abfragen...je nachdem ob der Zustand > dann high oder low sein soll wird dann das entsprechende Signal > generiert. Auweia. Du hast aber nichts verstanden...
TheGee schrieb: > Ja genau, hast alles richtig verstanden. Das mit dem verschieben hilft > mir weiter! Dann könnte ich die 30 Zustände in ein Array übertragen und > diese mit der Maske nacheinander abfragen...je nachdem ob der Zustand > dann high oder low sein soll wird dann das entsprechende Signal > generiert. > > Da werde ich mich morgen gleich mal reinhängen...Vielen Dank! HALT! HALT! HALT! Ich denke Du hast das falsch verstanden. Ein Array kommt nur als Puffer für die Daten vom PC vor. Aber NICHT, so wie Du es oben schriebst, für die zu sendenden Bitmuster. Das wäre total ineffizient in Bezug auf Übertragungsgeschwindigkeit und Speicherplatz. Oder habe ich jetzt was falsch verstanden? Die Kernfrage ist, wie die 10 Adressen und die 20 Kommandos bei der Übertragung vom PC kodiert sind. Dazu solltest Du was schreiben. Und zur Redundanz noch den Empfänger nennen oder beschreiben, der diese Impulsfolge letztlich empfängt.
@ TheGee Um mal klarzustellen, wo ich eine ungünstige Überlegung bei Dir vermute: Angenommen es ginge um Adresse 0x201 und Kommando 0x8001 (Die Daten sind absichlich so gewählt, dass lange Reihen von 0 entstehen). Dann würde Dein Array, dass in Millisekunden-Äuflösung das zu sendende Bitmuster enthält so aussehen: Es wäre, wie Du schon schriebst, 22800 Bit lang. Also 22800 / 8 = 2850 Byte Der überwiegende Teil der Daten würde, wegen der Pausen, aus Nullen bestehen. char Bitmuster [] {0x80, 0, 0, 0, ..., 0, 0, 1}; Eine enorme Platz und Zeitverschwendung. Mit der Bitmaske hat das nichts zu tun. Vielmehr soll Dein Array so aussehen (mal abgesehen von einigen Details, die man anders machen würde). struct Telegramm { uint16_t Adresse; uint32_t Kommando; }; #define ANZAHL_TELEGRAMME 10 struct Telegramm Buffer [ANZAHL_TELEGRAMME]; Deine Uart-Empfangsroutine füllt diesen Buffer (Ringpuffer). Das ist wesentlich kürzer, als Dein Monster-Array. Bitmasken wendest Du auf Adresse und Kommand an. Also 0x800 bzw. 0x80000. Und DIE schiebst Du über Adresse und Kommando. Die Pegel-Dauer erzeugst Du jeweils daraus, ob das Bit 1 oder 0 ist. Hoffe ich habe noch rechtzeitig geschrieben, ehe Du diese Monster implementierst.
Hanswurst schrieb: > @ TheGee > Hoffe ich habe noch rechtzeitig geschrieben, ehe Du diese Monster > implementierst. Guten Morgen, nein so war das nicht gemeint...würde ja dann mein Problem nicht lösen. Ich war in Gedanken daran die 30 einzellnen Zahlen vom PC->uC zu übertragen...wie sonst auch...ist ineffizient, reicht mir aber erstmal, da die Übertragungsdauer vom PC zum uC erstmal zweitrangig ist. Es ist im Prinzip (in C#) eine for Schleife welche die Zustände (high, low) der Zahlen 1,2,3,4,5,...,30 einzelln über die Schnittstelle sendet. Auf dem uC wird die Schnittstelle durch die ISR(USART_RXC_vect) abgefragt und nach jeder Sendung ein Zähler hochgezählt. So weis der uC an welcher Stelle (1,2,3,4,5,...,30 ) das high oder low ins Array eingetragen werden muss. Nun habe ich durch deinen Tipp überlegt statt ein Array für 22800 Zustände anzulegen, eines für die 30 Zustände zu erstellen. In der ISR vom Timer0 käme dann ein switch case rein der je nachdem ob high oder low gesendet werden soll, die Zeiten generiert. Beim Ende bin ich mir aber noch nicht so sicher...ich werds mal versuchen...
TheGee schrieb: > Nun habe ich durch deinen Tipp überlegt statt ein Array für 22800 > Zustände anzulegen, eines für die 30 Zustände zu erstellen. In der ISR > vom Timer0 käme dann ein switch case rein der je nachdem ob high oder > low gesendet werden soll, die Zeiten generiert. Beim Ende bin ich mir > aber noch nicht so sicher...ich werds mal versuchen... Und nochmal: Wie wäre es mit einem einzigen Byte von PC und direktem ausführen gleich danach ? Wozu die 30 Zustände, wozu die "Geschwindigkeit" von 1,3Hz ?
TheGee schrieb: > Der uC soll am Ausgang ein Taktsignal mit 0-30 Impulsen liefern. OK. Eigentlich aber nicht Ok. Was willst du mit einem Taktsignal? Der µC muss ein Datensignal liefern. > Die Impulse (Zustand 1) selber sollen 355ms lang sein, dazwischen 405ms > pause (0). Wie kommen diese Zeiten zustande? Abgesehen von der Länge, wieso 355 und 405? > Nun habe ich auf dem uC den Timer0 entsprechend eingestellt, dass er > jede ms in die ISR springt und einen Vergleich durchführt. Warum? Du weisst doch, daß mind. 355ms nichts passiert. Warum also alle ms nachgucken? > Vermutlich bin ich auch auf dem Holzweg Aber sowas von... > Mit delays möchte ich nicht arbeiten... Dein einziger richtiger Ansatz. Du überträgst Daten mit einer PWM. PWM definiert sich über die Zeit. Um zwei Zustände zu unterscheiden brauchst du also 2 Zeiten. Das ist jetzt trivial. Also nur, damit das klar ist. Die eine Zeit ist t, die andere 2t. Damit lässt sich das auch vernünftig unterscheiden: Eine logische 1 hat die Länge t eine 0 die Länge 2t. Das ist jetzt willkürlich festgelegt, aber bleiben wir dabei. Um eine logische 1 zu senden, setzt du den Leitungspegel auf High und schaltest ihn nach der Zeit t wieder auf Low. Bei einer logischen 0 wird der Leitungspegel ebenfalls auf High, aber erst nach 2t wieder auf Low gesetzt. Wichtig ist, daß die Leitung auch auf Low geht! Denn der Empfänger wird mit der steigenden Flanke des Highpegels getriggert und guckt timergesteuert nach 1,5t auf die Leitung. Ist der Pegel jetzt Low, wurde eine eine logische 1 empfangen, ist er (immer noch) High, steht eine logische 0 an. Das nächste Bit beginnt wieder mit einer steigenden Flanke auf der Leitung. Die Dauer des dazwischen liegenden Lowpegels ist vollkommen egal. Das können ein paar µs, ein paar ms oder auch ein paar Wochen sein. Zum Senden werden die Datenbytes bitweise ausgewertet. Dazu sieht man sich je nach Bitorder das oberste oder unterste Bit an und verschiebt das Byte danach entweder nach links oder rechts. Nichts mit switch und case, sondern einfach if und else. Dann wird zuerst der Ausgangspegel auf High gesetzt und entsprechend des Bitwertes nach t oder 2t wieder auf Low. Das erledigt der Timer mit seiner Hardware. Zur Not auch im Interrupt. Übrigens: Der Timer kann seinen korespondierenden Pin nicht nur zyklisch toggeln, sondern auch nach Ablauf der eingestellten Zeit auf High oder Low setzen. Auch wenn es sich bei der Übertragung um eine PWM handelt, ist CTC der richtige Timermodus. Und mach die Zeiten kürzer.
Naja. Das ist zwar speichersparender, aber Du musst immer noch rund 240 Byte übertragen anstatt 4 oder 5 wie bei meiner Methode. Ich weiss aber nun auch nicht mehr woran es liegt, dass Du das partout nicht verstehen oder eben nicht so machen willst. Ich weiss auch nicht wie ich das noch deutlicher erklären könnte. Deutlicher geht es eigentlich nicht mehr.
Ich bezweifle, dass die Spezifikation richtig ist. Wie sollen zum Beispiel die Befehle 0x0001, 0x0002, 0x0004 usw unterschieden werden? In allen Fällen kommt nur ein Impuls von 355 ms. Um welche Eisenbahnmarke und welche Bauteile handelt es sich denn, die du ansteuern möchtest?
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.