Forum: Mikrocontroller und Digitale Elektronik AVR (Mega16) Codeueberlegungen


von Wuschel (Gast)


Lesenswert?

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.

von Horst Gschwandtner (Gast)


Lesenswert?

> 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

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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...

von Horst Gschwandtner (Gast)


Lesenswert?

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.

von Horst Gschwandtner (Gast)


Lesenswert?

Jetzt war Stefan B. schneller g

von Tom (Gast)


Lesenswert?

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 ...

von Wuschel (Gast)


Lesenswert?

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. :-))

von Wuschel (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.