PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeitliche Ablaufsteuerung



Roboant
30.07.2013, 18:03
Hallo zusammen, folgendes Problem: Es wird an einem Atmega48 über ADC die Lichtverhältnisse geprüft es soll sein, dass bei Dunkelheit eine Sirene jede Std. für etwa 30sec eingeschaltet werden soll. Bei Tag ist die Schaltung quasi auf standby. Das mit dem Unterschied Tag und Nacht hab ich schon hinbekommen. Leider weiss ich nun nicht weiter, wie ich das mit der zeitlichen Steuerung hin bekomme. Vielleicht kann mir jemand mit Tipps weiterhelfen. Besten Dank und Gruß

Searcher
30.07.2013, 18:31
Man kann einen Timer zB im CTC Modus so einstellen, daß er jede Sekunde einen Interrupt erzeugt. In der ISR zählt er mit einer Variablen hoch, bis 30 Sekunden erreicht sind und schaltet die Sirene. Danach wird die Variable auf eine Stunde (3600 Sekunden) verglichen. Der Timer wird nur scharf geschaltet wenn es dunkel ist. Details kann man schauen, wenn Du einen Code reinstellst.

Gruß
Searcher

Roboant
30.07.2013, 19:12
Wie gesagt, hab erst mal nur den Teil mit dem Licht messen...der Rest fehlt noch, ich weiß nicht wie ich das bewerkstelligen soll, deshalb hier meine Frage. Außerdem schalte ich zur Zeit eine Led anstelle einer Sirene, das dürfte aber kein Problem darstellen, die Hardware ist für die Sirene schon ausgelegt.

$regfile = "m48def.dat"
$crystal = 12000000
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Dim Light As Word
Dim Bright As Word
Dim Dark As Word
Ldr Alias Getadc(0)
Licht Alias Portb.0
Config Licht = Output
Reset Licht
Light = 0
Dark = 400
Bright = 600

Do
'Nacht
If Ldr < Dark Then
Wait 2
If Ldr < Dark Then
Light = 1
End If
End If
'Tag
If Ldr > Bright Then
Wait 2
If Ldr > Bright Then
Light = 0
End If
End If
If Light = 1 Then
Licht = 1
Else
Licht = 0
End If

Loop
End

Searcher
30.07.2013, 20:31
Hallo,
so vielleicht. Ungetestet und ist bestimmt noch +- 1Sekunde Toleranz im Timing.
Meine Änderungen in Grün. Hoffenlich hab ich alles erwischt.

Gruß
Searcher



$regfile = "m48def.dat"
$crystal = 12000000
$framesize = 32
$swstack = 32
$hwstack = 34

Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Dim Light As Word
Dim Bright As Word
Dim Dark As Word
Ldr Alias Getadc(0)
Licht Alias Portb.0
Config Licht = Output
Reset Licht
Light = 0
Dark = 400
Bright = 600


Dim Sekundenzaehler As Word
ocr1a = 11718 'OCR1A Wert für Interrupt nach ca. 1,00002133 Sekunden
Config Timer1 = Timer , Prescale = 1024 , Clear_timer = 1 'startet Timer1 im CTC Modus mit OCR1A as Top
On compare1a Isr_sekundeninterrupt 'ISR wird jede Sekunde aufgerufen wenn ICP interrupt enabled ist
Enable Interrupts 'Interrupts global zulassen


Do
'Nacht
If Ldr < Dark Then
Wait 2
If Ldr < Dark Then
'Light = 1 'wird in ISR gesetzt
Enable compare1a 'Sekundenzaehler laufen lassen wenn es dunkel ist
End If
End If
'Tag
If Ldr > Bright Then
Wait 2
If Ldr > Bright Then
Disable compare1a 'Sekundenzaehler stoppen wenn es hell ist
Sekundenzaehler = 0 'initialisieren
Light = 0
End If
End If
If Light = 1 Then
Licht = 1
Else
Licht = 0
End If

Loop

Isr_sekundeninterrupt:
If Sekundenzaehler < 30 Then Light = 1 Else Light = 0 '30 Sekunden Licht/Sirene an danach aus
If Sekundenzaehler = 3600 Then Sekundenzaehler = 0 'Sekundenzaeler nach einer Stunde wieder bei 0 beginnen lassen
Incr Sekundenzaehler
Return

End

Roboant
31.07.2013, 07:28
Guten Morgen, super, vielen Dank schon mal für die Hilfe. Ich werde es testen und berichten !! Gruß Roboant

Andree-HB
31.07.2013, 08:02
...ich würde es mit der Tageszeit in Verbindung bringen, ansonsten hast Du bei jeder entsprechenden Veränderung am Lichtsensor einen Alarm-Auslöser, auch bei Gewitter/Regen am Tag oder dergleichen. Oder ist das gewollt ?

Damit könntest Du dann auch die Lichtabfrage sehr zeitgenau starten (à la " If Stunde > 20 and Minute = 00 Minute and Sekunden < 30 and Licht=Dark then Hupe an")

Roboant
31.07.2013, 08:18
@Searcher: habe den Code gerade mal eingespielt, leider funktioniert er so nicht. Besten Dank für Deine Hilfe. @Andree-HB: Bei der Lichtabfrage ist eine kleine Hysteresis eingebaut, dass heißt der LDR misst über einen Zeitraum die Lichtveränderung und soll dann das Horn aktivieren. Wie muss ich mir Deinen Tipp als Code vorstellen ??

Searcher
31.07.2013, 10:01
@Searcher: habe den Code gerade mal eingespielt, leider funktioniert er so nicht.

Hallo, hab gerade nochmal den Timer Mode im Simulator überprüft. Timer läuft im CTC Modus mit OCR1A as Top. Hab ich oben im Code berichtigt. Wie sieht es jetzt aus?

Gruß
Searcher

Roboant
31.07.2013, 16:53
Servus, habe die Veränderung getestet, die Sirene würde sich bei Dunkelheit 4Minuten einschalten und dann passiert nichts mehr, über zwei Std. beobachtet.

Searcher
31.07.2013, 17:15
... über zwei Std. beobachtet.

Oha :-)
ich gehe davon aus, daß Du einen 12MHz Quarz am µC hast. Wenn die 30 Sekunden zu 4 Minuten werden, läuft der µC 8 Mal zu langsam. CKDIV8 Fuse umgefused?!

Zum Testen kannst Du den Prescale vom Timer1 statt auf 1024 auf 8 oder sogar 1 setzten. Dann läuft alles entsprechend schneller.

Gruß
Searcher

Roboant
31.07.2013, 17:23
Ja genau auf 12MHz, und *schääähm* die Fuse nicht umgestellt..ich versuche und meld mich wieder!! Vielen Dank, für den Tipp...update...die 30 sec stimmen jetzt..teste die Std. nun.

Searcher
31.07.2013, 17:32
No problem. Bin ich auch schon öfter drauf reingefallen.
Prescale 8 mag ein bißchen schnell sein. Bei 64 werden die 30 Sekungen zu 30/(1024/64) = knapp 2 Sekunden und die Stunde zu knapp 4 Minuten.

Daumen drück
Gruß
Searcher

Roboant
01.08.2013, 08:55
@Searcher, Vielen vielen Dank!! Es funktioniert bestens.

Searcher
01.08.2013, 09:57
... Es funktioniert bestens.
*erleichtert* Prima, wenn es für Dich paßt.

Danke auch Dir; ich habe hier auch zum erstemal mitbekommen, daß man das GetADC direkt in der IF Abfrage verwenden kann.

Gibt natürlich noch 'ne Menge mehr und bessere Implementierungen als diese.
Wenn hier das Programm bei Helligkeit los läuft, fängt der Timer schon bei CONFIG TIMER1 an zu laufen, zählt aber wegen des noch nicht enabelten compare1a Interrupts die Sekunden noch nicht. Das Interruptflag wird aber schon nach der ersten Sekunde ab Timerlauf gesetzt.

Wird es nun dunkel und der Interrupt enabelt, wird der Interrupt durch das gesetzte Interruptflag sofort ausgeführt, egal welchen Wert der Timer1 hat und als erste Sekunde gezählt. Erreicht dann der Timer1 den OCR1A Wert, wird die zweite Sekunde gezählt. Ergebnis, die erste Sekunde ist praktisch immer zu kurz bemessen. Die Stundenmessung ist auch nicht ganz sekundengenau meine ich. Könnte man mit ein paar zusätzlichen Zeilen flicken; wird aber vermutlich bei Dir keine Rolle spielen.

Man könnte die WAIT Statements in der Hauptschleife loswerden, indem man die ISR für das Warten mitbenutzt.

Man könnte den Timer bei Helligkeit abschalten und nicht nur die Interrupts disablen - Strom sparen :-)

etc ...


Gruß
Searcher