Blitzzähler

 

(c) C. Winter 2009, 2010, v1.0


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.)).

Abb: der Prototyp des Blitzzählers (die Weihnachtsbeleuchtung gehört nicht dazu ;-)


Abb: Aufzeichnung eines Gewitters am 30.6.2009 - max. 32 Entladungen/min wurden gezählt.


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.

Insgesamt sind im Programm folgende Funktionen hinterlegt: Angezeigt werden können folgende Werte:




 

Aufbau


Der Prototyp wurde auf Lochrasterplatine aufgebaut, er enthält nur den Blitzzähler, nicht den Blitzdetektor! der Blitzdetektor wird separat per Kabel angebunden.
 

Abb: Aufbau in Funktion (Anzeige wählbar)


Abb: Die Lochrasterplatine stellt sich so dar (LCD abgenommen)


Abb: Rückseite mit hervorgehobenen Signal- und Versorgungsleitungen. Die Leitungsverlegung ist nicht immer optimal (manchmal seltsam), aber sie funktioniert...
(rechter Mausklick auf das Bild und "Speichern als" sichert das Bild in höherer Auflösung und mit mehr Details)
Signale: grün, blau, gelb
+5V: rot
GND: schwarz
 
 

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)
 
 
Bauteilliste (inkl. Blitzdetektor)
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
 
 

Zurück zur Hauptebene / Back to main level



Last change: Fuses C. Winter, 09. September  2011
Change: freigeschaltet C. Winter, 23. Januar  2010