PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mega 8 mit lcd Volt und Ampere und Amperesunden stürzt ab



mirco99
21.08.2008, 19:58
Hi,
ich habe ien Problem mit meinem Programm.
Es funktioniert einwandfrei bis der Amperestundenzähler 7mAh anzeigt.
Dann Zeigt das Display nur noch wirre Zeichen.
Irgendwann Zeigt es dann wieder alles richtig zB bei 20 mAh an und dann
fängt er wier mit Datenschrott im Display an. Nach 23 mAh geht die Anzeige auf #Null.
Alles seit dem ich bei Isr_von_timer1: die Amperestundenberechnung habe.


$regfile = "m8def.dat"
$crystal = 1000000


$hwstack = 32 ' default use 32 for the hardware stack

$swstack = 10 ' default use 10 for the SW stack

$framesize = 40 ' default use 40 for the frame space








Ddrc = &B11111001 'Pin PC1, PC2 Eingang
Config Adc = Single , Prescaler = Auto
Start Adc

'schalte den Timer1 ein
Config Timer1 = Timer , Prescale = 256 'timer 1 0 bis 65535 Zählen Taktfrequenz durch 256 =1000000/256=3906,25 Hz
Enable Timer1 ' 65536 - 3906 = 61630
On Timer1 Isr_von_timer1 'verzweige bei Timer1 überlauf zu Isr_von_Timer1
Enable Interrupts
Timer1 = 61630 'Timer1 soll schon von 61629 wegzählen



Dim Ah_zaehler As Word
Dim Ah As Single
Dim Watt_p As Word
Dim Wert As Word , Channel As Byte
Dim Volt As Single
Dim Adcstrom As Word
Dim Shuntspannung As Single
Dim Strom As Single
Dim Mstrom As Single
Dim Prozent As Word
'--------------------------------- EEPROM

'------------------------------

Config Lcdbus = 4
Config Lcd = 16 * 2 'configure lcd screen
Config Lcdpin = Pin , Db4 = Portb.1 , Db5 = Portb.2 , Db6 = Portb.3 , Db7 = Portb.4 , E = Portb.5 , Rs = Portb.6
Waitms 100
Initlcd
Waitms 100
Display On
Cursor Off Noblink
Cls



Do
Channel = 1
Wert = Getadc(channel) 'Spannungsmessung
Channel = 2
Adcstrom = Getadc(channel) 'Strommessung

Volt = 0.0048875855 * Wert ' 1024 /5 * ADC Wert = Spannung
Volt = Volt * 3 ' bei 15 Volt 5V am ADC

Shuntspannung = 0.00488 * Adcstrom ' Spannungsabfall Shunt in Volt
Strom = Shuntspannung / 3.9 ' Widerstand 3,7 Ohm
Mstrom = Strom * 1000 ' mA Umrechnung

'----------------------------------------- Amperestundenanzeige





Locate 1 , 1
Lcd Fusing(mstrom , "###.#") ; "mA" 'fusing Befehl für Stellenangabe ###.##


Locate 2 , 1
Lcd Fusing(volt , "##.##") ; "V "
Locate 2 , 8


'----------------------------- Ladesteuerung

If Volt < 13.4 Then
Portc.5 = 1
Locate 2 , 13
Lcd "lade "
End If

If Volt > 13.9 Then
Portc.5 = 0
Locate 1 , 10
Lcd "voll "

End If

Waitms 500
Loop
'------------------------------- geladene Ampere pro Stunde
Isr_von_timer1: 'ISR von Timer1
Timer1 = 61630 'Timer1 soll wieder von 61630 wegzählen
Toggle Portc.4 'schaltet Portd.0 im Sekundentakt
'EIN und AUS

Ah_zaehler = Ah_zaehler + Adcstrom 'ADC Shunt jede secunde in Ah_zaehler addiert
Ah = Ah_zaehler * 0.00488 'Spannung ausrechnen
Ah = Ah / 3.9 ' Strom Ausrechnen 3,9 Ohm
Ah = Ah / 3600 ' Ah Ausrechnen 1/sec = 3600
Locate 2 , 8

Lcd Fusing(ah , "#.###") ; "Ah"

Return

End

Dirk
21.08.2008, 20:24
Alles seit dem ich bei Isr_von_timer1: die Amperestundenberechnung habe.

Die Berechnung gehört auch nicht in eine ISR. Die ISR sollte so schnell wie möglich ablaufen und nur die nötigsten Werte berechnen, also keine langen Berechnungen machen und insbesondere keine LCD-Ausgaben, denn die dauern recht lange!

Man kann in der ISR z.B. ein Flag setzen. Wenn das gesetzt ist, wird im Hauptprogramm die Berechnung und LCD-Anzeige gemacht und das Flag zurückgesetzt.

Gruß Dirk

for_ro
21.08.2008, 21:37
Wenn du das mit der $dbg Directive im Simulator laufen lässt, wirst du feststellen, dass schon der erste Aufruf der Timer1 Isr nach einer Sekunde den HWStack überlaufen lässt. Danach ist alles reine Glücksache.
Also verdoppel mal die Werte von HWStack und SWStack und beherzige Dirks Kommentar, dann wird es schon werden.

Gruß

Rolf

mirco99
21.08.2008, 22:40
hi,
danke für die schnelle Antwort.
Flags habe ich noch nie gesetzt, werde mal in der Bascom Hilfe nachschauen. Was mir auf die schnelle einfällt...
Kann ich auch gosub benutzen, um die isr sofort zu verlassen um im Subprogramm die Berechnung durchzuführen?

Ich muss mich wohl auch noch mit HWStack und SWStack befassen und deren Auswirkungen bei falscher Dimensionierung.
Naja das ist mein 2. Programm, das ich schreibe.

Das erste war ne Temeratursteuerung für einen Laminator fur die Direkttonermethode um Platinen zu ätzen.

Wie groß darf der gespeicherte Wert mit einer Single Dimensionierung werden?

Danke nochmal, die framesize habe ich testweise schon verdoppelt, aber auf das isr Problem wäre ich nie gekommen.

So jetzt werde ich noch ein bisschen Matratzenhorchdienst betreiben, muss morgen früh raus.

for_ro
22.08.2008, 00:28
hi,
Kann ich auch gosub benutzen, um die isr sofort zu verlassen um im Subprogramm die Berechnung durchzuführen?


Nein, die Sub läuft dann immer noch in der Interrupt Umgebung, sprich es werden keine anderen Inrerupts zugelassen. Nur die Flags werden gesetzt, dass ein solcher Interrupt erkannt worden ist. Tritt ein Interrupt mehrmals während dieser Zeit auf, gehen alle außer dem ersten ganz verloren.
Also so machen, wie Dirk es beschrieben hat. Es gibt nichts Besseres.

Gruß

Rolf

mirco99
22.08.2008, 10:51
Hi Rolf und Dirk,

werde es heute Abend mal So ausprobieren.
Ich denke das meint ihr so oder?


Dim Timer_Flag as Byte

If Timer_Flag =1 Then
Timer_flag=0
Ah_zaehler = Ah_zaehler + Adcstrom 'ADC Shunt jede secunde in Ah_zaehler addiert
Ah = Ah_zaehler * 0.00488 'Spannung ausrechnen
Ah = Ah / 3.9 ' Strom Ausrechnen 3,9 Ohm
Ah = Ah / 3600 ' Ah Ausrechnen 1/sec = 3600
Locate 2 , 8
Lcd Fusing(ah , "##.###") ; "Ah"
End If

loop

Isr_von_timer1: 'ISR von Timer1
Timer1 = 61630 'Timer1 soll wieder von 61630 wegzählen
Toggle Portc.4 'schaltet Portd.0 im Sekundentakt 'EIN und AUS
Timer_flag = 1
Return