;Phasenanschnittsteuerung SLB0587-Ersatz mit ATtiny11-13
;UNFERTIG!
#define ATtiny
.NOLIST
#ifdef ATtiny
.include "tn11def.inc"
#else
.include "m8def.inc"
#endif
;.include "makros.i90"
.LIST
.listmac
;****************
;** Konstanten **
;****************
;Belegung GPIO (Pin)
;.equ TRIAC2 =0 ;(7) Triac-Steuerausgang, 0=EIN, TS=AUS
.equ SENSOR2 =1 ;(6) Sensorkontakt für zweiten Triac
.equ SENSOR =2 ;(5) Sensorkontakt für ersten Triac
.equ USENSE =3 ;(4) Spannungsüberwachung am 1. Triac
.equ TRIAC =4 ;(3) Triac-Steuerausgang, 0=EIN, TS=AUS
.equ MODE =5 ;(2) an + (A), offen (B), an - (C)
;Zurzeit nur ein Triac, WAHLWEISE an TRIAC oder TRIAC2 anschließbar!
;************************
;** RAM-Speicherzellen **
;************************
.def tmp0 = r17 ;Zwischenwert (Berechnung)
.def KeyBits = r18 ;Diverse Bits zur Tastensteuerung
;0 = Sensor vorher gedrückt (Unterdrückung einzelner Fehler)
;1 = Sensor gilt als gedrückt (>50ms)
;2 = Sensor-Langzeitdruck (>400ms)
;3 = Richtungsbit, 1=hoch, 0=runter (Helligkeit)
;4 = MODE klebt an + (Modus "A" lt. Datenblatt)
;5 = MODE klebt an - (Modus "C" lt. Datenblatt)
;6 = Licht EIN (ansonsten ist "Hell" der Speicherwert)
.def KeyCnt = r19 ;Zähler für Autorepeat
.def Hell = r11 ;Soll-Helligkeit (Zündwinkel)
.def Real = r12 ;Ist-Helligkeit wegen Softstart (Zündwinkel)
.def HellMin = r13 ;Mindest-Helligkeit (25%)
.def HellMax = r14 ;Höchst-Helligkeit (95%)
.def T2 = r15 ;Halbe Periodendauer
.equ CPUCLK = 1000000 ;Hz
.equ DEFGPIO = 0x3F;2Eh ;Normalzustand für GPIO-Ausgaberegister
.equ DEFTRIS = 0x0D;3Fh ;Normalzustand für TRIS-Ausgaberegister: Eingänge
.equ DEFOPT = 0x86 ;keine Pull-Ups(!!), Vorteiler=128, Zählerperiode > 32ms
;Zur Begrenzung der Nulldurchgangs-Suche (15 und 22 sind Millisekunden)
.equ MINCT0 = 10;15*CPUCLK/1000/128 ;Minimaler "erlaubter" Zählerstand (117)
.equ MAXCT0 = 255;22*CPUCLK/1000/128 ;Maximaler "erlaubter" Zählerstand (171)
;*********************
;** Programm im ROM **
;*********************
.org 0
rjmp startup
;====================
;== Unterprogramme ==
;====================
AdjustLimits:
;Anhand des gespeicherten Wertes für T2 die Werte HellMin(30%), HellMax(95%)
;berechnen und ggf. "Hell" eingrenzen
mov tmp0,T2
lsr tmp0 ;viertel Periodendauer (50%) laden
lsr tmp0 ;achtel Periodendauer (75%)
mov r16,T2
sub r16,tmp0 ;3/8 Periodendauer (25%)
cp Hell,HellMin ;Hell-HellMin, C=1 wenn Hell<HellMin (OK)
brcc al1
mov Hell,HellMin
al1: lsr tmp0 ;1/16 Periodendauer (88%)
lsr tmp0 ;1/32 Periodendauer (94%)
cp Hell,HellMax ;Hell-HellMax, C=1 wenn Hell<HellMax (nicht OK)
brcs al2
mov Hell,HellMax
al2: ret
ZeroCross: ;Sucht Nulldurchgang (des Stroms) so dass Spannung negativ wird
;Bei >22ms Periodendauer wird von einem Fehler ausgegangen
;Warten bis USENSE=H, dabei Zählerüberlauf detektieren
; movlw DEFGPIO&~(1<<SENSOR2)
; movwf GPIO
zc_1: in r16,TCNT0
cpi r16,MAXCT0
brcc zc_err
sbis PinB,USENSE
rjmp zc_1 ;warte solange USENSE=L
; movlw DEFGPIO
; movwf GPIO
zc_2: in r16,TCNT0
cpi r16,MAXCT0
brcc zc_err
sbic PinB,USENSE
rjmp zc_2 ;warte solange USENSE=H
cpi r16,MINCT0
brcs zc_1 ;warte solange zu wenig Zeit vergangen ist
lsr r16 ;Zählerwert halbieren
mov T2,r16 ;neue halbe Periodendauer
clr r16 ;Zähler neu starten
out TCNT0,r16
ret
zc_err: sec
ret
HandleSensor: ;Aufruf alle 20ms, nachdem USENSE auf L gegangen ist
;SENSOR ist H, wenn eine externe Kapazität (Mensch) den H-L-Wechsel verzögert
sbis PinB,SENSOR
rjmp hs_touched
; btfsc GPIO,SENSOR2
; goto hs_touched
;Sensor nicht berührt
sbrc KeyBits,0
rjmp hs_killonspike ;Einzel-OFF-Impuls ignorieren
sbrs KeyBits,1
ret ;Wenn nicht berührt gewesen, nichts tun!
cbr KeyBits,1<<1 ;Beim nächsten Mal nichts tun
sbrs KeyBits,2
rjmp hs_release_short
ldi r16,1<<3 ;Richtungsbit
sbrs KeyBits,4 ;Wenn MODE an + klebt Richtung NICHT ändern
eor KeyBits,r16
rjmp hs_switch_off
hs_release_short:
sbrs KeyBits,6 ;Licht brennt?
rjmp hs_switch_on ;nein, einschalten
hs_switch_off:
cbr KeyBits,1<<6 ;Licht AUS
ret
hs_switch_on:
sbrc KeyBits,4 ;Klebt an +? Maximum laden!
mov Hell,HellMax
sbrc KeyBits,5 ;Klebt an -? Maximum laden!
mov Hell,HellMax
sbr KeyBits,1<<6 ;Licht AN
ret
hs_killonspike:
cbr KeyBits,1<<0
hs_ret: ret
hs_touched: ;Sensor berührt
sbrs KeyBits,0
rjmp hs_killoffspike
sbrs KeyBits,1
rjmp hs_inittouch ;Wenn nicht berührt gewesen, Zähler init.
dec KeyCnt
brne hs_ret ;nichts tun wenn <>0
sbrc KeyBits,2 ;"Lange" Berührung?
rjmp hs_longtouch
sbrc KeyBits,4 ;Klebt an +? Minimum laden!
mov Hell,HellMin
sbrc KeyBits,5 ;Klebt an -? Minimum laden!
mov Hell,HellMin
;Licht AN
sbr KeyBits,(1<<2)|(1<<6) ;auf "lange Berührung" umschalten
ldi KeyCnt,5 ;Zähler laden, erster Repeat länger als 3
hs_longtouch:
cp Hell,HellMin ;Minimum ist erreicht?
brne hs_1
sbr KeyBits,1<<3 ;Richtung RAUF
hs_1: cp Hell,HellMax ;Maximum ist erreicht?
brne hs_2
cbr KeyBits,1<<3 ;Richtung RUNTER
hs_2: sbrc KeyBits,3
dec Hell ;RAUF (Anschnittwinkel verkleinern)
sbrs KeyBits,3
inc Hell ;RUNTER (Anschnittwinkel vergrößern)
ldi KeyCnt,3
ret
hs_inittouch:
sbr KeyBits,1<<1 ;"Berührt" melden
cbr KeyBits,1<<2 ;"Kurzer Tastendruck" melden
ldi KeyCnt,8 ;Zähler für 400ms
ret
hs_killoffspike:
sbr KeyBits,1<<0
ret
HandleSoftstart: ;Aufruf nach HandleSensor (alle 20ms)
;Nachführung von "Real" an "Hell"; Aufruf nur wenn EIN!
cp Hell,Real ;C=1 wenn Hell<Real
brcs hs_soft ;wenn Real>Hell
mov Real,Hell ;Zündwinkel halten oder vergrößern
ret
hs_soft:
dec Real ;Zündwinkel langsam verkleinern
ret
ReadMode: ;Verbindung (nach + oder -) am MODE-Pin prüfen
cbr KeyBits,(1<<4)|(1<<5)
sbi DDRB,MODE ;H ausgeben
nop
sbic PinB,MODE ;wenns an Minus (Udd) klebt
rjmp rm_nominus
cbi DDRB,MODE ;Treiber sofort entlasten (Kurzschluss!)
sbr KeyBits,1<<5
ret
rm_nominus:
cbi PortB,MODE ;L ausgeben
nop
sbic PinB,MODE ;wenns an Plus (Uss) klebt
sbr KeyBits,1<<4
sbi PortB,MODE
cbi DDRB,MODE ;Z ausgeben
ret
FireNow: ;Drei Zündimpulse (je 10µs) ausgeben
ldi tmp0,10
fn_loop:
;movlw DEFTRIS&~((1<<TRIAC)|(1<<TRIAC2))
;tris GPIO ;L ausgeben - Zündung
cbi PortB,TRIAC
nop
nop
nop
nop
nop
nop
nop
nop
;movlw DEFTRIS
;tris GPIO ;Z ausgeben
sbi PortB,TRIAC ;H ausgeben
dec tmp0
brne fn_loop
ret
FireNeg: ;Zündung Triac zur negativen (ersten) Halbwelle
fn_wait:
in r16,TCNT0
eor r16,Real
brne fn_wait
rjmp FireNow
;Bei der negativen Halbwelle wäre die Messung des Zünderfolgs möglich.
;Die dazu notwendige Zeit könnte zur positiven Halbwelle wiederholt werden,
;da hierbei nicht messbar.
;retlw 0
FirePos: ;Zündung Triac zur positiven (zweiten) Halbwelle
fp_wait:
in r16,TCNT0
mov tmp0,Real
add tmp0,T2
eor r16,tmp0
brne fp_wait
rjmp FireNow
;retlw 0
;===================
;== Hauptprogramm ==
;===================
startup:
;* Aktion 1:
; Ports einrichten, Option setzen
ldi r16,DEFOPT ;Vorteiler ???
out TCCR0,r16
ldi r16,DEFGPIO
out PortB,r16
ldi r16,DEFTRIS
out DDRB,r16
#if 0
test:
movlw DEFGPIO&~(1<<TRIAC)
movwf GPIO
movlw DEFGPIO&~(1<<MODE)
movwf GPIO
goto test
#endif
;* Aktion 2:
; H-L-Flanke abwarten, Timer starten (Timer zählt aufwärts)
fail:
; movlw DEFGPIO
; movwf GPIO ;gib H aus solange Low
f1: sbis PinB,USENSE
rjmp f1
; movlw DEFGPIO&~(1<<SENSOR2) ;gib L aus solange High
; movwf GPIO
f2: sbic PinB,USENSE
rjmp f2
; btfsc GPIO,SENSOR
; goto fail
clr r16
out TCNT0,r16
;* Aktion 3:
; Variablen vorbelegen
clr KeyBits
rcall ReadMode
rcall ZeroCross ;Periodendauer messen
rcall AdjustLimits
mov Hell,HellMin
;Hauptschleife
mainloop:
rcall ZeroCross
brcs fail
; call ReadMode
;Lt. Datenblatt 0,9ms warten, bevor Sensor eingelesen wird,
;das ist Zählerstand 7(!)
; btfsc GPIO,SENSOR
; bsf GPIO,MODE
; btfss GPIO,SENSOR
; bcf GPIO,MODE
rcall HandleSensor ;Unmittelbar nach ZeroCross!
rcall AdjustLimits
sbrs KeyBits,6 ;weiter nur wenn EIN
rjmp mainloop
rcall HandleSoftstart
rcall FireNeg
rcall FirePos
rjmp mainloop
Detected encoding: ANSI (CP1252) | 4
|
|