Hallo, ich habe ein paar Fragen zu einem kleinen Projekt, bevor ich richtig damit loslege. Ich habe bisher noch fast gar nicht mit AVRs oder überhaupt mit Mikrocontrollern gearbeitet, aber dieses Projekt sollte sich (hoffentlich) schön scheibchenweise realisieren lassen: Vorhanden ist eine kleine Platine, die zur Ansteuerung für ein paar Relais dienen soll. Per SPI werden Schieberegister gefüttert, an denen ULN2803A hängen. Anwendung: Diese Relais schalten 12 HF-Dämpfungsglieder mit unterschiedlichen Abstufungen wie 0,1dB, 0,2dB, 0,4dB, 0,4dB, 1dB, 2dB, 4dB, 4dB,usw. Alle Dämpfungsglieder sind in Reihe geschaltet und können über diese Relais ein- und ausgeschaltet werden. (Es gibt jeweils einen separaten Pin für ein- und ausschalten.) Der "Wertebereich" geht ungefähr von 0dB (alle aus) bis 120dB (alle an). Die Dämpfungsglieder wurden so ausgewählt, das in 0,1er Schritten geschaltet werden kann. µC ist ein Mega16. Der Anwender soll mittels Rotary Encoder und Siebensegment- Anzeige einen Dämpfungswert einstellen, der geschaltet wird, wenn er länger als 0,5s nicht am Encoder gedreht hat. Der vorhandene Code ist nur bruchstückhaft, nicht lauffähig und praktisch nicht dokumentiert, daher fange ich lieber nochmal ganz neu an. Gesucht ist also ungefähr folgendes: a) Frage den Rotary-Encoder ab und reagiere, wenn sich etwas geändert hat. b) Rauf bzw. runter zählen, 0,5s-Timer neu starten c) Änderung auf dem Display (Siebensegment, Multiplex) c) Wenn >=0,5s keine Änderung am Encoder -> Gewünschten Wert ausrechnen/auslesen und per Schieberegister+Relais schalten d) auf weitere Änderungen "warten", also im Prinzip wieder bei a) beginnen. Wie gehe ich am besten an die Sache ran? Den Code von Peter D. zu Drehwertgebern habe ich bereits gesehen. Aber bevor ich mich in den nächsten Tagen mal daran versuche den für meine Zwecke aufzubohren habe ich noch ein paar Fragen: 1) Die Abfragefrequenz für den Rotary Encoder muss "nur" so hoch sein, das sie für Drehungen mit der Hand reicht. Lieber pollen, um einen Interrupt zu sparen, oder mittels Timer? Ich befürchte, das mir während der Entwicklung die Timer "ausgehen" - ich brauche ja schon einen mind. für das Display-Multiplex und einen zum Zählen der 0,5s Pause. Damit wäre ich dann bei dreien und habe bei einem Mega16 keine mehr übrig?! 2) Die einzustellenden Werte gehen wie erwähnt in 0,1er Schritten von 0 bis 120, müssen also auch so auf dem Display zu sehen sein. Die Dämpfungsglieder haben andere Abstufungen (am ersten Schieberegister: 0,1dB, 0,2dB, 2x0,4dB, an den anderen beiden 1/2/4/4 bzw. 10/20/40/40) also muss man sich die zu schaltenden Relais ausrechnen oder einmalig vorher berechnen. Ich brauche die dezimalen Vorkomma und Nachkomma- Werte ja ohnehin für die Darstellung auf der Siebensegment- anzeige. Ich komme bei Werten von 0 bis 120,0 und 12 Dämpfungs- gliedern (mit je einem Pin für an und aus) auf 128*24=3072 mögliche Werte für Vorkomma und 10*24=240 Werte für Nachkomma. Alternativ könnte man die Tabelle so anpassen, das die Einer-, Zehner- und Hunderterstellen als Index dienen. Hat jemand einen Tip, wie ich das geschickt angehe? Wo packe ich die Tabelle(n) am besten hin? Ich werde mich da in den nächsten Tagen und Wochen erstmal scheibchenweise rantasten, also erstmal den Rotary-Encoder und dann das Display in Gang bringen, bevor die Schaltung überhaupt etwas "sinnvolles" macht. Insbesondere die beiden Fragen bereiten mir aber noch Kopfzerbrechen. Schonmal ein großes Dankeschön im Voraus an alle, die sich bis hierhin durchgekämpft haben und vielleicht noch etwas beisteuern können. Löchert mich gerne, wenn irgendwas zu wirr formuliert ist oder Angaben fehlen.
> 1) Die Abfragefrequenz für den Rotary Encoder muss "nur" so hoch > sein, das sie für Drehungen mit der Hand reicht. Lieber pollen, > um einen Interrupt zu sparen, oder mittels Timer? Ich befürchte, > das mir während der Entwicklung die Timer "ausgehen" - ich brauche > ja schon einen mind. für das Display-Multiplex und einen zum > Zählen der 0,5s Pause. Damit wäre ich dann bei dreien und habe > bei einem Mega16 keine mehr übrig?! Stelle einen Timer auf z.B. 1ms Intervall mit dem Du alle Zeitgeber steuerst. Verwenden z.B. einen MsTimer, einen Ms100Timer (den zählst Du in der Timer Isr nur jedes 100ste Mal eins nach oben) und einen SecTimer (den zählst Du jedes 10te Mal im Ms100Timer eins nach oben). // bzgl. Timeout fuer Rotary Encoder void TimerIsr() interrupt X // im Millisekundentakt { static unsigned char Ms100Divider = 100; if(--Ms100Divider == 0) { if(bytRotaryEncoderActive) bytRotaryEncoderActive--; Ms100Divider=100; } // sonstiges z.B. einen Sekundentakt fuer main() } // dort wo Du den Rotary Encoder auswertest setzt Du die Variable // wenn gedreht wird void ExtIsr() interrupt Y { bytRotaryEncoder = 6; // 0,5-0,6s } // wenn ExtIsr() fuer 0,5 bis 0,6s nicht eintrifft dann ist // bytRotaryEncoder auf 0, d.h. er ist inaktiv // wenn am Encoder gedreht wird dann bleibt die Variable fast immer auf 6
1/ Wenn der Timer für die 0,5s Pause ein ganzzahliges Vielfaches vom Display-Multiplex Timer ist, kannst du einen Timer für beides benutzen, wenn gleichzeitig per Software mitgezählt wird. (Horst war schneller) 2/ Ich komme auf 3 Vorkommastellen und 1 Nachkommastelle ;-) Um die Nachkommastelle wegzubekommen, würde ich die dB Werte *10 verwalten. Damit wäre der Wertebereich von 0 bis 1200. Statt über Tabelle kann man auch vom Zielwert nach und nach die einzelnen Dämpfungsglieder "abziehen" und das entsprechende Dämpfungsglied setzen, wenn kein negativer Wert rauskommt. 98 -= 40 (S) 58 -= 40 (S) 18 -= 20 (NS) 18 -= 10 (S) 8 -= 4 (S) 4 -= 4 (S) 0 fertig. 98dB = 2x40dB + 1x10dB + 2x4dB Mit *10 13,5 => 135 135 -= 400 (NS) 135 -= 400 (NS) 135 -= 200 (NS) 135 -= 100 (S) 35 -= 40 (NS) 35 -= 40 (NS) 35 -= 20 (S) 15 -= 10 (S) 5 -= 4 (S) 1 -= 4 (NS) 1 -= 2 (NS) 1 -= 1 (S) 0 fertig. 13,5 dB = 1x10dB + 1x2dB + 1x1dB + 1x0,4dB + 1x0,1dB Eignet sich gut als Schleife und Setzen (S) oder Nichtsetzen (NS) sieht schon nach Schieberegister aus...
Bei der Tabelle brauchst Du meiner Ansicht nach "nur" 1200 Einträge mit 16 Bit (eigentlich 12 Bit). Dann kannst Du von 0 bis 120dB in 0,1db Schritte einstellen. Wenn z.B. 115,2 dB einstellt wird dann mit dem größten Dämpfungswert der in den 115,2 Platz findet beginnen, diese Glied aktivieren, dann das nächste Glied welches im Restwert (115,2 minus erstes Glied) Platz findet usw. Sollte eigentlich so einfach funktionieren.
Zu den 0,5 s würde ich gerne noch was kommentieren. Möglicherweise wird der Anwender davon überrascht, wenn er etwas langsam an den Knöpfen dreht. So z.B. beim Wechseln der Dezimalstelle. Rein mechanische Geräte haben das früher ohne Verzögerung gemacht, das ist auch die Erwartungshaltung der Anwender. Nachteil ist das häufige Schalten der teuren Koax-Relais. Das andere Extrem wäre, erst den Wert fertig einzustellen und dann eine "Set"-Taste zu drücken. Auch das ist transparent für den Anwender. Schont auch die Relais maximal. Dann - wie bei allen Dezimalstellern - gibts das Problem mit dem Überlauf. Also da will einer von 99 dB auf 100 dB verstellen. Dreht er erstmal die Einer auf Null, dann die Zehner auf Null, und schläft noch eine halbe Sekunde bevor er die Hunderter verstellt, dann steht der Abschwächer auf 0 dB. Bummm vielleicht. Nur so meine 2 Cent ...
Hallo, >Zu den 0,5 s würde ich gerne noch was kommentieren. [...] Das ist so vom zukünftigen Anwender gewünschtes bzw. mit ihm abgesprochenes Verhalten. Wenn sich später noch mal eine Änderung ergibt, kann man die immer noch einbauen. Aber erstmal ist das so ein Kompromiss, um nicht dauernd schalten zu müssen. > Das andere Extrem wäre, erst den Wert fertig einzustellen > und dann eine "Set"-Taste zu drücken. Ich hatte dafür ursprünglich den Taster vorgesehen, der in vielen Rotary-Encodern vorhanden ist, da er für seinen eigentlich angedachten Zweck wohl nicht zu gebrauchen ist. Das war vom Anwender ausdrücklich nicht gewollt. (Ursprünglich sollte der Kontakt als "Turbo" dienen, d.h. bei gedrücktem Encoder wird schneller hoch gezählt. Das dürfte aber nicht funktionieren, wenn der nur als Taster funktioniert?!) > Dreht er erstmal die Einer auf Null, [...] Es gibt nur einen Drehwertgeber. Das Problem ist also nachvollziehbar, tritt aber nicht auf. Nullen ist nur durch kurzes Ausschalten des Gerätes machbar, oder natürlich durch auf Null drehen. Wahrscheinlich in einer nächsten Version sogar nur durch manuelles auf Null drehen oder einen separaten Pin für den Reset. (Es sind noch genug Pins frei.) Der Anwender möchte, das der zuletzt geschaltete Wert nach Aus- und wieder Einsschalten weiter benutzt werden kann. Das baue ich dann irgendwann später mal ein. Das es prinzipiell mit Atmels geht habe ich schon gesehen. Schonmal ein großes Dankeschön an dich und natürlich auch an Horst und Stefan, die mir ein paar Bretter vor dem Kopf entfernt haben. :-))
Hallo nochmal, >Statt über Tabelle kann man auch vom Zielwert nach und nach die einzelnen > Dämpfungsglieder "abziehen" und das entsprechende Dämpfungsglied setzen, > wenn kein negativer Wert rauskommt. Das hatte ich angedacht, für den Fall das der Controller nicht genug Speicher hat oder irgendwas anderes gegen die Tabellenlösung spricht. >Eignet sich gut als Schleife und Setzen (S) oder Nichtsetzen (NS) sieht >schon nach Schieberegister aus... Ich muss dann nur irgendwie noch jeweils das zweite Bit negieren. (Es gibt ja jeweils immer einen Pin für aus und einen für an.) Danke!
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.