Als Wetterinteressierter haben mich Blitze
schon immer fasziniert. Durch diese Seite (http://www.techlib.com/electronics/lightning.html)
bin ich auf einen Blitzdetektor und eine Möglichkeit, Blitze zu zählen
(siehe „Readers Versions“), aufmerksam geworden.
Da ich gerade mit der Programmierung von Microcontrollern als Hobby begonnen hatte, schien mir dies ein geeignetes Projekt. Die Hardware beschränkte sich auf ein Minimum (s. Teileliste), und alles sollte auf einer Lochrasterplatine realisierbar sein. In einem zweiten Schritt konnte ich sogar einen Temperaturfühler meiner Wetterstation anschließen, die eine Aufzeichnung der registrierten Entladungen pro Minute erlaubt.
Da nichts haltbarer als das Provisorium ist, habe ich immer noch keine Platine geätzt, denn der Zähler funktioniert immer noch (wohl aber einen Boardplan schon erstellt (s.u.)).
Eine Kurze Zusammenfassung der Funktionsweise:
Zentraler Bestandteil des Zählers ist ein ATmega8, der die Daten auf einem kleinen LCD anzeigt und über einem programmierbaren Widerstand auf eine Wetterstation überträgt.
Der Prototyp wurde auf Lochrasterplatine aufgebaut, er enthält nur den Blitzzähler, nicht den Blitzdetektor! der Blitzdetektor wird separat per Kabel angebunden.
Wer eine (ungetestete) Platine ätzen möchte,
kann gerne bei mir
die Eagle-Dateien anfragen. Das war aber einer meiner ersten Gehversuche mit Eagle gewesen, daher ist großes Optimierungspotential vorhanden (Net?), und Fehlerfreiheit wird nicht
garantiert!
Abb: Schaltplan inkl. Blitzdetektor (rechte Seite)
Bauteil | Wert | Device/Package |
ANT1 | 20cm | Antennendraht |
C1 | 330n | C5B2.5 |
C2 | 100n | C5B2.5 |
C3 | 100n | C5B2.5 |
C4 | 100n | C5B2.5 |
C5 | 330n | C5B2.5 |
C6 | 10µ | E2-5 |
C7 | 100µ | E2-5 |
C10 | 10p | C050-025X075 |
C11 | .001µ | C050-025X075 |
C12 | 120p | C050-025X075 |
D3 | 1N914 | DO35-7 |
IC1 | ATMEGA8 | DIL08 |
IC2 | 0-100k | X9C104P |
L1 | 10mH | Induktivität |
L2 | 1 mH | Induktivität |
LCD1 | LCD 2X16 | z.B. YM-1602C |
LED1 | 2mA | rot LowPower 5mm |
LED2 | 2mA | gelb LowPower 5mm |
P1 | 10k | Trimmer/Poti |
Q1 | 2N2222A | TO92 (o. verglb.) |
Q2 | BC547 | TO92 |
Q3 | 32768Hz | Quarz |
Q4 | 2N2222A | TO92 (o. verglb.) |
Q5 | 2N3906 | TO92 |
R1 | 4k7 | |
R2 | 220 Ohm | |
R3 | 1k | |
R4 | 33k | |
R5 | 33k | |
R6 | 1k | |
R7 | 10k | |
R8 | 14k7 (10k+4,7k) | |
R9 | 10k | |
R10 | 270k | |
R11 | 270k | |
R12 | 1M | |
R13 | 82k | |
R14 | 10k | |
R15 | 10k | |
R16 | 3k9 | |
R17 | 4k7 | |
S1 | Taster | |
S2 | Taster | |
SG1 | F/CM12P | |
SV1 | Stecker | |
HIDEKI | Thermosensor |
Anbei noch der Bascom-Code (Original
und Compilat auf Anfrage).
Hinweis: Die Fuses eines originalen ATmega8 müssen nicht(!) verändert werden. Der externe Quarz ist ein Uhrenquarz, der parallel zum internen Oszillator schwingt und lediglich die Uhr steuert. Es ist nicht der Quarz, der den Prozessor treibt :-)
Weiterhin kann es notwendig sein, Kapazitäten auch am Uhrenquarz anbringen zu müssen, normalerweise ist dies aber nicht notwendig. Wenn die Uhr aber auch mehrere Minuten nach dem Stellen nicht anläuft, könnte man dies in Erwägung ziehen...
'(------------------------------------------------------------------------------ Filename : blitzzaehler_11v57D.bas Zweck : Blitz- und Gewitterzähler / Lightning and thunderstorm counter Datum : 21.08.2009 Autor : Dr. Christoph Winter Funktion : siehe http://www.jurmo.de/AVR Controller : ATmega8 Compiler : BASCOM-AVR Rev. 1.11.9.5 Features: * at least "MinBpG" lightnings within "SecsNoGewitter" minutes are needed to indicate a thunderstorm * "SecsNoGewitter" minutes after the last recorded lightning the current thunderstorm is considered over and the thunderstorm counter increased. * lightnings are recorded even in display statistics oder batt-test mode * lightnings are usually mutiple seperate discharges, wich are as well counted seperately. One visible lightning might therefore result in 4 or 5 counts. * the average lightnings per minute are calculated on a "lightnings number since first stroke in thunderstorm"-base or by the last 5 "lightnings in the last minute" values (last 5 minutes). * real time clock included - you can set the time in boot mode by holding button #2, untill the desired value is displayed. If you set the wrong tine, reset the whole counter and start over. * while no active thunderstorm, only statistics of previous thunderstorms are displayable. * Button 1 resets always to the clock and couter display. * Button 2 does: ** display the Battery Status+Voltage, if pressed when backlight is off. ** display small statistics of the current and previous thunderstorms. ** increases the values of the time units in setup mode after reset. To Do: - Features for the future: - History: - V1.0 21.08.2009 Public version Free for noncomercial use! For commercial use contact avr@jurmo.de All rights reserved! -------------------------------------------------------------------------------- Pin Configuration ATmega8 +----------+ (RESET) PC6 |1 28| PC5 (ADC5/SCL) (RXD) PD0 |2 27| PC4 (ADC4/SDA) (TXD) PD1 |3 26| PC3 (ADC3) (INT0) PD2 |4 25| PC2 (ADC2) (INT1) PD3 |5 24| PC1 (ADC1) (XCK/T0) PD4 |6 23| PC0 (ADC0) VCC |7 22| GND GND |8 21| AREF (XTAL1/TOSC1) PB6 |9 20| AVCC (XTAL2/TOSC2) PB7 |10 19| PB5 (SCK) (T1) PD5 |11 18| PB4 (MISO) (AIN0) PD6 |12 17| PB3 (MOSI/OC2) (AIN1) PD7 |13 16| PB2 (SS/OC1 B) (ICP1) PB0 |14 15| PB1 (OC1A) +----------+ ****************************************************** v20090712 C. Winter ****************************************************** ') '$sim ' N ' .NNNNL (N ' NN`N4N) ' NL N "` _NNNL. (N N)JNN._NNL ' 4NNN_ (NN"4NN (N NNF4NNN"NN) ' "4NNN) (NN_. (N NN (N` N) ' N NN "NNNNL (N N) (N N) ' NN N JN ._ 4N (N N) (N N) ' 4NLNJNF (NN_JNN (N N) (N N) ' 4NNNF `NNNF` (N N) (N N) ' N ' '======(N==========(NNN=================(N==N)================================== ' (N (N` (N N) ' _NNL(N JNNN_ (NNN) JNNNN. N) N) (N NNNN _NNNL. ' JNN"NNN NNF"NNL`4N"`NNN"4NN N) N) (N "NF"(NN"4NN ' NN NN (NL___NN (N "/_JNNN N) N) (N N) (NN_. ' N) (N (NNNNNNN (N JNNNNNN N) N) (N N) "NNNNL ' NN NN (N) __ (N NF NN NL (N) (N N) ._ 4N ' NN_NNN NNN_NNF (N NNLJNNN. NNLJNN) (N NN_(NN_JNN ' "NNF(N 4NNN" (N `NNN"(N) `NNN`N) (N 4NN `NNNF` '=============================================================================== 'Definition für ATmega8 $Regfile ="m8def.dat" $Crystal =1000000 $Hwstack =36 $Swstack =16 $framesize=30 '$Baud =4800 'Baudrate für UART $EEPROMHEX ' Nicht mit PonyProg!!!! '=====(N================N)=====================(N===(N========================== ' (N N) (N ' _NL(N JNN_ _NN. N) JNNN. (NJNN .NNNL (NNN) (N JNN. (N NN. _NNNL. ' JNNNNN NNFNNL JNNNN) N) NNN4NN (NN"N(NNFNN) (N (N NN"NN) (NNFNN (NN"4NN ' NN NN (NL__NN NN "` N) NNN (N) NN) (N (N (N) NN (N) 4N (NN_. ' N) (N (NNNNNN N) N) JNNNNN (N .NNNNN) (N (N (N (N (N (N "NNNNL ' NN NN (N) __ NN .N) N) NF NN (N (N` (N) (N (N (N) NN (N (N ._ 4N ' .NNNNN NNNNNF 4NNNN` N) NNLNNN.(N (NN_NNL (NL. (N NN_NN) (N (N (NN_JNN ' "NF(N 4NN" "NN` N) `NN"(N)(N 4NN`NN `NN) (N 4NN` (N (N `NNNF` '=============================================================================== 'The Port Data Direction Register ' IHGFEDCBA ' Alles Eingang, was nicht Ausgang sein soll. Spart Strom. ' 76543210 DDRB =&B00111110 'DATA DIRECTION definieren der verwendeten Ports (1 = ausgang; 0= eingang) PortB=&B11000001 'pullup (0= low level; 1= high level) ' 76543210 DDRC =&B00001010 'DATA DIRECTION definieren der verwendeten Ports (1 = ausgang; 0= eingang) PortC=&B11110100 'pullup (0= low level; 1= high level) ' 76543210 DDRD =&B11100011 'DATA DIRECTION definieren der verwendeten Ports (1 = ausgang; 0= eingang) PortD=&B11100011 'pullup (0= low level; 1= high level) ' digital Potentiometer: R_INC alias PortD.5 ' Increment Control R_UD alias PortD.6 ' Up/Down Control 'R_CS alias PortB.0 ' Chip Select immer auf LOW 'mcucr = &B00001010 config INT0 = rising ' Taster gegen 5V config INT1 = falling ' wird bei Blitz auf GND gezogen ' Taste 1 weckt aus dem Idle-Modus auf on INT0 OnTaste1 PortD2_INT0 alias PortD.2 ' Taster1 PortD2_INT0=0 ' Kein Pull-Up (gegen 5V!) PinD2_INT0 alias PinD.2 ' Taster1 enable INT0 ' Ein Blitz weckt aus dem Idle-Modus auf on INT1 OnBlitz PortD3_INT1 alias PortD.3 ' Taster2 PortD3_INT1=1 ' Kein Pull-Up (automatisch gegen 5V!) PinD3_INT0 alias PinD.3 ' Taster2 enable INT1 ' Funktioniert nur, wenn aufgeweckt (alle 60 ms). Taste3 alias PinD.4 ' Für Hintergrundbeleuchtung config Timer1=PWM, prescale=1, Compare A PWM=clear down config TIMER0=TIMER, prescale=256 ' Verwendet für Dimmen LED-Hintergrundbeleuchtung on TIMER0 OnTimer0 'Interrupt-Routine für Timer0-Overflow enable TIMER0 'Timer0-Overflow-Interrupt einschalten ' Comparator ausschalten (Strom sparen) config ACI=OFF 'Timer2 - simple Uhr config Clock=Soft, gosub=SecTic ' Timer2 config ADC=single, Prescaler=auto, Reference=internal ' 2,56V stop ADC ' Ausschalten - Strom sparen! config Watchdog = 2048 stop Watchdog ' Strom sparen - dieser Befehl ist redundant, da CONFIG WD bereits den WD stoppt. declare Sub IncrUnit(byref B as Byte, byval maxval as Byte) ' Uhrzeit stellen '=============================================================================== ' N .NNNL NNNNN. ' N (N" `NN N `4N. ' N N) N N) ' N (N_ _NF N .JN` ' NNNNN "NNNF NNNNF` '=============================================================================== LCD_DB4 alias PortB.5 ' Verbindung gezogen LCD_DB5 alias PortB.4 ' Verbindung gezogen LCD_DB6 alias PortB.3 ' Verbindung gezogen LCD_DB7 alias PortB.2 ' Verbindung gezogen LCD_E alias PortC.1 ' Verbindung gezogen LCD_RS alias PortC.3 ' Verbindung gezogen config LCD=16*2 ' LCD als 16x2 Zeichen konfigurieren ' LCD-Pins konfigurieren config LCDPIN=Pin, DB4=LCD_DB4, DB5=LCD_DB5, DB6=LCD_DB6, DB7=LCD_DB7, E=LCD_E, RS=LCD_RS config LCDBUS=4 ' LCD wird im 4-Bit-Modus betrieben GewittergefahrLED1 alias PortD.0 ' -> eine besteht Gewittergefahr BlitzanzeigeLED2 alias PortD.1 ' -> es Blitzt gerade Summer alias PortD.7 ' akustischer Blitzindikator Backlight alias PortB.1 ' Backlight '=======================(N==========N)=======N)================================= ' N) N) ' [N. JN .NNNNL NLNN)(N .NNNNL N)JNN_ N) .NNNL. _NNNL. ' `NL .NF(NNF"NN) NNF4)(N (NNF"NN) NNN"NNL N) (NN"4NN.(NN"4NN ' NN. (N)`"__NNN) NN (N `"__NNN) NN NN N) NN___JN)(NN_. ' (N) NN .NNNNNN) N) (N .NNNNNN) N) (N N) NNNNNNN) "NNNNL ' NN(N) (N` (N) N) (N (N` (N) NN NN N) NN ._.._ 4N ' (NNN (NN_NNNL N) (N (NN_NNNL NNN_NN) N) (NNLJNN`(NN_JNN ' NN) 4NNF`NN N) (N 4NNF`NN N)4NN" N) `NNNF` `NNNF` '=============================================================================== ' Texte aus dem EEPROM: dim BDummy as ERAM Byte ' die erste EEPROM-Speicherstelle leer lassen dim EEChk as ERAM Byte ' Prüfen, ob EEPROM geschrieben wurde dim TERAM(20) as ERAM String*16 ' Texte dim B as Byte ' Arbeits-Variable dim W as Word ' Arbeits-Variable dim L as Long ' Arbeits-Variable dim S as Single ' Arbeits-Variable dim S1$ as String*16 ' Arbeits-Variable dim S2$ as String*16 ' Arbeits-Variable dim Bitleiste as Byte ' nur ein einziges Flag_Timer0_Overflow alias Bitleiste.0 ' Überlaufindikator für PWM dunkler machen Flag_BPM alias Bitleiste.1 ' Blitze pro Minute bereits berechnet Flag_Gewitter alias Bitleiste.2 ' Es gab einen Blitz in den letzten 2 h FlagTaste1 alias Bitleiste.3 ' Taste1 Interrupt -> Taste1 gedrück? FlagSecTic2 alias Bitleiste.4 ' Zeit angezeigt? FlagSleeper alias Bitleiste.5 ' Sleep ja/nein FlagLCDcls alias Bitleiste.6 ' Clearscreen gemacht (Urhzeitanzeige)? FlagLowBat alias Bitleiste.7 ' Low Battery Flag dim Menu as Byte ' Anzahl "Menüs" dim BackLightCNT as Byte ' Runterzähler dim OSCCALval as Byte ' für den Originalwert... dim StatusLEDcnt as Byte ' Zähler zum Blinken der Statusled (ca. alle 5 Sekunden) dim Blitz as Long ' Gezuckt? dim BlitzStandLMin as Long ' Blitze in der letzten Minute dim GewitterdauerStart as Long ' Beginn des Gewitters dim LastBlitz as Long ' Blitzeinschlagzeit in Sekunden seit Systemstart dim SecTic2Cnt as Long ' Stand Sekunden letzer Blitz dim BlitzeAvg5(5) as Long ' Array für Daten Blitze pro Minute (über 5 Minuten) dim TagLGewitter as Long ' Der Tag des letzten Gewitters dim ResultList(14) as Long 'damit alle Variablen reinpassen dim Blitze as Long at ResultList Overlay ' Blitze gesamnt seit Einschalten dim LastBlitzZeit as Long at ResultList+04 Overlay ' Für "Minten nach letztem Blitz" Berechnungn dim Bp5M as Single at ResultList+08 Overlay ' Blitze pro 5 Minuten Avg x10 - Teilung später dim Bl5M as Long at ResultList+12 Overlay ' Blitze letzte 5 Minuten dim BpM as Single at ResultList+16 Overlay ' Blitze pro Minute Avg x10 - Teilung später dim BlM as Long at ResultList+20 Overlay ' Blitze letzte Minute x10 - Teilung später dim BpT as long at ResultList+24 Overlay ' Blitze pro Transfer dim BpGewitter as Long at ResultList+28 Overlay ' Blitze im aktuellen Gewitter dim Gewitterdauer as Long at ResultList+32 Overlay ' Dauer des Gewitters in Minuten dim LastBlitzeGewitter as Long at ResultList+36 Overlay ' Anz Blitze im letzten Gewitter dim LastGewitterdauer as Long at ResultList+40 Overlay ' letzte Gewitterdauer in Minuten dim DseitLGewitter as Long at ResultList+44 Overlay ' Tage seit letztem Gewitter dim AnzGewitter as Long at ResultList+48 Overlay ' Anzahl der detektierten Gewitter dim Laufzeit as Long at ResultList+52 Overlay ' Laufzeit seit Einschalten in Stunden dim Results_L(14) as Long at ResultList Overlay ' Array als Long auch noch drüberlegen dim Results_S(14) as Single at ResultList Overlay ' Array als Single auch noch drüberlegen const SecsNoGewitter=900 ' 10 min (60*15 sec) ohne Blitz = Gewitter vorbei const MaxMenu=28 ' Anzahl Anzeige-Zeilen (MaxMenu/2 = Anzahl Ergebnisse) const SecTic2Cnst=60 ' Nach 60 Sec. Nichtstun die Zeit anzeigen const Batt="Batt.:" ' Batterieanzeige const Volt="Spannung: " ' Batterieanzeige const ADCchannel=0 ' PinC.0 const BattOffset=664 ' 4.1V Offset (Beginn LOW BAT blinken) const SegmentDiv=23 ' Teiler für Segmente, 4.1-5V const VoltFact=0.0061 ' Faktor Umrechnung Digits2Volts const MinBpG=7 ' Mindestanzahl Blitze in SecsNoGewitter, um als Gewitter zu zählen '=(N==========(N==N)============================N)============================== ' N) N) ' (N N)JNNL (N NNNN .JNNL .NNNL .JNN.N) .NNNL. ' (N NNN"NN) (N "NF" .NNF4NN (NN"4NN .NNF4NN) (NN"4NN. ' (N NN `N) (N N) (N) `" NN (N)(N) (N) NN___JN) ' (N N) N) (N N) (NNN)(N N) N)(N N) NNNNNNN) ' (N N) N) (N N) (N) JN NN (N)(N) (N) NN ._. ' (N N) N) (N NN_ `NNLJNF (NN_JNN NNLJNN) (NNLJNN` ' (N N) N) (N 4NN `4NNF `NNNF `4NN`N) `NNNF` '=============================================================================== PWM1A=255 ' Licht an! gosub R_max ' Max R im Widerstand OSCCALval=OSCCAL ' OSCCAL merken zum zurückschreiben Blitze=0 ' Initial auf 0 Backlight=1 ' Licht an! Menu=1 ' Menüzeile initiieren Summer=1 ' gegen 5V -> Strom sparen, wenn HI R_INC=1 ' HIGH LastBlitz=2147483646-SecsNoGewitter ' Initial gab's noch keinen Blitz, daher später Zeitpunkt ' wenn hier gleich der Max-Wert drin steht, kommt es zum Überlauf :-) _day=01 : _month=01 : _year=00 ' Startzeit ' Start"programm" InitLCD ' LCD ein Cursor off noblink cls ' LCD Display löschen if EEChk<>127 then GewittergefahrLED1=0 ' Warnung! LCD "EEPROM leer!" end end if ' Im Simulationsmodus keine Uhrzeit manuell stellen! #IF _SIM _sec=59 #ELSE LCD " Blitzz";chr(225);"hler v1.0" wait 1 locate 2, 1 ' LCD-Zeile 1 LCD "(c) C. Winter 2009" GewittergefahrLED1=0 ' 0=an wait 3 for B = 1 To 4 shiftLCD left 'shift the text to the right toggle GewittergefahrLED1 toggle BlitzanzeigeLED2 waitms 500 next wait 2 gosub UhrStellen #ENDIF GewittergefahrLED1=1 ' LED aus (gegen 5V!) BlitzanzeigeLED2=1 ' LED aus (gegen 5V!) enable Interrupts FlagLCDcls=0 SecTic2Cnt=1 ' Zeit anzeigen erlauben FlagSecTic2=1 ' Zeit anzeigen erlauben FlagSleeper=0 ' Normale Geschwindigkeit gosub LCDBpG ' Ausgabe Text auf LCD '======================(N==============(N======================================= ' (N ' (N.NNL.JNN. .NNNNL (N N)JNNL (N JNNN. .NNNL (N.NNL. ' (NN"NNNF4NN (NNF"NN) (N NNN"NN) (N NNF"NN) (NN"4NN (NNF4NN. ' (N) NF (N `"__NNN) (N NN `N) (N (N) NN NN (N)(N) (N) ' (N N) (N .NNNNNN) (N N) N) (N (N (N N) N)(N N) ' (N N) (N (N` (N) (N N) N) (N (N) NN NN (N)(N) (N) ' (N N) (N (NN_NNNL (N N) N) (N NNL_NN) (NN_JNN (NNLJNN ' (N N) (N 4NNF`NN (N N) N) (N 4NNN` `NNNF (N"NNF` ' (N '==========================================================(N=================== do ' "What's up, Doc?" Aufwecken! if FlagTaste1=1 then FlagTaste1=0 gosub LichtAn FlagLCDcls=0 ' Kein CLS gemacht gosub LCDBpG SecTic2Cnt=1 ' refreshe dieses Bild jede Sekunde :-) FlagSecTic2=1 ' refreshe dieses Bild jede Sekunde :-) FlagSleeper=0 ' erst mal kein Schlafen - Taste 2 und anderes bleibt aktiv end if ' Blitz"einschlag" if Blitz>0 then ' Es gab einen Blitz! Blitze=Blitze+Blitz ' Gesamtanzahl Blitze Zähler hoch BpGewitter=BpGewitter+Blitz ' Blitze in diesem Gewitter Blitz=0 ' Reset Blitz Flag_BPM=1 ' Berechnungen Statistics erlauben Flag_Gewitter=1 ' Warning-LED ein, Blitz-Routinen ein LastBlitz=Syssec() ' Timestamp letzter Einschlag LastBlitzZeit=0 ' Minuten seit letztem Einschlag zurücksetzen gosub LichtAn BlitzanzeigeLED2=0 ' LED an for W=0 to 2500 ' Blitz in LED erzeugen toggle Summer waitus 15 next Summer=1 ' Strom sparen! BlitzanzeigeLED2=1 ' aus FlagLCDcls=0 ' Kein CLS gemacht gosub LCDBpG ' Ausgabe Text auf LCD if GewitterdauerStart=0 then ' Gewitterdauer in Minuten - Basiszeit GewitterdauerStart=Syssec() ' Beginn des Gewitters else ' nach dem ersten Blitz L=Syssec() ' Aktuelle Zeit Gewitterdauer=L-GewitterdauerStart : Gewitterdauer=Gewitterdauer\60 : incr Gewitterdauer ' in Minuten, mind. 1 end if SecTic2Cnt=1 ' refreshe dieses Bild jede Sekunde :-) FlagSecTic2=1 ' refreshe dieses Bild jede Sekunde :-) FlagSleeper=0 ' erst mal kein Schlafen - Taste 2 und anderes bleibt aktiv end if ' Ergebnisausgabe Taste3 debounce Taste3, 1, SubTaste3, sub ' Wenn ein Blitz in den letzten x Minuten gezuckt hat, dann Berechnungen durchführen! if Flag_Gewitter=1 then ' nur dann Rechnen, wenn erlaubt ' Hier könnte man auch sectic verwenden... if _Sec=0 and Flag_BPM=1 then ' mit Flag nur einmal während _Sec=0 (1x pro Minute statt MHz!) incr LastBlitzZeit ' Minuten seit letztem Einschlag + 1 Minute BlM=BpGewitter-BlitzStandLMin ' neuester Wert - Blitzstand der letzen Minute BpM=BpGewitter/Gewitterdauer ' Blitze pro Minute = Heftigkeit des Gewitters if BpM<0.01 then BpM=0 ' Falls sehr klein werdend, dann NULLen ' Durchschnittsberechnung: Bl5M=0 ' Reset irgendwelcher Werte for B=5 to 2 step -1 ' Array um eine Stelle verschieben BlitzeAvg5(B)=BlitzeAvg5(B-1) ' Verschieben 4->5, 3->4, 2->3, 1->2 Bl5M=Bl5M+BlitzeAvg5(B) ' Blitze der letzten vier Minuten addieren (neu 5-4-3-2,alt neu 4-3-2-1) next BlitzeAvg5(1)=BlM ' neuester Wert - Blitze der letzen Minute Bl5M=Bl5M+BlitzeAvg5(1) ' Letzte Minute hinzuaddieren Bp5M=Bl5M/5 ' über 5 Minuten Durchschnitt mitteln ' Maxwert der letzten 5 Minuten übertragen BpT=0 ' Nullen for B=1 to 5 ' max(Array) if BpT<BlitzeAvg5(B) then BpT=BlitzeAvg5(B) next gosub R_max ' Widerstand setzen for B=1 to BpT R_UD=0 ' down R_INC=0 waitus 15 R_INC=1 next BlitzStandLMin=BpGewitter ' AktuellenStand für nächsten Durchlauf merken ' nur einmal pro Min erledigen: Flag_BPM=0 ' Durchlauf durch diese Schleife dokumentieren end if if _Sec<>0 then Flag_BPM=1 ' Solange Schlafen nicht aktiv ist! ######## end if ' Hintergrundbeleuchtung und StatusLED if Flag_Timer0_Overflow=1 then if Flag_Gewitter=0 then ' sonst flackert schon die andere LED incr StatusLEDcnt if StatusLEDcnt>35 then ' kurzer Flash der StatusLED - ca. 5 sec im idle-Modus BlitzanzeigeLED2=0 ' an if StatusLEDcnt>36 then ' wieder ausschalten! BlitzanzeigeLED2=1 ' aus StatusLEDcnt=0 end if end if else BlitzanzeigeLED2=1 ' aus - nur an, wenn's Blitzt :-) end if if BackLightCNT>0 then decr BackLightCNT else if PWM1A>0 then decr PWM1A ' Licht langsam aus! OSCCAL=OSCCALval ' Originalwert else OSCCAL=0 ' Es ruhiger angehen lassen, es ist eh' dunkel (nix passiert...) FlagSleeper=1 ' Erlaube Idle, bis Timer0, SecTic oder INT0 oder Blitz(INT1) end if end if Flag_Timer0_Overflow=0 end if ' Wenn das Gewitter vorrüber ist (>15 min nach letztem Blitz)... L=LastBlitz+SecsNoGewitter ' Hilfsvariable nehmen if L<Syssec() then ' Wenn der letzte Blitz x min (NoGewitter) vorbei ist ' Nur dann, wenn mindestens MinBpG gezählt wurden - sonst als Background abtun! if BpGewitter>MinBpG then incr AnzGewitter ' wieder eins mehr... LastBlitzeGewitter=BpGewitter 'merken LastGewitterdauer=Gewitterdauer ' merken TagLGewitter=SysDay() ' WANN war das letzte Gewitter end if ' Rest immer zurücksetzen GewittergefahrLED1=1 ' LED aus BpGewitter=0 ' Kein Gewitter - keine Blitze! BlitzStandLMin=0 ' Anzahl Blitze in lezter Minute Gewitterdauer=0 GewitterdauerStart=0 LastBlitzZeit=0 for B=1 to 5 BlitzeAvg5(B)=0 next Bp5M=0 ' Reset Blitze pro Minute Bl5M=0 ' Reset Blitze letzte 5 Minuten BpM=0 ' Reset Blitze pro Minute BlM=0 ' Reset in letzter Minute BpT=0 ' Reset Blitze pro Transfer Flag_Gewitter=0 ' Kein Gewitter mehr LastBlitz=2147483646-SecsNoGewitter ' Wieder zurücksetzen (siehe INIT) end if ' Uhrzeit anzeigen, wenn nix passiert L=SecTic2Cnt+SecTic2Cnst ' Hilfsvariable nehmen if L<Syssec() then ' Wenn der letzte Event >60 Sec vorbei ist, auf Uhr umschalten if FlagSecTic2=1 then ' nur anzeigen, wenn Flag gesetzt (einmal pro Sekunde)! gosub SecTic2 end if end if ' Schlafen legen, wenn GAR NIX passiert... Aufwecken über Events if FlagSleeper=1 then ' Lege dich schlafen! ' sleep well idle 'per Timer0 alle 1MHz/256(prescale)/256(8bit-Überlauf)=15Hz aufwachen = alle 60ms aufwachen ' Optional: Bits 7..0 – CAL7..0: Oscillator Calibration Value ändern auf -50% end if loop end '=================N)===========================N)=============================== ' N) N) ' .JNNN_ N) N) N)JNN_ _NNNL. .NNNL. NNNN .JNNL ' NNF"NN) N) N) NNN"NNL (NN"4NN (NN"4NN."NF".NNF4NN ' NNL_ N) N) NN NN (NN_. NN___JN) N) (N) `" ' `4NNNN. N) N) N) (N "NNNNL NNNNNNN) N) (N ' _. `N) NL (N) NN NN ._ 4N NN ._. N) (N) JN ' NNL_NN) NNLJNN) NNN_NN) (NN_JNN (NNLJNN` NN_`NNLJNF ._ ' 4NNN" `NNN`N) N)4NN" `NNNF` `NNNF` 4NN `4NNF (N '=============================================================================== ' Zum Aufwecken und Anzeige des Status OnTaste1: FlagTaste1=1 ' Flag gesetzt! return ' Bei Blitz OnBlitz: incr Blitz ' Blitze zählen return ' Für PWM und Aufwecken OnTimer0: 'Interrupt-Routine 488 Hz (10^6/8/2569) Flag_Timer0_Overflow=1 Return ' Anzeige Blitze aktuelles Gewitter und Uhrzeit - Hauptanzeige LCDBpG: ' Hier kein direktes cls hin, sonst flackert's! if FlagLCDcls=0 then cls FlagLCDcls=1 end if locate 1, 1 ' LCD-Zeile 2 LCD "Blitze akt: ";BpGewitter;" " locate 2, 1 ' LCD-Zeile 2 LCD "Zeit: ";time$; Menu=1 ' Wieder von vorne anfangen return ' LED PWM auf MAX LichtAn: PWM1A=255 ' Licht an! BackLightCNT=100 ' Zähler für Backlight gleichbleibend hell return ' Ausgabe der einzelnen Ergebnisse SubTaste3: if PWM1A=0 then ' BatTest nur während Schlafen gosub BatTest else gosub LichtAn if Flag_Gewitter=0 and Menu<17 then Menu=17 ' wenn es noch kein Gewitter gab... if AnzGewitter=0 and Menu>16 then Menu=1 ' Wenn es vorher(!) noch kein Gewitter gab... Menu=Menu+2 ' Nächstes Menü - Menüzeile I (3 5 7 9...) if Menu>MaxMenu then Menu=1 ' bei Überlauf rücksetzen ' Ausgabe der Ergebniswerte cls S1$=TERAM(Menu) ' 16 Zeichen erste Zeile Results zurück LCD S1$ B=Menu+1 ' LCD Menüzeile II (2 4 6 8...) S2$=TERAM(B) ' Zeile 2 aus ERAM auslesen S2$=trim(S2$) B=B\2 ' LCD Ergebnis: (1 2 3 4 5...) ' Reset, falls Unsinn (Werte<0.00001 oder >500.000 machen keinen Sinn ' wenn >10000000 und <876543210 if Results_L(B)<100000000 then ' leicht zu merkende Unterscheidung, ob Long- oder Single S1$=str(Results_L(B)) ' Long else S1$=fusing(Results_S(B),"#.##") ' Single end if S1$=S2$+" "+S1$ locate 2, 1 LCD S1$ ' Text+Wert SecTic2Cnt=Syssec() ' Indikator Event FlagLCDcls=0 ' Kein CLS nach beenden der Routine end if return ' echtes SecTic SecTic: FlagSecTic2=1 ' Uhrzeit anzeigen nach 60 sec. if Flag_Gewitter=1 then toggle GewittergefahrLED1 ' GewitterwarnungsLED return ' KEIN echtes SecTic! SecTic2: Laufzeit=SysDay() ' Laufzeit in Tagen DseitLGewitter=Laufzeit-TagLGewitter ' Tage seit letztem Gewitter in Tagen FlagSecTic2=0 gosub LCDBpG return ' Uhrzeitroutine für das Stellen der Uhr am Anfang UhrStellen: cls LCD "Uhr stellen:" locate 2, 1 LCD "Std: " call IncrUnit(B, 23) _Hour=B locate 2, 1 LCD "Min: " call IncrUnit(B, 59) _Min=B locate 2, 1 LCD "Sek: " call IncrUnit(B, 59) _Sec=B return ' Stelle erhöhen bis MaxWert Sub IncrUnit(byref B as Byte, byval MaxVal as Byte) do ' drücken loop until Taste3=1 waitms 25 ' entprelle B=0 do ' halten incr B if B>MaxVal then B=0 locate 2, 5 LCD B;" " waitms 400 loop until Taste3=0 end Sub BatTest: start ADC cls waitms 10 PWM1A=255 ' Licht an while Taste3=1 W=getADC(ADCchannel) ' Batteriestand einlesen mit Spannungsteiler! S=W*VoltFact ' Eingangsspannung berechnen S2$=fusing(S,"#.#") ' Spannung formatieren W=W-BattOffset ' 5V->4.1 V Offset für Blöcke if W>1024 then W=0 ' BattOffset größer getADC, Overflow! B=W\SegmentDiv : incr B ' in 10%-Schritten if B>10 then B=10 ' Max if B<=1 then ' Low Batt! Blinken! FlagLowBat=1 ' merken! locate 1, 1 LCD Batt+chr(255) waitms 500 S1$=Batt ' Nur Text und Block löschen else FlagLowBat=0 ' OK! S1$=string(B,255) ' Blocks S1$=Batt+S1$ ' Text + Blocks end if locate 1, 1 LCD S1$;" " ' Ladestatus ausgeben locate 2, 1 LCD Volt;S2$;"V" waitms 500 wend PWM1A=0 ' Licht aus Stop ADC return R_max: for B=1 to 100 R_UD=1 ' up R_INC=0 waitus 10 R_INC=1 next return '=============================================================================== ' .NNNL. JNNN_ N)JNN_ (NJNN JNNN. (N.NNL.JNN. ' (NN"4NN. NNF"NNL NNN"NNL (NN"N NNF"NN) (NN"NNNF4NN ' NN___JN)(NL___NN NN NN (N) (N) NN (N) NF (N ' NNNNNNN)(NNNNNNN N) (N (N (N (N (N N) (N ' NN ._.(N) __ NN NN (N (N) NN (N N) (N ' (NNLJNN` NNN_NNF NNN_NN) (N NNL_NN) (N N) (N ' `NNNF` 4NNN" NF4NN" (N 4NNN` (N N) (N ' N) '==================N)=========================================================== $eeprom DATA 0 ' 1. Stelle DATA 127 ' 2. Stelle: Kennung: Beschrieben! (default ist 255): '1234567890123456' max 16 Stellen DATA "Blitze gesamt: " DATA " " DATA "Letzter Blitz " DATA "vor (Min.): " DATA "Blitze pro Min. " DATA "(5 Min.): " DATA "Blitze letzte " DATA "5 Minuten: " DATA "Blitze pro " DATA "Minute: " DATA "Blitze letzte " DATA "Minute: " DATA "Blitze pro " DATA "Transfer: " DATA "Blitze in diesem" DATA "Gewitter: " DATA "Gewitterdauer in" DATA "Minuten: " DATA "Blitze letztes " DATA "Gewitter: " DATA "Letzte Gewitter-" DATA "dauer (Min): " DATA "Tage seit letzt." DATA "Gewitter: " DATA "Anzahl Gewitter:" DATA " " DATA "Gesamtlaufzeit " DATA "in Tagen: " $data end |
Christoph Winter, 2010
Alle Rechte vorbehalten
Last change: Fuses | C. Winter, 09. September 2011 |
Change: freigeschaltet | C. Winter, 23. Januar 2010 |