Lazareth
20.11.2009, 11:29
Morgen leute!!!!
also, ich fang am besten mal von vorne an. Ich habe für meinen vater und dessen Hühner eine automatische klappe gebastelt, die auf Helligkeit reagiert und die Klappe entsprechend bewegt. hat seit rund 2 monaten alles wunderbar funktioniert, kein huhn war bisher unter der klappe o.ä.
nun seit geraumer zeit, macht die klappe allerdings komische gestalten. Immer (nicht immer, geht mal 2-5 tage gut, aber immer in der herabbewegung) beim herabfahren, reagiert der ATmega8 nichtmehr. der motor dreht munter weiter und nur ein ausschalten der schaltung bringt diesen zum stoppen. Ich hab mittlerweile den µC, den LDR und die komplette Schaltung getauscht, ohne erfolg.
zum aufbau am besten mal ein Schaltplan:
http://img44.imageshack.us/img44/4396/huehnerklappe.png
ich denke, die anschlussbelegung sollte klar sein, Motor, LDR und Endschalter als abschaltende begrenzung.
zum Programm:
ich erkläre mal kurz, was ich mir dabei gedacht habe :)
also, ich setze den C für rund 4 min schlafen, und überprüfe dann den Spannungswert am ADC. sollte eine änderung eingetreten sein, wird entsprechend reagiert.
haupt:
in "haupt" wird die Spannung abgefragt und bei einer änderung entsprechend verzweigt.
slep:
legt den C für 4 min schlafen.
auf/ab:
setzt die ausgänge entsprechend fürs hinauf/abfahren und wartet bis ein schalter auslöst oder die zeit für die bewegung beendet ist (sicherheit).
entprellen:
entprellt die mechanischen Endschalter. hierfür wird auch die software-warteschleife ms10 benötigt.
zeitaktiv_auf/ab:
hier wird der Timer gesetzt, solange die bewegung maximal dauern darf (für hoch und runter unterschiedliche zeiten, weil der auffahren länger dauert)
timer0:
ist die reaktion auf die abgelaufene zeit ( ausgänge abschalten, und timer rücksetzen)
daher kommt auch meine annahme das der µC abschmiert, weil er weder auf die zeit, noch auf die endschalter reagiert. und die ausgäng bleiben tatsächlich bis zum abschalten gesetzt, ich habe entsprechend LED´s dran gelötet.
habe das programm nun schon nach nem überlaufenden stack hin untersucht, leider nichts gefunden. vielleicht schaut mal schnell ein profi drüber ob er einen fehler findet, bzw. ob er eine andere vermutung hat.
ich danke deshalb schonmal im voraus für eure hilfe, bin gerade leicht am verzweifeln =P
.equ zeit = 1700 ;für die MS10 routine, 10ms warteschleife
.equ schleife_durch = 10 ;10 ;für entprellroutine durchläufe
.equ schleife_sleep = 4 ;4 ;schleifendurchläufe für timer. 1 durchlauf = 67 sekunden.
.equ slep_tcnt_vorladen = 1 ;zum vorladen des register tcnt des timers 1, um feiner abstufungen zu erreichen. Normal=0
.equ adc_wert = 130 ;100 ;vergleichswert für adc und lichtsensor
.equ Zeit_hochfahren = 33 ;33 ;Wert zur einstellung der Zeit, die für das hochfahren der klappe verantwortlich ist.
.equ Zeit_runterfahren = 24 ;24 ;wert zur einstellung der Zeit für das Herunterfahren
;4 => 1 sec. (1zyklus = 261,1 ms)
; = 4.22V am LDR = 21.14Uhr am 24.07.09
; 4.66V am LDR = 21.23Uhr
; differenz rund 0.44 V
;***definitionsdatei***
.include "m8def.inc"
;***interrupt adressen***
.org 0x000 rjmp reset ;Programm start
;.org 0x001 rjmp stop ;Näherungsschalter
;.org 0x002 rjmp aus ;Interrupt schalter
.org 0x008 rjmp timer ;Timer für sicherheit, wird aktiviert nach dem schalten der ausgänge
.org 0x009 rjmp timer0 ;Timer0 für das hoch/runterfahren der tür
; Stack initialisieren
reset:
ldi r16, LOW(RAMEND)
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16
;Ein/Ausgänge konfigurieren
ser r16 ;ausgang
out DDRB, r16
clr r16 ;Eingang
out DDRC, r16
out DDRD, r16
;sleep mode aktivieren
ldi r16, 0b10000000; 0b10001111
out MCUCR, r16
;ldi r16, 0b00000001
;out GICR, r16
;variable für ersten durchlauf ins register kopieren
ldi r16, 1
mov r2, r16
sei ;interrupts frei
Haupt:
;ADC konfig, ADC0
ldi r16, 0b01100000
out admux, r16
ldi r16, 0b11000011
out adcsra, r16
adcrun:
in r10, adcsra
sbrc r10, 6
rjmp adcrun
;adc werte in reg. schreiben
in r17, ADCL
in r18, ADCH
;ACHTUNG, unteren WERT ebenfalls ändern
cpi r18, adc_wert ;hier einstellwert für sreg
in r16, SREG ;SREG speichern
andi r16, 0b00000001
mov r1, r16
eor r1, r0
mov r0, r16
sbrc r2, 0
rjmp erstedurchgang
breq slep
;ACHTUNG, oberen Wert ebenfalls ändern
cpi r18, adc_wert ;hier einstellwert
brlo ab1 ;hier tor zu
brsh auf1 ;hier tor auf
rjmp slep
;unterprogramme
slep: ;schlafen legen, und alle 10 min wieder wecken
ldi r16, 0b00000101 ;teiler
out TCCR1B, r16
ldi r16, 0b00000100
out TIMSK, r16
ldi r30, schleife_sleep ;schleifendurchläufe für wartezeit
clr r31
slep1:
;wdr ;watchdog reset
ldi r16, low(slep_tcnt_vorladen) ;63535 ins register laden = 2 sekunden
ldi r17, high(slep_tcnt_vorladen)
out TCNT1H, r17
out TCNT1L, r16
sleep
nop
tst r30
brne slep1
rjmp haupt
erstedurchgang:
clr r2
rjmp haupt
auf1:
ldi r16, 0b00000101
out PORTB, r16
rcall zeitaktiv_auf ;Timer1 für Sicherheitszeit aktivieren
;warten bis schalter betätigt
warten1:
sbrc r31, 0 ;wenn timer1 interrupt fahrt beendet
rjmp slep ;dann springt wieder nach slep zurück
in r16, PIND
sbrc r16, 3
rjmp entprellen
rjmp warten1
ab1:
ldi r16, 0b00000110
out PORTB, r16
rcall zeitaktiv_ab ;Timer1 für Sicherheitszeit aktivieren
;warten bis schalter betätigt
warten2:
sbrc r31, 0 ;wenn timer1 interrupt fahrt beendet
rjmp slep ;dann springt wieder nach slep zurück
in r16, PIND
sbrc r16, 2
rjmp entprellen
rjmp warten2
;entprell routine
entprellen:
push r16
ldi r17, schleife_durch ;schleifendurchläufe
in r16, PIND
mov r3, r16
aus1:
in r16, PIND
mov r2, r16
eor r2, r3
mov r3, r16
push r16
rcall ms10
pop r16
dec r17
tst r17
brne aus1
sbrc r16, 3
rjmp aus2
sbrc r16, 2
rjmp aus2
rcall ms10
clr r17
pop r16
rjmp slep
aus2:
clr r16
clr r17
clr r19
out PORTB, r16
out TCCR0, r16 ;timer deaktivieren
out TCNT0, r16 ;timer0 zählregister nullen
pop r16
rjmp slep
;timer0 fürs bewegen der Tür aktivieren
zeitaktiv_auf:
;r29 zum herunterzählen beladen.
ldi r29, zeit_hochfahren
ldi r16, 0b00000101 ;teiler
out TCCR0, r16
ldi r16, 0b00000001 ;interrupt starten
out TIMSK, r16
ret
zeitaktiv_ab:
;r29 zum herunterzählen beladen.
ldi r29, zeit_runterfahren
ldi r16, 0b00000101 ;teiler
out TCCR0, r16
ldi r16, 0b00000001 ;interrupt starten
out TIMSK, r16
ret
;***********Warteschleife*********
ms10: ;taster entprellen
;wdr
push r17
push r18
ldi r16, low(zeit)
ldi r17, byte2(zeit)
ldi r18, byte3(zeit)
ms101:
subi r16, low(1) ;1 Takt
sbci r17, byte2(1) ;1 Takt
sbci r18, byte3(1) ;1 Takt
sbrs r18, 0 ;1 takt
breq ms102 ;
rjmp ms101 ;2 takte
ms102:
pop r18
pop r17
ret
;*************************interrupt handler***************************
;sleep-timer, 16 bit
timer:
dec r30
reti
;nach abgelaufener zeit motor aus, timer0, 8bit
timer0:
dec r29
tst r29
breq timer0_stop
reti
timer0_stop:
push r16
clr r16
out PORTB, r16
out TCCR0, r16
out TCNT0, r16
sbr r31,1
pop r16
reti
also, ich fang am besten mal von vorne an. Ich habe für meinen vater und dessen Hühner eine automatische klappe gebastelt, die auf Helligkeit reagiert und die Klappe entsprechend bewegt. hat seit rund 2 monaten alles wunderbar funktioniert, kein huhn war bisher unter der klappe o.ä.
nun seit geraumer zeit, macht die klappe allerdings komische gestalten. Immer (nicht immer, geht mal 2-5 tage gut, aber immer in der herabbewegung) beim herabfahren, reagiert der ATmega8 nichtmehr. der motor dreht munter weiter und nur ein ausschalten der schaltung bringt diesen zum stoppen. Ich hab mittlerweile den µC, den LDR und die komplette Schaltung getauscht, ohne erfolg.
zum aufbau am besten mal ein Schaltplan:
http://img44.imageshack.us/img44/4396/huehnerklappe.png
ich denke, die anschlussbelegung sollte klar sein, Motor, LDR und Endschalter als abschaltende begrenzung.
zum Programm:
ich erkläre mal kurz, was ich mir dabei gedacht habe :)
also, ich setze den C für rund 4 min schlafen, und überprüfe dann den Spannungswert am ADC. sollte eine änderung eingetreten sein, wird entsprechend reagiert.
haupt:
in "haupt" wird die Spannung abgefragt und bei einer änderung entsprechend verzweigt.
slep:
legt den C für 4 min schlafen.
auf/ab:
setzt die ausgänge entsprechend fürs hinauf/abfahren und wartet bis ein schalter auslöst oder die zeit für die bewegung beendet ist (sicherheit).
entprellen:
entprellt die mechanischen Endschalter. hierfür wird auch die software-warteschleife ms10 benötigt.
zeitaktiv_auf/ab:
hier wird der Timer gesetzt, solange die bewegung maximal dauern darf (für hoch und runter unterschiedliche zeiten, weil der auffahren länger dauert)
timer0:
ist die reaktion auf die abgelaufene zeit ( ausgänge abschalten, und timer rücksetzen)
daher kommt auch meine annahme das der µC abschmiert, weil er weder auf die zeit, noch auf die endschalter reagiert. und die ausgäng bleiben tatsächlich bis zum abschalten gesetzt, ich habe entsprechend LED´s dran gelötet.
habe das programm nun schon nach nem überlaufenden stack hin untersucht, leider nichts gefunden. vielleicht schaut mal schnell ein profi drüber ob er einen fehler findet, bzw. ob er eine andere vermutung hat.
ich danke deshalb schonmal im voraus für eure hilfe, bin gerade leicht am verzweifeln =P
.equ zeit = 1700 ;für die MS10 routine, 10ms warteschleife
.equ schleife_durch = 10 ;10 ;für entprellroutine durchläufe
.equ schleife_sleep = 4 ;4 ;schleifendurchläufe für timer. 1 durchlauf = 67 sekunden.
.equ slep_tcnt_vorladen = 1 ;zum vorladen des register tcnt des timers 1, um feiner abstufungen zu erreichen. Normal=0
.equ adc_wert = 130 ;100 ;vergleichswert für adc und lichtsensor
.equ Zeit_hochfahren = 33 ;33 ;Wert zur einstellung der Zeit, die für das hochfahren der klappe verantwortlich ist.
.equ Zeit_runterfahren = 24 ;24 ;wert zur einstellung der Zeit für das Herunterfahren
;4 => 1 sec. (1zyklus = 261,1 ms)
; = 4.22V am LDR = 21.14Uhr am 24.07.09
; 4.66V am LDR = 21.23Uhr
; differenz rund 0.44 V
;***definitionsdatei***
.include "m8def.inc"
;***interrupt adressen***
.org 0x000 rjmp reset ;Programm start
;.org 0x001 rjmp stop ;Näherungsschalter
;.org 0x002 rjmp aus ;Interrupt schalter
.org 0x008 rjmp timer ;Timer für sicherheit, wird aktiviert nach dem schalten der ausgänge
.org 0x009 rjmp timer0 ;Timer0 für das hoch/runterfahren der tür
; Stack initialisieren
reset:
ldi r16, LOW(RAMEND)
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16
;Ein/Ausgänge konfigurieren
ser r16 ;ausgang
out DDRB, r16
clr r16 ;Eingang
out DDRC, r16
out DDRD, r16
;sleep mode aktivieren
ldi r16, 0b10000000; 0b10001111
out MCUCR, r16
;ldi r16, 0b00000001
;out GICR, r16
;variable für ersten durchlauf ins register kopieren
ldi r16, 1
mov r2, r16
sei ;interrupts frei
Haupt:
;ADC konfig, ADC0
ldi r16, 0b01100000
out admux, r16
ldi r16, 0b11000011
out adcsra, r16
adcrun:
in r10, adcsra
sbrc r10, 6
rjmp adcrun
;adc werte in reg. schreiben
in r17, ADCL
in r18, ADCH
;ACHTUNG, unteren WERT ebenfalls ändern
cpi r18, adc_wert ;hier einstellwert für sreg
in r16, SREG ;SREG speichern
andi r16, 0b00000001
mov r1, r16
eor r1, r0
mov r0, r16
sbrc r2, 0
rjmp erstedurchgang
breq slep
;ACHTUNG, oberen Wert ebenfalls ändern
cpi r18, adc_wert ;hier einstellwert
brlo ab1 ;hier tor zu
brsh auf1 ;hier tor auf
rjmp slep
;unterprogramme
slep: ;schlafen legen, und alle 10 min wieder wecken
ldi r16, 0b00000101 ;teiler
out TCCR1B, r16
ldi r16, 0b00000100
out TIMSK, r16
ldi r30, schleife_sleep ;schleifendurchläufe für wartezeit
clr r31
slep1:
;wdr ;watchdog reset
ldi r16, low(slep_tcnt_vorladen) ;63535 ins register laden = 2 sekunden
ldi r17, high(slep_tcnt_vorladen)
out TCNT1H, r17
out TCNT1L, r16
sleep
nop
tst r30
brne slep1
rjmp haupt
erstedurchgang:
clr r2
rjmp haupt
auf1:
ldi r16, 0b00000101
out PORTB, r16
rcall zeitaktiv_auf ;Timer1 für Sicherheitszeit aktivieren
;warten bis schalter betätigt
warten1:
sbrc r31, 0 ;wenn timer1 interrupt fahrt beendet
rjmp slep ;dann springt wieder nach slep zurück
in r16, PIND
sbrc r16, 3
rjmp entprellen
rjmp warten1
ab1:
ldi r16, 0b00000110
out PORTB, r16
rcall zeitaktiv_ab ;Timer1 für Sicherheitszeit aktivieren
;warten bis schalter betätigt
warten2:
sbrc r31, 0 ;wenn timer1 interrupt fahrt beendet
rjmp slep ;dann springt wieder nach slep zurück
in r16, PIND
sbrc r16, 2
rjmp entprellen
rjmp warten2
;entprell routine
entprellen:
push r16
ldi r17, schleife_durch ;schleifendurchläufe
in r16, PIND
mov r3, r16
aus1:
in r16, PIND
mov r2, r16
eor r2, r3
mov r3, r16
push r16
rcall ms10
pop r16
dec r17
tst r17
brne aus1
sbrc r16, 3
rjmp aus2
sbrc r16, 2
rjmp aus2
rcall ms10
clr r17
pop r16
rjmp slep
aus2:
clr r16
clr r17
clr r19
out PORTB, r16
out TCCR0, r16 ;timer deaktivieren
out TCNT0, r16 ;timer0 zählregister nullen
pop r16
rjmp slep
;timer0 fürs bewegen der Tür aktivieren
zeitaktiv_auf:
;r29 zum herunterzählen beladen.
ldi r29, zeit_hochfahren
ldi r16, 0b00000101 ;teiler
out TCCR0, r16
ldi r16, 0b00000001 ;interrupt starten
out TIMSK, r16
ret
zeitaktiv_ab:
;r29 zum herunterzählen beladen.
ldi r29, zeit_runterfahren
ldi r16, 0b00000101 ;teiler
out TCCR0, r16
ldi r16, 0b00000001 ;interrupt starten
out TIMSK, r16
ret
;***********Warteschleife*********
ms10: ;taster entprellen
;wdr
push r17
push r18
ldi r16, low(zeit)
ldi r17, byte2(zeit)
ldi r18, byte3(zeit)
ms101:
subi r16, low(1) ;1 Takt
sbci r17, byte2(1) ;1 Takt
sbci r18, byte3(1) ;1 Takt
sbrs r18, 0 ;1 takt
breq ms102 ;
rjmp ms101 ;2 takte
ms102:
pop r18
pop r17
ret
;*************************interrupt handler***************************
;sleep-timer, 16 bit
timer:
dec r30
reti
;nach abgelaufener zeit motor aus, timer0, 8bit
timer0:
dec r29
tst r29
breq timer0_stop
reti
timer0_stop:
push r16
clr r16
out PORTB, r16
out TCCR0, r16
out TCNT0, r16
sbr r31,1
pop r16
reti