Bascom Atmega spinnt nach kurzer Zeit

tenor

Mitglied
30. Sep. 2012
169
0
16
44
Sprachen
  1. BascomAVR
Hallo,
ich habe mal wieder ein seltsames Problem mit meiner Steuerung..

Bin gerade dabei Funktionen zu schreiben und diese zu testen.
Beim ausgeben der Werte kommt es regelmäßig zu Problemen, sprich die Anzeige zeigt nur noch merkwürdige
Zeichen an. Hin und wieder bleibt der Controller auch komplett stehen und reagiert auf nichts mehr!

Erst hatte ich das Problem mit einer Funktion die mir permanent nur 0 zurück gab nur weil ich einen weiteren Wert übergeben hab.
Nach dem erhöhen des HWstacks konnte das Problem jedoch gelöst werden.

Aber ich denke das das aktuelle Problem evtl. da was mit zu tun hat.

Was sind den Höchstwerte für hwstack, swstack und framesize? Nutze den Atmega 644, im Datenblatt habe ich keine Antwort gefunden.
Hier der relevante Teil des Codes, das menü habe ich weggelassen, das Problem taucht ja auch so auf, ohne das man ins menü geht.

Die Funktion ist eigentlich so wie erwartet, es werden die korrekten Werte angezeigt, nur halt eben nur für ein paar Minuten..

Hat jemand Rat?


Code:
$regfile = "m644def.dat"
$crystal = 16000000
$lib "i2c_twi.lbx"
$framesize = 32                                             ' die Größe des Frames
$swstack = 32                                               ' die Größe des Software-stacks
$hwstack = 48                                               ' die Größe des Hardware-Stacks
Config Lcdpin = Pin , Db4 = Porta.2 , Db5 = Porta.3 , Db6 = Porta.4 , Db7 = Porta.5 , E = Porta.1 , Rs = Porta.0
Config Lcd = 20 * 4
Config 1wire = Pind.3
Config Timer1 = Timer , Prescale = 256                      'Timer1 für den Sekundentakt
On Timer1 Timer_irq
Initlcd                                                     'initalisieren und Pause damit das Zeichen in den Puffer des LCDs geschrieben werden kann
Waitms 100
Cls
Deflcdchar 1 , 8 , 20 , 8 , 32 , 32 , 32 , 32 , 32          'Grad Zeichen
Declare Sub Twi_send_byte(byval Slave As Byte , Zeichen As Byte)
Declare Function Decigrades(byval Sc(9) As Byte) As Integer
Declare Function Prescale(byval B_maxpwm As Byte , Byref B_zeiger As Byte) As Byte

Lcd_backlight Alias Pina.6                                  ' LCD - LED Hintergrundbeleuchtung
Dosierpumpe1 Alias Pina.7
Dosierpumpe2 Alias Pinc.7
Dosierpumpe3 Alias Pinc.6
Heizung Alias Pinc.4
Backlight Alias Pinc.3
Led_weiss Alias Pind.4
T_runter Alias Pinb.0
T_rechts Alias Pinb.1
T_hoch Alias Pinb.2
T_links Alias Pinb.3
T_menu Alias Pinb.4
T_wasserwechsel Alias Pind.0
T7 Alias Pind.1
T8 Alias Pind.2

Config Porta = Output                                       'LCD Display
Config Portc = Output
Config Portb = Input
Config T_wasserwechsel = Input
Config T7 = Input
Config T8 = Input
Config Led_weiss = Output
Config Pind.3 = Input                                       ' DS18B20
Config Pind.4 = Output                                      ' PWM Kanal LED Weiss
Config Pind.5 = Output                                      ' PWM Kanal LED Backlight
Config Clock = User
Config Date = Dmy , Separator = .                           ' Datumsformat DD.MM.YY

Const Timervorgabe = 3036
Const Ds1307w = &HD0                                        ' Addresse des DS1307 zum schreiben
Const Ds1307r = &HD1
Dim Menu As Byte
Dim Twi_control As Byte                                     ' Controlregister lokale kopie
Dim Twi_status As Byte
Dim Twi_data As Byte
Dim B As Byte                                               ' Zeichen von UART
Dim Error As Byte
Dim _wd As Byte                                             ' Wochentag
Dim _sec_bcd As Byte , _min_bcd As Byte , _hour_bcd As Byte , _day_bcd As Byte , _month_bcd As Byte , _year_bcd As Byte
Dim I As Integer , Sekunde As Integer
Dim Temperatur As String * 5
Dim Messen As Integer , Zeitabgleich As Integer
Dim W As Word
Dim Dg As Integer
Dim Dg1 As Byte
Dim Dsid1(8) As Byte                                        ' Adresses des DS18B20
Dim Sc(9) As Byte
Dim Zeit As String * 8
Dim Menuzeit As Integer , Hauptmenu As Integer , Beleuchtung As Integer , Dosierpumpen As Integer
Dim Monat As String * 2
Dim Stunde As String * 2
Dim Minute As String * 2
Dim Tag As String * 2
Dim Pwmstartstunde As Integer , Pwmstartminute As Integer , Pwmstopstunde As Integer , Pwmstopminute As Integer
Dim Pwm1(3) As Byte
Dim Pwm2(3) As Byte
Dim Pwm_wert(6) As Byte , Pwm_trigger(6) As Byte , Maxpwm(6) As Byte , Presc(6) As Byte
Dim Eedummy As Eram Byte                                    'erstes Byte im Eeprom leer lassen da evtl. Probleme beim Neustart
Dim Eetest As Eram Byte
Dim Teststring As String * 3
Dim Daysek As Dword , Daysek2 As Dword , Daysek3 As Dword
Dim Dauer(6) As Byte
Dim Zeiger As Byte
Dim Test1 As Byte , Test2 As Byte

Dsid1(1) = 40 : Dsid1(2) = 3 : Dsid1(3) = 213 : Dsid1(4) = 113 : Dsid1(5) = 4 : Dsid1(6) = 0 : Dsid1(7) = 0 : Dsid1(8) = 114       ' Addresse des DS18B20 zum lesen

'Twi Initialisieren
Twcr = &B00000100
Twsr = 0                                                    ' Status und Prescaler Register
Twbr = 72

Pwm1(1) = 10
Pwm1(2) = 10
Pwm1(3) = 10
Pwm2(1) = 10
Pwm2(2) = 10
Pwm2(3) = 10

Maxpwm(1) = 50
Maxpwm(2) = 75
Maxpwm(3) = 80
Maxpwm(4) = 20
Maxpwm(5) = 15
Maxpwm(6) = 40                                              'Prozentwert der gedimmt werden soll
Test1 = 1
Test2 = 2


'#########################################################################################
Initlcd                                                     'Display initialisieren
Cursor On
Cls
Enable Timer1                                               'Bildschirm löschen
Enable Interrupts

Lcd_backlight = 1                                           ' LCD Dauerhaft eingeschaltet für Testphase
'#########################################################################################
Gosub Getdatetime                                           ' Datum und Uhrzeit auslesen
' sind schon Daten im DS1307 vorhanden?
If _day = 1 And _month = 1 And _year = 0 Then               ' 01.01.00 = keine Daten
   I2cstart
   I2cwbyte Ds1307w
   I2cwbyte &H07
   I2cwbyte &B00000000
   I2cstop
   Date$ = "01.08.13"                                       ' Datum
   _wd = 6                                                  ' Wochentag
   Gosub Setdate                                            ' Datum schreiben
   Time$ = "10:30:00"                                       ' Uhrzeit
   Gosub Settime                                            ' Uhrzeit schreiben
End If
'Test = Eetest                                               ' Nach dem einschalten Eeprom Wert zurück kopieren
Main:
Cls
Menu = 0
Hauptmenu = 0
Menuzeit = 0
Beleuchtung = 0
Gosub Settime
Gosub Setdate
Daysek3 = _hour * 3600                                      ' Die Tagessekunde anhand der aktuellen Uhrzeit einstellen
Daysek2 = _min * 60
Daysek = Daysek2 + Daysek3
'Eetest = Test                   'Config Änderung im Menü im Eeprom speichern

For Zeiger = 1 To 6
   Presc(zeiger) = Prescale(maxpwm(zeiger) , Zeiger)
Next
Do
   Locate 4 , 5
   For Zeiger = 1 To 6
      Teststring = Str(presc(zeiger))
      Lcd Teststring
   Next
   Debounce T_menu , 0 , Menuconfig
   If Menu = 0 Then                                         'Wenn das Menu aktiv ist, reguläre Anzeige überspringen
      Select Case _wd
         Case 1
            Locate 2 , 11 : Lcd "Montag"
         Case 2
            Locate 2 , 11 : Lcd "Dienstag"
         Case 3
            Locate 2 , 11 : Lcd "Mittwoch"
         Case 4
            Locate 2 , 11 : Lcd "Donnerstag"
         Case 5
            Locate 2 , 11 : Lcd "Freitag"
         Case 6
            Locate 2 , 11 : Lcd "Samstag"
         Case 7
            Locate 2 , 11 : Lcd "Sonntag"
      End Select
      Locate 1 , 11
      Tag = Str(_day)                                       'Formatierung auf 2 Stellen
      Tag = Format(tag , "00")
      Monat = Str(_month)                                   'Formatierung auf 2 Stellen
      Monat = Format(monat , "00")
      Lcd Tag ; "." ; Monat ; ".20" ; _year
      Stunde = Str(_hour)
      Stunde = Format(stunde , "00")
      Minute = Str(_min)
      Minute = Format(minute , "00")
      Locate 1 , 1
      Lcd Stunde ; ":" ; Minute ; " Uhr"
      Locate 2 , 1
      Lcd Temperatur : Lcd "{001}C"                         'Einfügen des 'Sonderzeichen Grad {001}
      Debounce T_wasserwechsel , 0 , Pwm_senden , Sub
      Debounce T7 , 0 , Pwm_addieren , Sub
      Debounce T8 , 0 , Pwm_subtrahieren , Sub
      If Messen > 10 Then
         Gosub Gettemp                                      ' Temperatur auslesen
         Messen = 0
      End If
      If Zeitabgleich > 2 Then
         Gosub Getdatetime                                  ' Datum und Uhrzeit auslesen
         Zeitabgleich = 0
      End If
      Locate 3 , 1
      For I = 1 To 6
         Lcd Dauer(i)
         Lcd " "
      Next
   End If
Loop
Code:
Function Decigrades(byval Sc(9) As Byte)
   Decigrades = 0
   Decigrades = Makeint(sc(1) , Sc(2))
   Decigrades = Decigrades * 10
   Decigrades = Decigrades / 16
End Function

Gettemp:
      Disable Interrupts
      1wreset                                               ' reset the bus
      1wwrite &HCC                                          ' skip rom
      1wwrite &H44                                          ' Convert T
      Waitms 500
      1wverify Dsid1(1)                                     'Issues the "Match ROM "
      If Err = 1 Then
         Locate 3 , 1
         Lcd "Err "                                         'Err = 1 if something is wrong
      Elseif Err = 0 Then                                   'lcd " Sensor found"
         1wwrite &HBE
         Sc(1) = 1wread(9)                                  'read bytes into array
         Temperatur = Str(dg)
         Temperatur = Format(temperatur , " 0.0")
      End If
      If Sc(9) = Crc8(sc(1) , 8) Then
         Dg = Decigrades(sc(9))
      End If
      Enable Interrupts
Return

Function Prescale(b_maxpwm As Byte , B_zeiger As Byte)
   Local L_maxpwm As Single
   Local L_prozw1 As Single
   Local L_prozw2 As Single
   Local L_prescale As Single
   L_maxpwm = B_maxpwm
   L_prozw1 = L_maxpwm / 100
   L_prozw2 = 255 * L_prozw1
   L_prescale = 3600 / L_prozw2                             ' Auflösung des Dimm Vorgangs bestimmen 3600 = 1 Stunde zum Dimmen
   Prescale = L_prescale
   Pwm_trigger(b_zeiger) = Pwm_trigger(b_zeiger) + 1
   Pwm_wert(b_zeiger) = Pwm_trigger(b_zeiger)
End Function

Timer_irq:                                                  ' der Interrupt wird jede Sekunde ausgeführt
   Timer1 = Timervorgabe
    Sekunde = Sekunde + 1
   If Sekunde > 59 Then
      Sekunde = 0
   End If
   For Zeiger = 1 To 6
      If Dauer(zeiger) > Presc(zeiger) And Pwm_trigger(zeiger) < 255 Then
         Presc(zeiger) = Prescale(maxpwm(zeiger) , Zeiger)
         Dauer(zeiger) = 0
      End If
   Next
   For I = 1 To 6
      Dauer(i) = Dauer(i) + 1
   Next
   Messen = Messen + 1
   Zeitabgleich = Zeitabgleich + 1
   Daysek = Daysek + 1                                      ' Sekunden des gesamten Tages
   If Daysek > 86400 Then Daysek = 0                        ' 86400 = 1 Tag in Sekunden
Return
 
Hallo,

Was sind den Höchstwerte für hwstack, swstack und framesize? Nutze den Atmega 644, im Datenblatt habe ich keine Antwort gefunden.
Hier der relevante Teil des Codes, das menü habe ich weggelassen, das Problem taucht ja auch so auf, ohne das man ins menü geht.

Die Funktion ist eigentlich so wie erwartet, es werden die korrekten Werte angezeigt, nur halt eben nur für ein paar Minuten..

Hat jemand Rat?

zuerst mal einen wichtigen Rat ... bei solchen Fehlern (und eigentlich auch bei anderen) immer den gesamten Code einstellen. Es kann ja sein das irgendwo im Menü nen Return fehlt oder was weiß ich, wodurch ein Stacküberlauf/Unterlauf erzeugt wird. Außerdem kann man dann ohne großen Firlefanz deinen Code mal selber compilieren. So muß der Helfende wieder aus mehreren Teilen ein ganzes stricken und erstmal die Fehlermeldungen beim compilieren ausbügeln die durch die fehlenden Teile erzeugt werden weil irgendwas nicht gefunden wird. Das kostet Zeit (Freizeit der Helfenden) und Nerven. Wenn du Hilfe haben willst, dann solltest du es den Helfenden möglichst einfach machen dir zu helfen und nicht noch zusätzlichen Steine in den Weg legen.

Gruß
Dino
 
Hallo,
war nicht meine Absicht irgendjemanden Steine in den Weg zu legen!
Ich habe den Code extra so gemacht das nur der relevante Teil da ist.

Denn wie ich schon geschrieben habe, es funktioniert am anfang wie es soll (somit compiliert es auch richtig).

Hab die stacks auf 100 erhöht, scheint jetzt etwas besser zu laufen, muß das noch etwas länger laufen lassen.

Hier der gesamte Code:

edit:
Die Erhöhung des stacks hat nichts gebracht, das programm ist schon 2 mal wieder eingefroren, ohne das ich eine Taste
sprich Menü gedrückt habe.
 
Code:
$regfile = "m644def.dat"
$crystal = 16000000
$lib "i2c_twi.lbx"
$framesize = 100                                            ' die Größe des Frames
$swstack = 100                                              ' die Größe des Software-stacks
$hwstack = 100                                              ' die Größe des Hardware-Stacks
Config Lcdpin = Pin , Db4 = Porta.2 , Db5 = Porta.3 , Db6 = Porta.4 , Db7 = Porta.5 , E = Porta.1 , Rs = Porta.0
Config Lcd = 20 * 4
Config 1wire = Pind.3
Config Timer1 = Timer , Prescale = 256                      'Timer1 für den Sekundentakt
On Timer1 Timer_irq
Initlcd                                                     'initalisieren und Pause damit das Zeichen in den Puffer des LCDs geschrieben werden kann
Waitms 100
Cls
Deflcdchar 1 , 8 , 20 , 8 , 32 , 32 , 32 , 32 , 32          'Grad Zeichen
Declare Sub Twi_send_byte(byval Slave As Byte , Zeichen As Byte)
Declare Function Decigrades(byval Sc(9) As Byte) As Integer
Declare Function Prescale(byval B_maxpwm As Byte , Byref B_zeiger As Byte) As Byte

Lcd_backlight Alias Pina.6                                  ' LCD - LED Hintergrundbeleuchtung
Dosierpumpe1 Alias Pina.7
Dosierpumpe2 Alias Pinc.7
Dosierpumpe3 Alias Pinc.6
Heizung Alias Pinc.4
Backlight Alias Pinc.3
Led_weiss Alias Pind.4
T_runter Alias Pinb.0
T_rechts Alias Pinb.1
T_hoch Alias Pinb.2
T_links Alias Pinb.3
T_menu Alias Pinb.4
T_wasserwechsel Alias Pind.0
T7 Alias Pind.1
T8 Alias Pind.2

Config Porta = Output                                       'LCD Display
Config Portc = Output
Config Portb = Input
Config T_wasserwechsel = Input
Config T7 = Input
Config T8 = Input
Config Led_weiss = Output
Config Pind.3 = Input                                       ' DS18B20
Config Pind.4 = Output                                      ' PWM Kanal LED Weiss
Config Pind.5 = Output                                      ' PWM Kanal LED Backlight
Config Clock = User
Config Date = Dmy , Separator = .                           ' Datumsformat DD.MM.YY

Const Timervorgabe = 3036
Const Ds1307w = &HD0                                        ' Addresse des DS1307 zum schreiben
Const Ds1307r = &HD1
Dim Menu As Byte
Dim Twi_control As Byte                                     ' Controlregister lokale kopie
Dim Twi_status As Byte
Dim Twi_data As Byte
Dim B As Byte                                               ' Zeichen von UART
Dim Error As Byte
Dim _wd As Byte                                             ' Wochentag
Dim _sec_bcd As Byte , _min_bcd As Byte , _hour_bcd As Byte , _day_bcd As Byte , _month_bcd As Byte , _year_bcd As Byte
Dim I As Integer , Sekunde As Integer
Dim Temperatur As String * 5
Dim Messen As Integer , Zeitabgleich As Integer
Dim W As Word
Dim Dg As Integer
Dim Dg1 As Byte
Dim Dsid1(8) As Byte                                        ' Adresses des DS18B20
Dim Sc(9) As Byte
Dim Zeit As String * 8
Dim Menuzeit As Integer , Hauptmenu As Integer , Beleuchtung As Integer , Dosierpumpen As Integer
Dim Monat As String * 2
Dim Stunde As String * 2
Dim Minute As String * 2
Dim Tag As String * 2
Dim Pwmstartstunde As Integer , Pwmstartminute As Integer , Pwmstopstunde As Integer , Pwmstopminute As Integer
Dim Pwm1(3) As Byte
Dim Pwm2(3) As Byte
Dim Pwm_wert(6) As Byte , Pwm_trigger(6) As Byte , Maxpwm(6) As Byte , Presc(6) As Byte
Dim Eedummy As Eram Byte                                    'erstes Byte im Eeprom leer lassen da evtl. Probleme beim Neustart
Dim Eetest As Eram Byte
Dim Teststring As String * 3
Dim Daysek As Dword , Daysek2 As Dword , Daysek3 As Dword
Dim Dauer(6) As Byte
Dim Zeiger As Byte
Dim Test1 As Byte , Test2 As Byte

Dsid1(1) = 40 : Dsid1(2) = 3 : Dsid1(3) = 213 : Dsid1(4) = 113 : Dsid1(5) = 4 : Dsid1(6) = 0 : Dsid1(7) = 0 : Dsid1(8) = 114       ' Addresse des DS18B20 zum lesen

'Twi Initialisieren
Twcr = &B00000100
Twsr = 0                                                    ' Status und Prescaler Register
Twbr = 72

Pwm1(1) = 10
Pwm1(2) = 10
Pwm1(3) = 10
Pwm2(1) = 10
Pwm2(2) = 10
Pwm2(3) = 10

Maxpwm(1) = 50
Maxpwm(2) = 75
Maxpwm(3) = 80
Maxpwm(4) = 20
Maxpwm(5) = 15
Maxpwm(6) = 40                                              'Prozentwert der gedimmt werden soll
Test1 = 1
Test2 = 2


'#########################################################################################
Initlcd                                                     'Display initialisieren
Cursor On
Cls
Enable Timer1                                               'Bildschirm löschen
Enable Interrupts

Lcd_backlight = 1                                           ' LCD Dauerhaft eingeschaltet für Testphase
'#########################################################################################
Gosub Getdatetime                                           ' Datum und Uhrzeit auslesen
' sind schon Daten im DS1307 vorhanden?
If _day = 1 And _month = 1 And _year = 0 Then               ' 01.01.00 = keine Daten
   I2cstart
   I2cwbyte Ds1307w
   I2cwbyte &H07
   I2cwbyte &B00000000
   I2cstop
   Date$ = "01.08.13"                                       ' Datum
   _wd = 6                                                  ' Wochentag
   Gosub Setdate                                            ' Datum schreiben
   Time$ = "10:30:00"                                       ' Uhrzeit
   Gosub Settime                                            ' Uhrzeit schreiben
End If
'Test = Eetest                                               ' Nach dem einschalten Eeprom Wert zurück kopieren
Main:
Cls
Menu = 0
Hauptmenu = 0
Menuzeit = 0
Beleuchtung = 0
Gosub Settime
Gosub Setdate
Daysek3 = _hour * 3600                                      ' Die Tagessekunde anhand der aktuellen Uhrzeit einstellen
Daysek2 = _min * 60
Daysek = Daysek2 + Daysek3
'Eetest = Test                   'Config Änderung im Menü im Eeprom speichern

For Zeiger = 1 To 6
   Presc(zeiger) = Prescale(maxpwm(zeiger) , Zeiger)
Next
Do
   Locate 4 , 5
   For Zeiger = 1 To 6
      Teststring = Str(presc(zeiger))
      Lcd Teststring
   Next
   Debounce T_menu , 0 , Menuconfig
   If Menu = 0 Then                                         'Wenn das Menu aktiv ist, reguläre Anzeige überspringen
      Select Case _wd
         Case 1
            Locate 2 , 11 : Lcd "Montag"
         Case 2
            Locate 2 , 11 : Lcd "Dienstag"
         Case 3
            Locate 2 , 11 : Lcd "Mittwoch"
         Case 4
            Locate 2 , 11 : Lcd "Donnerstag"
         Case 5
            Locate 2 , 11 : Lcd "Freitag"
         Case 6
            Locate 2 , 11 : Lcd "Samstag"
         Case 7
            Locate 2 , 11 : Lcd "Sonntag"
      End Select
      Locate 1 , 11
      Tag = Str(_day)                                       'Formatierung auf 2 Stellen
      Tag = Format(tag , "00")
      Monat = Str(_month)                                   'Formatierung auf 2 Stellen
      Monat = Format(monat , "00")
      Lcd Tag ; "." ; Monat ; ".20" ; _year
      Stunde = Str(_hour)
      Stunde = Format(stunde , "00")
      Minute = Str(_min)
      Minute = Format(minute , "00")
      Locate 1 , 1
      Lcd Stunde ; ":" ; Minute ; " Uhr"
      Locate 2 , 1
      Lcd Temperatur : Lcd "{001}C"                         'Einfügen des 'Sonderzeichen Grad {001}
      Debounce T_wasserwechsel , 0 , Pwm_senden , Sub
      Debounce T7 , 0 , Pwm_addieren , Sub
      Debounce T8 , 0 , Pwm_subtrahieren , Sub
      If Messen > 10 Then
         Gosub Gettemp                                      ' Temperatur auslesen
         Messen = 0
      End If
      If Zeitabgleich > 2 Then
         Gosub Getdatetime                                  ' Datum und Uhrzeit auslesen
         Zeitabgleich = 0
      End If
      Locate 3 , 1
      For I = 1 To 6
         Lcd Dauer(i)
         Lcd " "
      Next
   End If
Loop
'#########################################################################################
Menuconfig:
Menuzeit = 0
Beleuchtung = 0
Dosierpumpen = 0
Menu = 1
Incr Hauptmenu
Cls
If Menuzeit = 0 Then
If Hauptmenu > 3 Then Hauptmenu = 1
   Do
      Debounce T_runter , 0 , Menuconfig
      Debounce T_menu , 0 , Main
      Select Case Hauptmenu
         Case 1 :
            Locate 1 , 1 : Lcd "Uhrzeit - Datum"
            Debounce T_rechts , 0 , L_menuzeit
         Case 2 :
            Locate 1 , 1
            Lcd "Beleuchtung"
            Debounce T_rechts , 0 , L_beleuchtung
         Case 3 :
            Locate 1 , 1
            Lcd "Dosierpumpen"
            Debounce T_rechts , 0 , L_dosierpumpen
      End Select
   Loop
End If
L_menuzeit:
Hauptmenu = 0
Incr Menuzeit
L_menuzeitconst:
Cls
Do
   Debounce T_menu , 0 , Main
   If Menuzeit > 6 Then Goto Menuconfig                     'Wenn alle Punkte durchlaufen wurden, zurück ins Hauptmenü
   Debounce T_rechts , 0 , L_menuzeit                       'Nächster Menüpunkt
   Debounce T_runter , 0 , Subtrahieren                     'Im aktuellen Menüpunkt subtrahieren
   Debounce T_hoch , 0 , Addieren                           'Im aktuellen Menüpunkt addieren
   Select Case Menuzeit
      Case 1 :
         Locate 1 , 1 : Lcd "Uhrzeit bearbeiten:"
         Locate 2 , 1 : Lcd "Stunde einstellen     "
         Locate 3 , 1 : Lcd _hour : Lcd ":" : Lcd _min : Lcd " " : Lcd "Uhr"
      Case 2 :
         Locate 1 , 1 : Lcd "Uhrzeit bearbeiten:"
         Locate 2 , 1 : Lcd "Minute stellen"
         Locate 3 , 1 : Lcd _hour : Lcd ":" : Lcd _min : Lcd " " : Lcd "Uhr"
      Case 3 :
         Locate 1 , 1 : Lcd "Datum bearbeiten"
         Locate 2 , 1 : Lcd "Tag stellen"
         Tag = Str(_day)                                    'Formatierung auf 2 Stellen
         Tag = Format(tag , "00")
         Locate 3 , 1 : Lcd Tag
      Case 4 :
         Locate 1 , 1 : Lcd "Datum bearbeiten"
         Locate 2 , 1 : Lcd "Monat stellen"
         Locate 3 , 1
         Select Case _month
            Case 1 : Lcd "Januar"
            Case 2 : Lcd "Februar"
            Case 3 : Lcd "Maerz"
            Case 4 : Lcd "April"
            Case 5 : Lcd "Mai"
            Case 6 : Lcd "Juni"
            Case 7 : Lcd "Juli"
            Case 8 : Lcd "August"
            Case 9 : Lcd "September"
            Case 10 : Lcd "Oktober"
            Case 11 : Lcd "November"
            Case 12 : Lcd "Dezember"
         End Select
      Case 5 :
         Locate 1 , 1 : Lcd "Datum bearbeiten"
         Locate 2 , 1 : Lcd "Jahr stellen"
         Locate 3 , 1 : Lcd "20" : Lcd _year
      Case 6 :
         Locate 1 , 1 : Lcd "Datum bearbeiten"
         Locate 2 , 1 : Lcd "Wochentag stellen"
         Select Case _wd
            Case 1:
               Locate 3 , 1 : Lcd "Montag"
            Case 2:
               Locate 3 , 1 : Lcd "Dienstag"
            Case 3:
               Locate 3 , 1 : Lcd "Mittwoch"
            Case 4:
               Locate 3 , 1 : Lcd "Donnerstag"
            Case 5:
               Locate 3 , 1 : Lcd "Freitag"
            Case 6:
               Locate 3 , 1 : Lcd "Samstag"
            Case 7:
               Locate 3 , 1 : Lcd "Sonntag"
         End Select
   End Select
Loop
L_beleuchtung:
Hauptmenu = 0
Incr Beleuchtung
L_beleuchtungconst:
Cls
Do
   If Beleuchtung > 5 Then Goto Menuconfig                  'Wenn alle Punkte durchlaufen wurden, zurück ins Hauptmenü
   Debounce T_menu , 0 , Main
   Debounce T_rechts , 0 , L_beleuchtung                    'Nächster Menüpunkt
   Debounce T_runter , 0 , Subtrahieren                     'Im aktuellen Menüpunkt subtrahieren
   Debounce T_hoch , 0 , Addieren                           'Im aktuellen Menüpunkt addieren
   Select Case Beleuchtung
      Case 1 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Stunde hochdimmen"
         Locate 3 , 1 : Lcd Pwmstartstunde
      Case 2 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Minute hochdimmen"
         Locate 3 , 1 : Lcd Pwmstartminute
      Case 3 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Stunde herabdimmen"
         Locate 3 , 1 : Lcd Pwmstopstunde
      Case 4 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Minute herabdimmen"
         Locate 3 , 1 : Lcd Pwmstopminute
      Case 5 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Mondlicht"
   End Select
Loop
L_dosierpumpen:
Hauptmenu = 0
Incr Dosierpumpen
Cls
Do
    If Dosierpumpen > 2 Then Goto Menuconfig
    Debounce T_menu , 0 , Main
    Debounce T_rechts , 0 , L_dosierpumpen                  'Nächster Menüpunkt
    Debounce T_runter , 0 , Subtrahieren                    'Im aktuellen Menüpunkt subtrahieren
    Debounce T_hoch , 0 , Addieren                          'Im aktuellen Menüpunkt addieren
    Select Case Dosierpumpen
      Case 1 :
         Locate 1 , 1 : Lcd "Dosierpumpe 1"
      Case 2 :
         Locate 1 , 1 : Lcd "Dosierpumpe 2"
    End Select
Loop
Goto Main                                                   'Für den Fall das eine Schleife nicht greift

Addieren:
If Menuzeit <> 0 Then
    Select Case Menuzeit
        Case 1 :
            _hour = _hour + 1 : If _hour > 23 Then _hour = 0
        Case 2 :
            _min = _min + 1 : If _min > 59 Then _min = 0
        Case 3 :
            _day = _day + 1 : If _day > 31 Then _day = 0
        Case 4 :
            _month = _month + 1 : If _month > 12 Then _month = 1
        Case 5 :
            _year = _year + 1 : If _year > 99 Then _year = 01
        Case 6 :
            _wd = _wd + 1 : If _wd > 7 Then _wd = 1
    End Select
 Goto L_menuzeitconst
End If
If Beleuchtung <> 0 Then
    Select Case Beleuchtung
        Case 1 :
            Pwmstartstunde = Pwmstartstunde + 1
            If Pwmstartstunde > 23 Then Pwmstartstunde = 0
        Case 2 :
            Pwmstartminute = Pwmstartminute + 1
            If Pwmstartminute > 59 Then Pwmstartminute = 0
        Case 3 :
            Pwmstopstunde = Pwmstopstunde + 1
            If Pwmstopstunde > 23 Then Pwmstopstunde = 0
        Case 4 :
            Pwmstopminute = Pwmstopminute + 1
            If Pwmstopminute > 59 Then Pwmstopminute = 0
    End Select
 Goto L_beleuchtungconst
End If
Goto Main                                                   'Für den Fall das eine Schleife nicht greift

Subtrahieren:
If Menuzeit <> 0 Then
   Select Case Menuzeit
      Case 1 :
         _hour = _hour - 1 : If _hour = -1 Then _hour = 23
      Case 2 :
         _min = _min - 1 : If _min = 255 Then _min = 59
      Case 3 :
         _day = _day - 1 : If _day = 255 Then _day = 31
      Case 4 :
         _month = _month - 1 : If _month = 255 Then _month = 12
      Case 5 :
         _year = _year - 1 : If _year = 255 Then _year = 99
      Case 6 :
         _wd = _wd - 1 : If _wd = 255 Then _wd = 7
   End Select
Goto L_menuzeitconst
End If
If Beleuchtung <> 0 Then
   Select Case Beleuchtung
      Case 1 :
         Pwmstartstunde = Pwmstartstunde - 1 : If Pwmstartstunde = -1 Then Pwmstartstunde = 23
      Case 2 :
         Pwmstartminute = Pwmstartminute - 1 : If Pwmstartminute = -1 Then Pwmstartminute = 59
      Case 3 :
         Pwmstopstunde = Pwmstopstunde - 1 : If Pwmstopstunde = -1 Then Pwmstopstunde = 23
      Case 4 :
         Pwmstopminute = Pwmstopminute - 1 : If Pwmstopminute = -1 Then Pwmstopminute = 59
   End Select
Goto L_beleuchtungconst
End If
Goto Main                                                   'Für den Fall das eine Schleife nicht greift

'#########################################################################################
' TWI send_byte
' sendet ein Byte und schliesst die Übertragung ab
Sub Twi_send_byte(byval Slave As Byte , Zeichen As Byte)
    Error = 0                                               ' Fehler zurücksetzen
    Twcr = &B10100100                                       ' Startbedingung - TWINT
    Gosub Twi_wait_int                                      ' warten bis TWINT gesetzt ist
    If Twi_status = &H08 Or Twi_status = &H10 Then          ' wenn Zugriff auf den Bus erlaubt, Slaveadresse ausgeben
        Twdr = Slave And &HFE                               ' slave adresse + Write
        Twcr = &B10000100                                   ' TWINT löschen, Byte senden
         Gosub Twi_wait_int                                 ' warten bis TWINT gesetzt ist
        If Twi_status = &H18 Or Twi_status = &H20 Then      ' Slave hat sich gemeldet
            Twdr = Zeichen                                  ' Daten
            Twcr = &B10000100                               ' TWINT löschen, Byte senden
            Gosub Twi_wait_int                              ' warten bis TWINT gesetzt ist
            If Twi_status = &H28 Or Twi_status = &H30 Then  ' Zeichen wurden gesendet
                Error = 0                                   ' kein Fehler
            Else
                Error = Twi_status                          ' Fehler
            End If
        Else                                                ' kein slave
            Error = Twi_status                              ' Fehler
        End If
        Twcr = &B10010100                                   ' TWINT löschen, STOP senden  nach einem STOP wird TWINT nicht mehr gesetzt, man darf/kann also nicht darauf warten !
    Else                                                    ' Bus belegt, wird er wieder freigegeben
        Twcr = &B10000100                                   ' TWINT löschen, Bus freigeben
        Error = Twi_status                                  ' Fehler
    End If
End Sub
'#########################################################################################
' warten bis TWINT gesetzt ist, status auslesen
Twi_wait_int:
    Do
        Twi_control = Twcr And &H80
    Loop Until Twi_control = &H80

    Twi_status = Twsr And &HF8                              ' status

Return
'#########################################################################################
                 ' RTC DS1307 Programmteile

' Datum und Uhrzeit auslesen
Getdatetime:
   ' Daten aus DS1307 abrufen
   I2cstart                                                 ' I2C Start
   I2cwbyte Ds1307w                                         ' Adresse zum schreiben senden
   I2cwbyte &H00                                            ' Registeradresse senden
   I2cstart                                                 ' erneuter I2C Start
   I2cwbyte Ds1307r                                         ' Adresse zum lesen senden
   I2crbyte _sec_bcd , Ack                                  ' Sekunden
   I2crbyte _min_bcd , Ack                                  ' Minuten
   I2crbyte _hour_bcd , Ack                                 ' Stunden
   I2crbyte _wd , Ack                                       ' Wochentag
   I2crbyte _day_bcd , Ack                                  ' Tag
   I2crbyte _month_bcd , Ack                                ' Monat
   I2crbyte _year_bcd , Nack                                ' Jahr
   I2cstop                                                  ' I2C Stop
   ' BCD-Zahlen in DEC-Zahlen konvertieren
   _sec = Makedec(_sec_bcd) : _min = Makedec(_min_bcd) : _hour = Makedec(_hour_bcd)
   _day = Makedec(_day_bcd) : _month = Makedec(_month_bcd) : _year = Makedec(_year_bcd)
Return
'#########################################################################################
' Datum schreiben
Setdate:
    ' DEC-Zahlen in BCD-Zahlen konvertieren
   _day_bcd = Makebcd(_day) : _month_bcd = Makebcd(_month) : _year_bcd = Makebcd(_year)
   ' Daten in DS1307 schreiben
   I2cstart                                                 ' I2C Start
   I2cwbyte Ds1307w                                         ' Adresse zum schreiben senden
   I2cwbyte 3                                               ' Registeradresse senden
   I2cwbyte _wd                                             ' Wochentag
   I2cwbyte _day_bcd                                        ' Tag
   I2cwbyte _month_bcd                                      ' Monat
   I2cwbyte _year_bcd                                       ' Jahr
   I2cstop                                                  ' I2C Stop
Return
'#########################################################################################
' Uhrzeit schreiben
Settime:
    ' DEC-Zahlen in BCD-Zahlen konvertieren
   _sec_bcd = Makebcd(_sec) : _min_bcd = Makebcd(_min) : _hour_bcd = Makebcd(_hour)
   ' Daten in DS1307 schreiben
   I2cstart                                                 ' I2C Start
   I2cwbyte Ds1307w                                         ' Adresse zum schreiben senden
   I2cwbyte &H00                                            ' Registeradresse senden
   I2cwbyte _sec_bcd                                        ' Sekunden
   I2cwbyte _min_bcd                                        ' Minuten
   I2cwbyte _hour_bcd                                       ' Stunden
   I2cstop                                                  ' I2C Stop
Return

'#########################################################################################
'Makes a integer value of the first two bytes in scratchpad'''''''''''''
'Works on DS18 B 20 , observe "B". The R0 and R1 in Sc(5) tells you how many bits are accurate
Function Decigrades(byval Sc(9) As Byte)
   Decigrades = 0
   Decigrades = Makeint(sc(1) , Sc(2))
   Decigrades = Decigrades * 10
   Decigrades = Decigrades / 16
End Function

Gettemp:
   Disable Interrupts
   1wreset                                               ' reset the bus
   1wwrite &HCC                                          ' skip rom
   1wwrite &H44                                          ' Convert T
   Waitms 500
   1wverify Dsid1(1)                                     'Issues the "Match ROM "
   If Err = 1 Then
      Locate 3 , 1
      Lcd "Err "                                         'Err = 1 if something is wrong
   Elseif Err = 0 Then                                   'lcd " Sensor found"
      1wwrite &HBE
      Sc(1) = 1wread(9)                                  'read bytes into array
      Temperatur = Str(dg)
      Temperatur = Format(temperatur , " 0.0")
   End If
   If Sc(9) = Crc8(sc(1) , 8) Then
      Dg = Decigrades(sc(9))
   End If
   Enable Interrupts
Return

Function Prescale(b_maxpwm As Byte , B_zeiger As Byte)
   Local L_maxpwm As Single
   Local L_prozw1 As Single
   Local L_prozw2 As Single
   Local L_prescale As Single
   L_maxpwm = B_maxpwm
   L_prozw1 = L_maxpwm / 100
   L_prozw2 = 255 * L_prozw1
   L_prescale = 3600 / L_prozw2                             ' Auflösung des Dimm Vorgangs bestimmen 3600 = 1 Stunde zum Dimmen
   Prescale = L_prescale
   Pwm_trigger(b_zeiger) = Pwm_trigger(b_zeiger) + 1
   Pwm_wert(b_zeiger) = Pwm_trigger(b_zeiger)
End Function

Timer_irq:                                                  ' der Interrupt wird jede Sekunde ausgeführt
   Timer1 = Timervorgabe
    Sekunde = Sekunde + 1
   If Sekunde > 59 Then
      Sekunde = 0
   End If
   For Zeiger = 1 To 6
      If Dauer(zeiger) > Presc(zeiger) And Pwm_trigger(zeiger) < 255 Then
         Presc(zeiger) = Prescale(maxpwm(zeiger) , Zeiger)
         Dauer(zeiger) = 0
      End If
   Next
   For I = 1 To 6
      Dauer(i) = Dauer(i) + 1
   Next
   Messen = Messen + 1
   Zeitabgleich = Zeitabgleich + 1
   Daysek = Daysek + 1                                      ' Sekunden des gesamten Tages
   If Daysek > 86400 Then Daysek = 0                        ' 86400 = 1 Tag in Sekunden
Return

Pwm_senden:
   Call Twi_send_byte(&H40 , Pwm1(1))                          ' Den Wert zum Slave senden
   Call Twi_send_byte(&H40 , Pwm1(2))
   Call Twi_send_byte(&H40 , Pwm1(3))
   Call Twi_send_byte(&H40 , Pwm2(1))
   Call Twi_send_byte(&H40 , Pwm2(2))
   Call Twi_send_byte(&H40 , Pwm2(3))
Return

Pwm_addieren:
   Pwm1(1) = Pwm1(1)
   Pwm1(2) = Pwm1(2)
   Pwm1(3) = Pwm1(3)
   Pwm2(1) = Pwm2(1) + 10                                      'blau
   Pwm2(2) = Pwm2(2) + 10                                      'rot
   Pwm2(3) = Pwm2(3) + 10                                      'grün
Return

Pwm_subtrahieren:
   Pwm1(1) = Pwm1(1)
   Pwm1(2) = Pwm1(2)
   Pwm1(3) = Pwm1(3)
   Pwm2(1) = Pwm2(1) - 10
   Pwm2(2) = Pwm2(2) - 10
   Pwm2(3) = Pwm2(3) - 10
Return
 
Hi,

war nicht meine Absicht irgendjemanden Steine in den Weg zu legen!
Ich habe den Code extra so gemacht das nur der relevante Teil da ist.
Denn wie ich schon geschrieben habe, es funktioniert am anfang wie es soll (somit compiliert es auch richtig).
Wenn dann aber im "relevanten Teil" Verweise/Sprünge/... auf die fehlenden Teile drin sind dann schmeißt einem der Compiler Fehler um die Ohren die nicht sein müßten wenn man alles reinstellt. Außerdem sind Stack-Fehler immer sehr schlecht zu finden und können an den unmöglichsten Stellen begründet sein.

Hab die stacks auf 100 erhöht, scheint jetzt etwas besser zu laufen, muß das noch etwas länger laufen lassen.
edit:
Die Erhöhung des stacks hat nichts gebracht, das programm ist schon 2 mal wieder eingefroren, ohne das ich eine Taste sprich Menü gedrückt habe.
Und schon gehts wieder weiter. Mit der Vergrößerung des Stacks hast du dein Problem nur verzögert. Irgendwo wird bei jedem Schleifendurchlauf etwas auf dem Stack zurückgelassen das sich auftürmt und dann einen Überlauf (Überschreiben des Variablenbereichs und anschließendem Überschreiben der Rücksrünge durch die Variablen) erzeugt. Wenn dauernd zuviel runtergenommen wird, dann geht das in der umgekehrten Richtung (Stack-Unterlauf).

Man müßte also für die Fehlersuche das gesamte Programm (das ja jetzt drinsteht) überprüfen ob nicht irgendwo Stackoperationen drin sind die nicht zusammen passen.

Gruß
Dino
 
Und schon gehts wieder weiter. Mit der Vergrößerung des Stacks hast du dein Problem nur verzögert. Irgendwo wird bei jedem Schleifendurchlauf etwas auf dem Stack zurückgelassen das sich auftürmt und dann einen Überlauf (Überschreiben des Variablenbereichs und anschließendem Überschreiben der Rücksrünge durch die Variablen) erzeugt. Wenn dauernd zuviel runtergenommen wird, dann geht das in der umgekehrten Richtung (Stack-Unterlauf).
Hallo Dino!
besten Dank erst einmal für den Hinweis.
Hatte eigentlich gedacht das wenn der stack zu klein ist, er gar nicht mehr den Platz hat um die ganzen Adressen zwischen zu speichern.
Hab gelesen, das er speziell bei interrupts viel Speicher braucht.
Mir ist nur nicht klar wie ich die Größe des Stacks bestimmten kann.

Dann werde ich das Programm nochmal Zeile für Zeile durchgehen um ein Fehler beim Rücksprung etc. zu finden.

Danke!
 
Hallo,

Code:
L_dosierpumpen:
Hauptmenu = 0
Incr Dosierpumpen
Cls
Do
... ... ... ...
Loop
[B]Goto Main[/B]                                                   'Für den Fall das eine Schleife nicht greift

Addieren:
If Menuzeit <> 0 Then
... ... ... ...
[B]Goto L_menuzeitconst[/B]
End If
If Beleuchtung <> 0 Then
... ... ... ...
[B]Goto L_beleuchtungconst[/B]
End If
[B]Goto Main[/B]                                                   'Für den Fall das eine Schleife nicht greift

Subtrahieren:
If Menuzeit <> 0 Then
... ... ... ...
[B]Goto L_menuzeitconst[/B]
End If
If Beleuchtung <> 0 Then
... ... ... ...
[B]Goto L_beleuchtungconst[/B]
End If
[B]Goto Main[/B]                                                   'Für den Fall das eine Schleife nicht greift

Ich tippe mal das dein Problem an diesen Stellen begraben ist. Mit Debounce wird eine Unterroutine angesprungen und die Rückspungadresse auf dem Stack abgelegt. Mit deinem GOTO springst du aber einfach so zurück ohne die Adresse wieder vom Stack runterzuholen. Da würde ich an deiner Stelle mal weitersuchen. Außerdem springst du mit deinem GOTO MAIN immer vor die DO-LOOP der Hauptroutine die du eigentlich dur die Suproutinenaufrufe von innen verläßt. Das Programm benötigt nach meiner Meinung ein wenig "saubere Programmierung" durch die dann sauber zu den Sprungpunkten zurückgekehrt wird. GOTO ist absolut kontraproduktiv und sollte nur in absoluten Notfällen verwendet werden. Es erschwert die Fehlersuche und bringt einem Stacküberläufe ein wenn man nicht aufpaßt.

Das war so der erste Eindruck beim kurzen rübersehen.

Gruß
Dino
 
Hallo Tenor!

Grundsätzlich ist der Gedanke mit den Stacks und dem Frame nicht verkehrt.
Allerdings ist dein Programm ja nun nicht besonders groß und soviele Variablen hast du auch nicht.

Wenn ich dein Programm mal kompiliere, um nach möglichen Fehlern ausschau zu halten, bekomme ich folgende Warnungen.
Source string could be too big to fit into target string [TAG>___STRBUF] in line 178
Source string could be too big to fit into target string [MONAT>___STRBUF] in line 180
Source string could be too big to fit into target string [STUNDE>___STRBUF] in line 183
Source string could be too big to fit into target string [MINUTE>___STRBUF] in line 185
Source string could be too big to fit into target string [TAG>___STRBUF] in line 260
Source string could be too big to fit into target string [TEMPERATUR>___STRBUF] in line 543


Das sind immer die Formatierungen vom Byte zum String.

Du hast jetzt zum Beispiel den "Tag" als "String * 2" dimensioniert.
Das ist ja theoretisch auch OK, weil du ggf. nur Tage von 0 bis 31 hast.

Damit müsste der zweistellige String ja auch auskommen. :wink:

Was ist aber, wenn es irgendwann mal einen "ungültigen" Wert im Programm gibt, wie z.B. 255 ?
Dann wird der Bytewert 255 plötzlich in einen dreistelligen String konvertiert und es überschreibt dir damit das erste Byte der nächsten definierten Variable.

Da dein zweistelliger String aus drei Byte besteht (das letzte Byte ist immer &H00 als String-Abschluss), wird genau das &H00 in das nächste Byte einer Variable "geschoben".


Ob das mit der Zeit einen Fehler produziert kann ich nicht sagen, aber du solltest die Punkte mit den Warnungen im Programm noch mal durchgehen!
Da dein AVR aber noch eine Menge Platz bietet, könntest du zum Test ja mal alle Stringvariablen auf die vollständige Anzahl Stellen des zugehörigen Byte oder Word oder was auch immer einstellen.


Grüße,
Cassio
 
Hallo Zusammen,
Danke für eure Mühen!

@ Dino,
ich habe mir deine Passagen angesehen, konnte aber keinen Fehler erkennen (Ausser einer redundanten Sprungmarke).
Den Debounce gibt es mit dem Schalter Sub, in dem Fall muss man mit return wieder zurück springen, ich nutze ihn an der stelle jedoch ohne,
somit als reinen GOTO Befehl. Ausserdem ist der Programmteil im Menü, das ich nicht aufrufen muß um den Fehler zu reproduzieren.

Mit der Übersichtlichkeit gebe ich dir Recht, bin mit der debounce Geschichte und dem Menü alles andere als zufrieden, aber für den Moment tut es was es soll.

@ Cassio,
an so was habe ich gar nicht gedacht!
Ich schau mir die Punkte gleich mal an und ändere die string Größen.

Das Programm an sich lief vorher stabil, der letzte Punkte den ich hinzugefügt habe, sind die For Next schleifen.
Die brauche ich für die 7 PWM Kanäle.
 
Hallo tenor,

also ich hab mal etwas weitergesucht ... ich kann dir nur empfehlen, deine Sprünge mal ganz stark zu überarbeiten. Du springst über Debounce (das ist wie Gosub mit Adresse auf Stack ablegen!) in eine Menüroutine und von dort teilweise wieder über Debounce zurück zur Main. Eigentlich wunder ich mich das es überhaupt so gut funktioniert. Einige Teile hab ich mal mit Bemerkungen versehen (mit ##### davor oder mit "Dino" drin). Die vordere Hälfte hab ich dann nicht mehr bearbeitet weil es in der aktuellen Version nichts bringen würde. Du mußt definitiv wesentlich mehr Struktur in deine Sprünge bringen. Du springst mit Debounce wild zwischen den Routinen hin und her und kehrst teilweise über Goto zurück. So wird das leider garnix. :(

Ups ... "Der Text, den Sie eingegeben haben, besteht aus 27282 Zeichen und ist damit zu lang. Bitte kürzen Sie den Text auf die maximale Länge von 25000 Zeichen."
Also kürzen ...

Code:
' ##### Alles vor dem Label "Main" abgeschnitten #####

[B][COLOR="#FF0000"]Main:[/COLOR][/B]
Cls
Menu = 0
Hauptmenu = 0
Menuzeit = 0
Beleuchtung = 0
Gosub Settime
Gosub Setdate
Daysek3 = _hour * 3600                                      ' Die Tagessekunde anhand der aktuellen Uhrzeit einstellen
Daysek2 = _min * 60
Daysek = Daysek2 + Daysek3
'Eetest = Test                   'Config Änderung im Menü im Eeprom speichern

For Zeiger = 1 To 6
   Presc(zeiger) = Prescale(maxpwm(zeiger) , Zeiger)
Next



Do
   Locate 4 , 5
   For Zeiger = 1 To 6
      Teststring = Str(presc(zeiger))
      Lcd Teststring
   Next
   Debounce T_menu , 0 , [B][COLOR="#FF0000"]Menuconfig[/COLOR][/B]
   If Menu = 0 Then                                         'Wenn das Menu aktiv ist, reguläre Anzeige überspringen
      Select Case _wd
         Case 1
            Locate 2 , 11 : Lcd "Montag"
         Case 2
            Locate 2 , 11 : Lcd "Dienstag"
         Case 3
            Locate 2 , 11 : Lcd "Mittwoch"
         Case 4
            Locate 2 , 11 : Lcd "Donnerstag"
         Case 5
            Locate 2 , 11 : Lcd "Freitag"
         Case 6
            Locate 2 , 11 : Lcd "Samstag"
         Case 7
            Locate 2 , 11 : Lcd "Sonntag"
      End Select
      Locate 1 , 11
      Tag = Str(_day)                                       'Formatierung auf 2 Stellen
      Tag = Format(tag , "00")
      Monat = Str(_month)                                   'Formatierung auf 2 Stellen
      Monat = Format(monat , "00")
      Lcd Tag ; "." ; Monat ; ".20" ; _year
      Stunde = Str(_hour)
      Stunde = Format(stunde , "00")
      Minute = Str(_min)
      Minute = Format(minute , "00")
      Locate 1 , 1
      Lcd Stunde ; ":" ; Minute ; " Uhr"
      Locate 2 , 1
      Lcd Temperatur : Lcd "{001}C"                         'Einfügen des 'Sonderzeichen Grad {001}
      Debounce T_wasserwechsel , 0 , [B][COLOR="#FF0000"]Pwm_senden , Sub[/COLOR][/B]
      Debounce T7 , 0 , [B][COLOR="#FF0000"]Pwm_addieren , Sub[/COLOR][/B]
      Debounce T8 , 0 , [B][COLOR="#FF0000"]Pwm_subtrahieren , Sub[/COLOR][/B]
      If Messen > 10 Then
         Gosub Gettemp                                      ' Temperatur auslesen
         Messen = 0
      End If
      If Zeitabgleich > 2 Then
         Gosub Getdatetime                                  ' Datum und Uhrzeit auslesen
         Zeitabgleich = 0
      End If
      Locate 3 , 1
      For I = 1 To 6
         Lcd Dauer(i)
         Lcd " "
      Next
   End If
Loop
'#########################################################################################




[B][COLOR="#FF0000"]Menuconfig:[/COLOR][/B]
Menuzeit = 0
Beleuchtung = 0
Dosierpumpen = 0
Menu = 1
Incr Hauptmenu
Cls
If Menuzeit = 0 Then
If Hauptmenu > 3 Then Hauptmenu = 1
   Do
      Debounce T_runter , 0 , [B][COLOR="#FF0000"]Menuconfig[/COLOR][/B]
      Debounce T_menu , 0 , [B][COLOR="#FF0000"]Main[/COLOR][/B]
      Select Case Hauptmenu
         Case 1 :
            Locate 1 , 1 : Lcd "Uhrzeit - Datum"
            Debounce T_rechts , 0 , [B][COLOR="#FF0000"]L_menuzeit[/COLOR][/B]
         Case 2 :
            Locate 1 , 1
            Lcd "Beleuchtung"
            Debounce T_rechts , 0 , [B][COLOR="#FF0000"]L_beleuchtung[/COLOR][/B]
         Case 3 :
            Locate 1 , 1
            Lcd "Dosierpumpen"
            Debounce T_rechts , 0 , [B][COLOR="#FF0000"]L_dosierpumpen[/COLOR][/B]
      End Select
   Loop
End If


[B][COLOR="#FF0000"]L_menuzeit:[/COLOR][/B]
Hauptmenu = 0
Incr Menuzeit


[B][COLOR="#FF0000"]L_menuzeitconst:[/COLOR][/B]
Cls
Do
   Debounce T_menu , 0 , [B][COLOR="#FF0000"]Main     ' ##### Rücksprung zur Hauptroutine [/COLOR][/B]
   If Menuzeit > 6 Then Goto Menuconfig                     'Wenn alle Punkte durchlaufen wurden, zurück ins Hauptmenü
   Debounce T_rechts , 0 , [B][COLOR="#FF0000"]L_menuzeit[/COLOR][/B]                       'Nächster Menüpunkt
   Debounce T_runter , 0 , [B][COLOR="#FF0000"]Subtrahieren[/COLOR][/B]                     'Im aktuellen Menüpunkt subtrahieren
   Debounce T_hoch , 0 , [B][COLOR="#FF0000"]Addieren[/COLOR][/B]                           'Im aktuellen Menüpunkt addieren
   Select Case Menuzeit
      Case 1 :
         Locate 1 , 1 : Lcd "Uhrzeit bearbeiten:"
         Locate 2 , 1 : Lcd "Stunde einstellen     "
         Locate 3 , 1 : Lcd _hour : Lcd ":" : Lcd _min : Lcd " " : Lcd "Uhr"
      Case 2 :
         Locate 1 , 1 : Lcd "Uhrzeit bearbeiten:"
         Locate 2 , 1 : Lcd "Minute stellen"
         Locate 3 , 1 : Lcd _hour : Lcd ":" : Lcd _min : Lcd " " : Lcd "Uhr"
      Case 3 :
         Locate 1 , 1 : Lcd "Datum bearbeiten"
         Locate 2 , 1 : Lcd "Tag stellen"
         Tag = Str(_day)                                    'Formatierung auf 2 Stellen
         Tag = Format(tag , "00")
         Locate 3 , 1 : Lcd Tag
      Case 4 :
         Locate 1 , 1 : Lcd "Datum bearbeiten"
         Locate 2 , 1 : Lcd "Monat stellen"
         Locate 3 , 1
         Select Case _month
            Case 1 : Lcd "Januar"
            Case 2 : Lcd "Februar"
            Case 3 : Lcd "Maerz"
            Case 4 : Lcd "April"
            Case 5 : Lcd "Mai"
            Case 6 : Lcd "Juni"
            Case 7 : Lcd "Juli"
            Case 8 : Lcd "August"
            Case 9 : Lcd "September"
            Case 10 : Lcd "Oktober"
            Case 11 : Lcd "November"
            Case 12 : Lcd "Dezember"
         End Select
      Case 5 :
         Locate 1 , 1 : Lcd "Datum bearbeiten"
         Locate 2 , 1 : Lcd "Jahr stellen"
         Locate 3 , 1 : Lcd "20" : Lcd _year
      Case 6 :
         Locate 1 , 1 : Lcd "Datum bearbeiten"
         Locate 2 , 1 : Lcd "Wochentag stellen"
         Select Case _wd
            Case 1:
               Locate 3 , 1 : Lcd "Montag"
            Case 2:
               Locate 3 , 1 : Lcd "Dienstag"
            Case 3:
               Locate 3 , 1 : Lcd "Mittwoch"
            Case 4:
               Locate 3 , 1 : Lcd "Donnerstag"
            Case 5:
               Locate 3 , 1 : Lcd "Freitag"
            Case 6:
               Locate 3 , 1 : Lcd "Samstag"
            Case 7:
               Locate 3 , 1 : Lcd "Sonntag"
         End Select
   End Select
Loop


[B][COLOR="#FF0000"]L_beleuchtung:[/COLOR][/B]
Hauptmenu = 0
Incr Beleuchtung


[B][COLOR="#FF0000"]L_beleuchtungconst:[/COLOR][/B]
Cls
Do
   If Beleuchtung > 5 Then Goto Menuconfig                  'Wenn alle Punkte durchlaufen wurden, zurück ins Hauptmenü
   Debounce T_menu , 0 , [B][COLOR="#FF0000"]Main                               ' ##### zurück zur Main[/COLOR][/B]
   Debounce T_rechts , 0 , [B][COLOR="#FF0000"]L_beleuchtung                    ' ##### Nächster Menüpunkt[/COLOR][/B]
   Debounce T_runter , 0 , [B][COLOR="#FF0000"]Subtrahieren                     ' ##### Im aktuellen Menüpunkt subtrahieren[/COLOR][/B]
   Debounce T_hoch , 0 , [B][COLOR="#FF0000"]Addieren                           ' ##### Im aktuellen Menüpunkt addieren[/COLOR][/B]
   Select Case Beleuchtung
      Case 1 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Stunde hochdimmen"
         Locate 3 , 1 : Lcd Pwmstartstunde
      Case 2 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Minute hochdimmen"
         Locate 3 , 1 : Lcd Pwmstartminute
      Case 3 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Stunde herabdimmen"
         Locate 3 , 1 : Lcd Pwmstopstunde
      Case 4 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Minute herabdimmen"
         Locate 3 , 1 : Lcd Pwmstopminute
      Case 5 :
         Locate 1 , 1 : Lcd "Beleuchtung"
         Locate 2 , 1 : Lcd "Mondlicht"
   End Select
Loop


[B][COLOR="#FF0000"]L_dosierpumpen:                                             ' ###### <== Einsprung über Debounce !!! (Dino)[/COLOR][/B]
Hauptmenu = 0
Incr Dosierpumpen
Cls
Do
    If Dosierpumpen > 2 Then [B][COLOR="#FF0000"]Goto Menuconfig[/COLOR][/B]
    Debounce T_menu , 0 , [B][COLOR="#FF0000"]Main[/COLOR][/B]
    Debounce T_rechts , 0 , [B][COLOR="#FF0000"]L_dosierpumpen                  'Nächster Menüpunkt[/COLOR][/B]
    Debounce T_runter , 0 , [B][COLOR="#FF0000"]Subtrahieren                    'Im aktuellen Menüpunkt subtrahieren[/COLOR][/B]
    Debounce T_hoch , 0 , [B][COLOR="#FF0000"]Addieren                          'Im aktuellen Menüpunkt addieren[/COLOR][/B]
    Select Case Dosierpumpen
      Case 1 :
         Locate 1 , 1 : Lcd "Dosierpumpe 1"
      Case 2 :
         Locate 1 , 1 : Lcd "Dosierpumpe 2"
    End Select
Loop
[B][COLOR="#FF0000"]Goto Main[/COLOR][/B]                                                   'Für den Fall das eine Schleife nicht greift
[B][COLOR="#FF0000"]' ###### ==> ??? Debounce=Gosub, dann kein Return ??? (Dino)[/COLOR][/B]


[B][COLOR="#FF0000"]Addieren:                                                   ' ###### <== Einsprung über Debounce !!! (Dino)[/COLOR][/B]
If Menuzeit <> 0 Then
    Select Case Menuzeit
        Case 1 :
            _hour = _hour + 1 : If _hour > 23 Then _hour = 0
        Case 2 :
            _min = _min + 1 : If _min > 59 Then _min = 0
        Case 3 :
            _day = _day + 1 : If _day > 31 Then _day = 0
        Case 4 :
            _month = _month + 1 : If _month > 12 Then _month = 1
        Case 5 :
            _year = _year + 1 : If _year > 99 Then _year = 01
        Case 6 :
            _wd = _wd + 1 : If _wd > 7 Then _wd = 1
    End Select
 [B][COLOR="#FF0000"]Goto L_menuzeitconst[/COLOR][/B]
End If
If Beleuchtung <> 0 Then
    Select Case Beleuchtung
        Case 1 :
            Pwmstartstunde = Pwmstartstunde + 1
            If Pwmstartstunde > 23 Then Pwmstartstunde = 0
        Case 2 :
            Pwmstartminute = Pwmstartminute + 1
            If Pwmstartminute > 59 Then Pwmstartminute = 0
        Case 3 :
            Pwmstopstunde = Pwmstopstunde + 1
            If Pwmstopstunde > 23 Then Pwmstopstunde = 0
        Case 4 :
            Pwmstopminute = Pwmstopminute + 1
            If Pwmstopminute > 59 Then Pwmstopminute = 0
    End Select
 [B][COLOR="#FF0000"]Goto L_beleuchtungconst ' ###### ==> ??? Debounce=Gosub, dann kein Return ??? (Dino)[/COLOR][/B]
End If
[B][COLOR="#FF0000"]Goto Main[/COLOR][/B]                                                   'Für den Fall das eine Schleife nicht greift
[B][COLOR="#FF0000"]' ###### ==> ??? Debounce=Gosub, dann kein Return ??? (Dino)[/COLOR][/B]


[B][COLOR="#FF0000"]Subtrahieren:                                               ' ###### <== Einsprung über Debounce !!! (Dino)[/COLOR][/B]
If Menuzeit <> 0 Then
   Select Case Menuzeit
      Case 1 :
         _hour = _hour - 1 : If _hour = -1 Then _hour = 23
      Case 2 :
         _min = _min - 1 : If _min = 255 Then _min = 59
      Case 3 :
         _day = _day - 1 : If _day = 255 Then _day = 31
      Case 4 :
         _month = _month - 1 : If _month = 255 Then _month = 12
      Case 5 :
         _year = _year - 1 : If _year = 255 Then _year = 99
      Case 6 :
         _wd = _wd - 1 : If _wd = 255 Then _wd = 7
   End Select
[B][COLOR="#FF0000"]Goto L_menuzeitconst                                        ' ###### ==> ??? Debounce=Gosub, dann kein Return ??? (Dino)[/COLOR][/B]
End If
If Beleuchtung <> 0 Then
   Select Case Beleuchtung
      Case 1 :
         Pwmstartstunde = Pwmstartstunde - 1 : If Pwmstartstunde = -1 Then Pwmstartstunde = 23
      Case 2 :
         Pwmstartminute = Pwmstartminute - 1 : If Pwmstartminute = -1 Then Pwmstartminute = 59
      Case 3 :
         Pwmstopstunde = Pwmstopstunde - 1 : If Pwmstopstunde = -1 Then Pwmstopstunde = 23
      Case 4 :
         Pwmstopminute = Pwmstopminute - 1 : If Pwmstopminute = -1 Then Pwmstopminute = 59
   End Select
[B]Goto L_beleuchtungconst[/B]
End If
[B][COLOR="#FF0000"]Goto Main[/COLOR][/B]                                                   'Für den Fall das eine Schleife nicht greift
[B][COLOR="#FF0000"]' ###### ==> ??? Debounce=Gosub, dann kein Return ??? (Dino)[/COLOR][/B]


'#########################################################################################
' TWI send_byte
' sendet ein Byte und schliesst die Übertragung ab
Sub Twi_send_byte(byval Slave As Byte , Zeichen As Byte)
    Error = 0                                               ' Fehler zurücksetzen
    Twcr = &B10100100                                       ' Startbedingung - TWINT
    Gosub Twi_wait_int                                      ' warten bis TWINT gesetzt ist
    If Twi_status = &H08 Or Twi_status = &H10 Then          ' wenn Zugriff auf den Bus erlaubt, Slaveadresse ausgeben
        Twdr = Slave And &HFE                               ' slave adresse + Write
        Twcr = &B10000100                                   ' TWINT löschen, Byte senden
         Gosub Twi_wait_int                                 ' warten bis TWINT gesetzt ist
        If Twi_status = &H18 Or Twi_status = &H20 Then      ' Slave hat sich gemeldet
            Twdr = Zeichen                                  ' Daten
            Twcr = &B10000100                               ' TWINT löschen, Byte senden
            Gosub Twi_wait_int                              ' warten bis TWINT gesetzt ist
            If Twi_status = &H28 Or Twi_status = &H30 Then  ' Zeichen wurden gesendet
                Error = 0                                   ' kein Fehler
            Else
                Error = Twi_status                          ' Fehler
            End If
        Else                                                ' kein slave
            Error = Twi_status                              ' Fehler
        End If
        Twcr = &B10010100                                   ' TWINT löschen, STOP senden  nach einem STOP wird TWINT nicht mehr gesetzt, man darf/kann also nicht darauf warten !
    Else                                                    ' Bus belegt, wird er wieder freigegeben
        Twcr = &B10000100                                   ' TWINT löschen, Bus freigeben
        Error = Twi_status                                  ' Fehler
    End If
End Sub                                                     ' ###### ==> OK (Dino)



'#########################################################################################
' warten bis TWINT gesetzt ist, status auslesen
Twi_wait_int:
    Do
        Twi_control = Twcr And &H80
    Loop Until Twi_control = &H80

    Twi_status = Twsr And &HF8                              ' status
Return                                                      ' ###### ==> OK (Dino)



'#########################################################################################
                 ' RTC DS1307 Programmteile
' Datum und Uhrzeit auslesen
Getdatetime:
   ' Daten aus DS1307 abrufen
   I2cstart                                                 ' I2C Start
   I2cwbyte Ds1307w                                         ' Adresse zum schreiben senden
   I2cwbyte &H00                                            ' Registeradresse senden
   I2cstart                                                 ' erneuter I2C Start
   I2cwbyte Ds1307r                                         ' Adresse zum lesen senden
   I2crbyte _sec_bcd , Ack                                  ' Sekunden
   I2crbyte _min_bcd , Ack                                  ' Minuten
   I2crbyte _hour_bcd , Ack                                 ' Stunden
   I2crbyte _wd , Ack                                       ' Wochentag
   I2crbyte _day_bcd , Ack                                  ' Tag
   I2crbyte _month_bcd , Ack                                ' Monat
   I2crbyte _year_bcd , Nack                                ' Jahr
   I2cstop                                                  ' I2C Stop
   ' BCD-Zahlen in DEC-Zahlen konvertieren
   _sec = Makedec(_sec_bcd) : _min = Makedec(_min_bcd) : _hour = Makedec(_hour_bcd)
   _day = Makedec(_day_bcd) : _month = Makedec(_month_bcd) : _year = Makedec(_year_bcd)
Return                                                      ' ###### ==> OK (Dino)



'#########################################################################################
' Datum schreiben
Setdate:
    ' DEC-Zahlen in BCD-Zahlen konvertieren
   _day_bcd = Makebcd(_day) : _month_bcd = Makebcd(_month) : _year_bcd = Makebcd(_year)
   ' Daten in DS1307 schreiben
   I2cstart                                                 ' I2C Start
   I2cwbyte Ds1307w                                         ' Adresse zum schreiben senden
   I2cwbyte 3                                               ' Registeradresse senden
   I2cwbyte _wd                                             ' Wochentag
   I2cwbyte _day_bcd                                        ' Tag
   I2cwbyte _month_bcd                                      ' Monat
   I2cwbyte _year_bcd                                       ' Jahr
   I2cstop                                                  ' I2C Stop
Return                                                      ' ###### ==> OK (Dino)



'#########################################################################################
' Uhrzeit schreiben
Settime:
    ' DEC-Zahlen in BCD-Zahlen konvertieren
   _sec_bcd = Makebcd(_sec) : _min_bcd = Makebcd(_min) : _hour_bcd = Makebcd(_hour)
   ' Daten in DS1307 schreiben
   I2cstart                                                 ' I2C Start
   I2cwbyte Ds1307w                                         ' Adresse zum schreiben senden
   I2cwbyte &H00                                            ' Registeradresse senden
   I2cwbyte _sec_bcd                                        ' Sekunden
   I2cwbyte _min_bcd                                        ' Minuten
   I2cwbyte _hour_bcd                                       ' Stunden
   I2cstop                                                  ' I2C Stop
Return                                                      ' ###### ==> OK (Dino)



'#########################################################################################
'Makes a integer value of the first two bytes in scratchpad'''''''''''''
'Works on DS18 B 20 , observe "B". The R0 and R1 in Sc(5) tells you how many bits are accurate
Function Decigrades(byval Sc(9) As Byte)
   Decigrades = 0
   Decigrades = Makeint(sc(1) , Sc(2))
   Decigrades = Decigrades * 10
   Decigrades = Decigrades / 16
End Function                                                ' ###### ==> OK (Dino)



Gettemp:
   Disable Interrupts
   1wreset                                               ' reset the bus
   1wwrite &HCC                                          ' skip rom
   1wwrite &H44                                          ' Convert T
   Waitms 500
   1wverify Dsid1(1)                                     'Issues the "Match ROM "
   If Err = 1 Then
      Locate 3 , 1
      Lcd "Err "                                         'Err = 1 if something is wrong
   Elseif Err = 0 Then                                   'lcd " Sensor found"
      1wwrite &HBE
      Sc(1) = 1wread(9)                                  'read bytes into array
      Temperatur = Str(dg)
      Temperatur = Format(temperatur , " 0.0")
   End If
   If Sc(9) = Crc8(sc(1) , 8) Then
      Dg = Decigrades(sc(9))
   End If
   Enable Interrupts
Return                                                      ' ###### ==> OK (Dino)



Function Prescale(b_maxpwm As Byte , B_zeiger As Byte)
   Local L_maxpwm As Single
   Local L_prozw1 As Single
   Local L_prozw2 As Single
   Local L_prescale As Single
   L_maxpwm = B_maxpwm
   L_prozw1 = L_maxpwm / 100
   L_prozw2 = 255 * L_prozw1
   L_prescale = 3600 / L_prozw2                             ' Auflösung des Dimm Vorgangs bestimmen 3600 = 1 Stunde zum Dimmen
   Prescale = L_prescale
   Pwm_trigger(b_zeiger) = Pwm_trigger(b_zeiger) + 1
   Pwm_wert(b_zeiger) = Pwm_trigger(b_zeiger)
End Function                                                ' ###### ==> OK (Dino)



Timer_irq:                                                  ' der Interrupt wird jede Sekunde ausgeführt
   Timer1 = Timervorgabe
    Sekunde = Sekunde + 1
   If Sekunde > 59 Then
      Sekunde = 0
   End If
   For Zeiger = 1 To 6
      If Dauer(zeiger) > Presc(zeiger) And Pwm_trigger(zeiger) < 255 Then
         Presc(zeiger) = Prescale(maxpwm(zeiger) , Zeiger)
         Dauer(zeiger) = 0
      End If
   Next
   For I = 1 To 6
      Dauer(i) = Dauer(i) + 1
   Next
   Messen = Messen + 1
   Zeitabgleich = Zeitabgleich + 1
   Daysek = Daysek + 1                                      ' Sekunden des gesamten Tages
   If Daysek > 86400 Then Daysek = 0                        ' 86400 = 1 Tag in Sekunden
Return                                                      ' ###### ==> OK (Dino)



Pwm_senden:
   Call Twi_send_byte(&H40 , Pwm1(1))                          ' Den Wert zum Slave senden
   Call Twi_send_byte(&H40 , Pwm1(2))
   Call Twi_send_byte(&H40 , Pwm1(3))
   Call Twi_send_byte(&H40 , Pwm2(1))
   Call Twi_send_byte(&H40 , Pwm2(2))
   Call Twi_send_byte(&H40 , Pwm2(3))
Return                                                      ' ###### ==> OK (Dino)



Pwm_addieren:
   Pwm1(1) = Pwm1(1)
   Pwm1(2) = Pwm1(2)
   Pwm1(3) = Pwm1(3)
   Pwm2(1) = Pwm2(1) + 10                                      'blau
   Pwm2(2) = Pwm2(2) + 10                                      'rot
   Pwm2(3) = Pwm2(3) + 10                                      'grün
Return                                                      ' ###### ==> OK (Dino)



Pwm_subtrahieren:
   Pwm1(1) = Pwm1(1)
   Pwm1(2) = Pwm1(2)
   Pwm1(3) = Pwm1(3)
   Pwm2(1) = Pwm2(1) - 10
   Pwm2(2) = Pwm2(2) - 10
   Pwm2(3) = Pwm2(3) - 10
Return                                                      ' ###### ==> OK (Dino)

Also wenn ich ehrlich bin. Bei dem wilden hin und hergespringe steigt kaum einer durch (ich jedenfalls nicht) :p

EDIT: Ich hab mal bei Debounce nachgelesen ...
When you specify the optional parameter SUB, a GOSUB to label is performed instead of a GOTO.
Naja ... OK ... dann sind es noch mehr Goto´s ... Irgendwo bei diesen Sprüngen liegt der Hase im Pfeffer.

Ich hab auch gesehen das du Functions verwendest. Die verbraten ne Menge FRAME-Platz. Es könnte also auch sein das dein Frame-Bereich (der glaube ich von unten wächst) in deinen Stack einwandert und die Rücksprungadressen zerballert. Wenn du ne Serielle Schnittstelle dran hast, dann gibt es bei Bascom glaube ich ein Stack-Debuging das dir den Stackinhalt auf der seriellen rausgibt. Wäre mal eine Gelegenheit das auszuprobieren.

EDIT2: Ups ... hat sich ja in der Zwischenzeit einiges getan.

Gruß
Dino
 
Ja, habe bislang keine alternative zu dieser Menüstruktur gefunden.
Debounce gibt es leider nicht ohne sprünge...

Wie gesagt, das Problem tritt auch auf, wenn ich nicht ins Menü gehe, denke also nicht das es in erster Linie damit zu tun hat.
Die Funktionen in den For Next Schleifen waren das letzte Thema.
 
Hi,

Ja, habe bislang keine alternative zu dieser Menüstruktur gefunden.
Debounce gibt es leider nicht ohne sprünge...

Wie gesagt, das Problem tritt auch auf, wenn ich nicht ins Menü gehe, denke also nicht das es in erster Linie damit zu tun hat.
Die Funktionen in den For Next Schleifen waren das letzte Thema.

Bascom-Referenz:
6.268 LOCAL
Action
Dimensions a variable LOCAL to the function or sub program.

A LOCAL variable is a temporary variable that is stored on the frame.
When the SUB or FUNCTION is terminated, the memory will be released back to the
frame.

versuch mal eine Verdoppelung deines Frame-Bereiches auf 200 Byte. Evtl liegt es an den ganzen lokalen Variablen. Oder du legst die als global an. Dann müssen die nicht dauernd erzeugt und wieder vernichtet werden.

Gruß
Dino
 
Habe jetzt alle Strings erhöht:
Dim Temperatur As String * 7
Dim Monat As String * 4
Dim Stunde As String * 4
Dim Minute As String * 4
Dim Tag As String * 4

und die Framesize auf 200 gestellt, noch läuft das Programm weiter, allerdings ist links neben der Uhr schon ein 5 zu sehen,
die da nichts zu suchen hat.

Werde mal Testweise die Temperatur rausnehmen, nicht das es da Probleme mit den Interrupts disablen gibt.
 
Leider ohne Erfolg!
Hab jetzt die LCD Schleife entfernt, aber so richtig ist das auch noch nicht das problem...
 
Hallo Tenor!

Ich komme gerade vom Schneeschieben wieder rein und habe deinen Code noch mal überflogen.....

Momentan "kämpfe" ich mit deiner Routine zur Temperaturberechnung.
Wie bist du auf diese Variante gekommen? :hmmmm:
Welchen Sensor hast du denn, den "S" oder den "B" ?

Was mich gerade stuzig macht.....
Du arbeitest eigentlich nur mit Integer-Variablen.
Trotzdem folgt ein "Temperatur = Str(dg)" und dann formatierst du "Temperatur" auch noch mit Kommastelle.
Wo soll die Kommastelle denn herkommen, wenn du nur Interger verwendest? :hmmmm:

Habe ich da auf die Schnelle vielleicht etwas übersehen?
Kannst du mir bei der Routine sonst mal helfen?


Grüße,
Cassio
 
Hi Cassio,
hab das Grundgerüst von Bascom genommen:
http://www.mcselec.com/index.php?option=com_content&task=view&id=75&Itemid=57
Mein alter Code von der S Variante hatte nicht mehr funktioniert,
jetzt ist der DS18B20 im Einsatz, da ich nur diesem in einem Wasserdichten Gehäuse fand.
Code:
'Makes a integer value of the first two bytes in scratchpad'''''''''''''
'Works on DS18 B 20 , observe "B". The R0 and R1 in Sc(5) tells you how many bits are accurate
function Decigrades(Byval Sc(9) as byte)
 Decigrades = 0
 Decigrades = Makeint(Sc(1) , Sc(2))
 Decigrades = Decigrades * 10
 Decigrades = Decigrades / 16
end function

In der Funktion Decigrades wird multipliziert und dividiert, daher macht ein Integer hier Sinn.

Die lokalen Variablen habe ich durch globale ersetzt der Fehler tritt immer noch auf.

Glaube schon fast das es mit der Uhr zu tun hat, da ich schon 3 mal bei einer Umstellung der Minute die gleich Zahl der Minute neben dem
Datum gesehen habe, also in der gleiche Sekunde wie die Minute umgestellt wurde.
 
...In der Funktion Decigrades wird multipliziert und dividiert, daher macht ein Integer hier Sinn...
Nein, das geht genauso wenig wie mit words. Der Knackpunkt ist, daß Du vorzeichenbehaftete Ganzzahlen erhälst - das sind Integer (bei Bascom als 16-bit-Integer).
Der Sensor liefert eigentlich Sechzehntel-Grad (Celsius). Durch die Multiplikation mit 10 werden die zu sechzehntel-dezigrad(Celsius). Durch die anschließende ganzzahlige Division (Integer, also mit abgehackten Nachkommastellen (oder rundet Bascom da?)) bleiben also Dezigrad-Celsius. Wenn man dann vor die letzte Stelle ein Komma schummelt (bei der Darstellung) stimmts wieder.
 
Hallo Tenor!

Ich habe mir das Datenblatt vom DS18B20 jetzt mal angesehen.....
und nebenbei deinen Programmcode. :wink:


Im Datenblatt steht, dass Byte0 und Byte1 des Scratchpad den konvertierten Temperaturwert beinhalten.
Byte0 ist dabei LSB und
Byte1 ist dabei MSB (siehe Datenblatt Seite 7).

LSB teilt sich jedoch in die Werte für VOR und NACH dem Komma (siehe Datenblatt Seite 4) !!


Die oberen Nibbels gehören zur Temperatur VOR dem Komma,
die unteren Nibbles ist die Kommastelle (0,5 / 0,25 / 0,125 / 0,0625).


Nun mal ein Beispiel aus dem Datenblatt Seite 4:
25,0625 °C = 0000_0001_1001_0001

Dabei sind:
0000_0001_1001_0001 = positive 25 °C
und:
0000_0001_1001_0001 = 1 * 0,0625 = 0,0625

25 + 0,0625 = 25,0625 °C



Schauen wir uns jetzt mal "deinen" Programmcode an:
Einmal oben....
Code:
Declare Function [B][COLOR="#FF0000"]Decigrades[/COLOR][/B](byval Sc(9) As Byte) [COLOR="#FF0000"][B]As Integer[/B][/COLOR]


....dann in der Funktion:
Code:
   Decigrades = 0
   Decigrades = Makeint(sc(1) , Sc(2))
   Decigrades = Decigrades * 10
   Decigrades = Decigrades / 16


Byte0 und Byte1 aus dem Scratchpad werden bei dir also in Sc(1) UND Sc(2) gespeichert.

Anschließend erfolgt die Rechnung:
Decigrades = (mache aus LSB und MSB eine 16bit Variable)
Nach dem obigen Beispiel würde dann also 0000_0001_1001_0001 (bzw. 401 Dezmimalwert) in der Variable stehen.

dann folgt:
Decigrades = 401 * 10
Nun würde 4010 in der Integervariable stehen und das ist auch OK.

dann folgt aber:
Decigrades = 4010 / 16
Genau hier liegt das Problem!
Jetzt müsstest du in einer Integer-Variable plötzlich: 250,625 stehen haben!


Ich frage mich nun die ganze Zeit.....
Was soll diese 250 und wie werden die 0,625 in der Integervariable wohl vermerkt! :hmmmm:


Verstehst du jetzt was ich meine? :wink:

Grüße,
Cassio
 
...
dann folgt:
Decigrades = 401 * 10
Nun würde 4010 in der Integervariable stehen und das ist auch OK.

dann folgt aber:
Decigrades = 4010 / 16
Genau hier liegt das Problem!
Jetzt müsstest du in einer Integer-Variable plötzlich: 250,625 stehen haben!
...
Nein, gerade weil das ein Integer ist (wäre bei word und byte ähnlich), ist das Ergebnis der Division (wie ich oben beschrieben hatte) 250. Die Nachkommastellen sind abgeschnitten. Und es ist in etwa (eben deswegen) das zehnfache des eigentlichen Ergebnisses (10fach da Multiplikation, in etwa da ganzzahlige Division). Es sind nahezu Dezigrad. Und wenn Du die irgendwie ausgeben willst, und vor die letzte Stelle ein Komma schummelst, hast Du mit 25,0 in etwa das richtige Ergebnis - liegst in diesem konkreten Beispiel also 0,0625 Kelvin daneben.
 
Hallo Lota...!

Danke schön, für den Hinweis..... :angry: :dirol: :hmpf:


Eigentlich wollte ich ja von Tenor wissen, wie das mit dem Integer gehen soll.


Gute Nacht,
Cassio
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)