Forum: Projekte & Code ATtiny26 Balkenanzeige ( Hysterese ) mit acht Schaltschwellen (ASM)


von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

nachdem ich ein Problem damit hatte, wie man eine Hysterese in Assembler 
programmiert Beitrag "Wie programmiert man eine Hysterese in Assembler ?" habe ich 
mal ein Programm hierzu geschrieben. Dort wird mit einem Poti dem ADC 
eine Spannung im Bereich 0 bis 5V vorgegeben und anhand der Schwellwerte 
acht LEDs angesteuert.

Durch die Hilfestellung in dem oben genannten Thread bin ich darauf 
gekommen mit Flags zu arbeiten, die das Ueberschreiten bzw. das 
Unterschreiten der einzelnen Schwellwerte speichern.

Bernd_Stein

von spess53 (Gast)


Lesenswert?

Hi

Das ist ja sehr voluminös geraten. Ist dir bewusst, das das 
Unterprogramm 'schwellwert_verarbeiten' völlig überflüssig ist? Der Wert 
den du dort ermittelst und ausgibst ist identisch mit dem Inhalt von 
SW_FLAGS den du dort verarbeitest.

MfG Spess

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

spess53 schrieb:
> Hi
>
> Das ist ja sehr voluminös geraten.
>
Das finde ich auch. Würde natürlich gerne sehen und nachvollziehen 
können wie man es " schlanker " machen kann.
>
> Ist dir bewusst, das das Unterprogramm 'schwellwert_verarbeiten' völlig
> überflüssig ist?
>
Nein. Auch jetzt nicht nachdem ich es mir nochmal angeguckt habe.
Ich habe mich halt hier dran orientiert :
Beitrag "Re: Wie programmiert man eine Hysterese in Assembler ?"
>
> Der Wert den du dort ermittelst und ausgibst ist identisch mit dem Inhalt > von 
SW_FLAGS den du dort verarbeitest.
>
Ich verstehe leider nicht was Du mir damit sagen willst.
So ist es recht übersichtlich programmiert, finde ich.

Bernd_Stein

von spess53 (Gast)


Lesenswert?

Hi

>Ich verstehe leider nicht was Du mir damit sagen willst.
>So ist es recht übersichtlich programmiert, finde ich.

Der Wert, den du in SW_FLAGS an 'schwellwert_verarbeiten' übergibst ist 
identisch mit dem Wert den diese Routine an PortA ausgibt.

Lass es mal durch den Simulator laufen und vergleiche mal r19 (SW_FLAGS) 
und r16 (A).

>Das finde ich auch. Würde natürlich gerne sehen und nachvollziehen
>können wie man es " schlanker " machen kann.

Bekommst du morgen früh (hab wieder mal den USB-Stick stecken gelassen). 
Hat etwa ein viertel Codegröße.

Aber schon mal als Anregung:

Deine Schwellwerte sind z.B. alle durch 4 teilbar. Damit kannst du mit 
8-Bit-Werten (ADC rechtsbündig mit ADLAR eingestellt) arbeiten. Erspart 
die ganzen 16-Bit Vergleiche.

Schwellwerte nicht als Konstanten sondern als Tabelle im Flash. Damit 
können deine ellenlangen Vergleiche als Schleife ausgeführt werden.

Der Ausgabewert wird beginnend mit 0b11111111 bei jedem Vergleich mit 
shl angepasst.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

Nachtrag: Wenn du schon etwas für die Codesammlung machst, dann nimm 
nicht so einen Oldtimer wie den ATTiny26. Der hat noch nicht einmal den 
vollständigen Befehlssatz eines aktuellen AVR.

MfG Spess

von spess53 (Gast)


Angehängte Dateien:

Lesenswert?

Hi

Wie versprochen.

MfG Spess

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

spess53 schrieb:
> Hi
>
> Wie versprochen.
>
> MfG Spess
>
Erstmal Danke.

Ich kämpfe gerade mit dieser genialen Routine

Beitrag "Tasten entprellen - Bulletproof"

und deshalb habe ich noch nicht hierauf reagiert. Tut mir leid das ich 
so sprunghaft bin. Hoffe jedoch bald wieder auf diesen Thread zurück 
kommen zu können.

Danke für deine Mühe.

Bernd_Stein

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

spess53 schrieb:
> Hi
>
> Der Wert, den du in SW_FLAGS an 'schwellwert_verarbeiten' übergibst ist
> identisch mit dem Wert den diese Routine an PortA ausgibt.
>
Ja, aber das sollte ja nur ein anschauliches Beispiel für eine Hysterese 
sein. In z.B.
1
;
2
;Aktionen entsprechend den Schwellwerten ausfuehren
3
;                                 
4
aktion_7:
5
        ldi   A,0b11111111 ;Alle Pins des... 
6
        out   PORTA,A      ;...Ports setzen
7
        rjmp  swv_end      ;Ruecksprung aus Schwellwert verarbeiten
könnte ja auch zusätzlich eine Pumpe eingeschaltet werden.
1
aktion_7:
2
        ldi   A,0b11111111    ;Alle Pins des... 
3
        out   PORTA,A         ;...Ports setzen
4
        sbi   PORTB,PUMPE_EIN ;Pumpe einschalten
>
Mir ist jedoch aufgefallen, das man bei so etwas ganz schön aufpassen 
muß, wenn der Meßwert sich schneller ändert als das Abtasten durch den 
ADC geschieht. So könnte z.B. die Pumpe eingeschaltet werden und beim 
erneuten einlesen des Meßwertes einen Schwellwert unter dem liegen,
der die Pumpe wieder ausschaltet. Also müssen alle Schwellwerte darunter 
auch die Pumpe ausschalten, was natürlich bei mehreren Schwellwerten 
viel Schreibaufwand bzw. kopieren bedeutet.

Aber erstmal egal. Wollte nur mal zeigen, wie man evtl. eine Hysterese 
in Assembler programmieren kann.

Danke für deinen Code.
Ehrlich gesagt kann ich ihn nicht nachvollziehen. Aber der ist ja eher 
auf " so kurz wie möglich " getrimmt. Schön daran ist auch zu sehen,
wie man es machen kann den Code für den " Nachfolgecontroller " 
anzupassen.

Bernd_Stein

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

@spess53

Habe deinen Code mal Hardwaremäßig ausprobiert. Dabei ist mir 
aufgefallen, das ich es schaffe ( mit 10k Poti ) wenn ich ganz 
feinfühlig bin jede LED bis auf die Unterste ( nahe bei Null Volt ) zum 
flimmern zu bringen.

Das wollte ich ja durch eine Hysterese verhindern. Habe das Programm, 
weil ich noch nicht alles ganz verstehe im Simulator des AVR-Studios 
laufen lassen. Die Werte des ADCs waren dabei 120, 119, 120. Dort kann 
man sehr schön sehen, das es keine Hysterese an diesem Punkt gibt, was 
ja im Hardwaretest schon aufgefallen ist.

Augenscheinlich scheinen also die beiden Programme das Selbe zu machen, 
nur im Detail betrachtet arbeiten sie etwas anders, da bei mir eine LED 
beim Überschreiten des Schwellwertes eingeschaltet wird und erst beim 
Unterschreiten der darunter liegenden Schaltwelle wieder ausgeschaltet 
wird.

Diese Sequenz ist mir noch nicht ganz klar bzw. ich bin mir noch nicht 
sicher ob sie wirklich gebraucht wird. Aber mit dem AVR-Studio Simulator 
werde ich dies hoffentlich auch noch herausbekommen.
1
                      lpm r21,Z
2
3
                      cp r20,r21             
4
                      brcs end_loop           ; wenn IST kleiner -> fertig
5
6
                      in r16,PortA            ; letzte Bargrafausgabe
7
                      ;com r16                ; negieren ( wegen STK 500 )
8
                      bst r16,0               ; Bit0 nach T
9
                      bld r18,0               ; T nach Bit0

Bernd_Stein

von Horst H. (horha)


Lesenswert?

Hallo,

Bernd Stein schrieb:
> Überschreiten des Schwellwertes eingeschaltet wird und erst beim
> Unterschreiten der darunter liegenden Schaltwelle wieder ausgeschaltet
> wird.

SWerte:               .db 240,210,180,150,120, 90, 60, 30, 15, 0
Also beim Aufstieg von 119 auf 120 wechselst Du in den Bereich 
[120..150[ , aber erst bei unterschreiten von 90 in den Bereich 
[90..120[ .
Diese bedeutet, dass Du beim Abstieg immer einen Bereich hinterher 
hinkst, denn erst beim Wechsel auf 59 würde in den Bereich [60..90[ 
gewechselt.
Du kämst wohl nict mehr auf den untersten Bereich zurück, denn die 0 
kannst Du nicht unterschreiten.

Wäre es nicht logischer, die Bereiche mit Überlappungen anzulegen.
Bereich 1 :[0..50]  // 0..40 Hysterese 0 und +10 oder Mitte 25 +- 25
Bereich 2 :[20..70] // 30..60 Hysterese -10 und +10 //Mitte 45 +- 25
Bereich 3 :[50..100] // 60..90 Hysterese -10 und +10 //Mitte 75 +- 25
....
Beim unterschreiten wechselt man in den Bereich darunter und beim 
überschreiten in denjenigen darüber.

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Horst Hahn schrieb:
> Hallo,
>
> Bernd Stein schrieb:
>> Überschreiten des Schwellwertes eingeschaltet wird und erst beim
>> Unterschreiten der darunter liegenden Schaltwelle wieder ausgeschaltet
>> wird.
>
> SWerte:               .db 240,210,180,150,120, 90, 60, 30, 15, 0
>...
>
> Wäre es nicht logischer, die Bereiche mit Überlappungen anzulegen.
> Bereich 1 :[0..50]  // 0..40 Hysterese 0 und +10 oder Mitte 25 +- 25
> Bereich 2 :[20..70] // 30..60 Hysterese -10 und +10 //Mitte 45 +- 25
> Bereich 3 :[50..100] // 60..90 Hysterese -10 und +10 //Mitte 75 +- 25
> ....
> Beim unterschreiten wechselt man in den Bereich darunter und beim
> überschreiten in denjenigen darüber.
>
Also durch diese theoretische Lösung steige ich nicht durch.


Denke das durch den einfachen Vergleich eines Wertes und dann die 
sofortige Reaktion beim Überschreiten und Unterschreiten dessen,
der Wurm zu suchen ist.
1
cp r20,r21              ; Ist-Schwellwert
2
brcc end_loop           ; wenn Schwellwert < -> fertig
3
lsr r18                 ; Bargraf
...
1
end_loop: 
2
com r18                 ; negieren (wegen STK500)
3
out PortA,r18
4
5
rjmp mainloop

Bernd_Stein

von Horst H. (horha)


Lesenswert?

Hallo,
@Bernd Stein
> Denke das durch den einfachen Vergleich eines Wertes und dann die
> sofortige Reaktion beim Überschreiten und Unterschreiten dessen,
> der Wurm zu suchen ist.
zuvor
>120, 119, 120. Dort kann man sehr schön sehen, das es keine Hysterese an diesem 
Punkt gibt

Dann zeig doch mal für 3 Bereiche auf wie das ablaufen soll, wenn der 
Wert langsam  0.. max ansteigt und dann wieder auf 0 abfällt.
Mit Schaltschwellen und Umschaltwerten.
I = 0..119; II = 120..199; III = 200..255

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.