'******************************************************************************
'PWM Lueftersteuerung                                               17.07.2009
'Luefter_V3 - Erweiterungen: Matthias Foth
'
'Sollwert wird im EEPROM gespeichert
'
'Atmel Controller ATmega8
'AVCC Pin20 an +5V
'AREF Pin21 an +5V
'AGND Pin22 an GND
'
'Temperatur- Sensor LM35 an PC1
'Taster "Down" an PC5
'Taster "UP" an PC4
'LCD 16x2 an Port D
'LED grün an PD0
'LED rot an PD1
'IRF510 an PB1
'******************************************************************************

'$sim

$regfile = "m8def.dat"                                      ' ATMega8
$crystal = 8000000                                          ' 8 MHz intern
'$crystal = 1000000                                          ' 1 MHz intern

Const Const5 = 0.0048828125                                 ' 5V / 1024 (10-Bit-ADC)

Dim Adc1 As Word                                            ' Wert vom LM35
Dim Volt1 As Single                                         ' Volt vom LM35
Dim Templm35 As Single                                      ' Temperatur (celsius) von LM35
Dim Isttemp As Single                                       ' aktuelle Temperatur in Celsius
Dim Letzter_isttemp As Single                               ' Messwert davor
Dim Disp_volt1 As String * 10                               ' zur LCD-Anzeige
Dim Disp_templm35 As String * 10                            ' zur LCD-Anzeige

Dim Adc3 As Word                                            ' Wert vom ADC vom IRF510
Dim Volt3 As Single                                         ' Volt vom IRF510
Dim Strom As Single                                         ' Strom vom IRF510
Dim Disp_strom As String * 10                               ' zur LCD-Anzeige

Dim Solltemp As Single                                      ' Vorgabe der maximal zulässigen Temperatur
Dim Disp_solltemp As String * 10                            ' zur LCD-Anzeige

Dim I As Integer                                            ' Zähler / Schleife

Dim E_solltemp As Eram Single                               'EEPROM Variable
Dim Eramempty As Eram Byte                                  'Flag wenn EEPROM noch leer ist

Declare Sub Adc_in
Declare Sub Regeln
Declare Sub Anzeigen
Declare Sub Tasten

Config Lcdbus = 4
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2

Config Portb = Output
Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Down , Prescale = 1


Taste_up Alias Pinc.4
Taste_dn Alias Pinc.5
Dim Tasteup As Integer
Dim Tastedn As Integer

Config Pinc.0 = Input
Config Pinc.1 = Input
Config Pinc.2 = Input
Config Pinc.3 = Input
Config Pinc.4 = Input
Set Portc.4
Config Pinc.5 = Input
Set Portc.5


Config Adc = Single , Prescaler = Auto , Reference = Avcc
Set Sfior.adhsm                                             'ADC high speed mode ATmega8

Config Portd.0 = Output
Config Portd.1 = Output
Ledgruen Alias Portd.0
Ledrot Alias Portd.1

Deflcdchar 1 , 14 , 10 , 14 , 32 , 32 , 32 , 32 , 32        ' creating ° Symbol for Degree Centigrade
'Deflcdchar 1 , 24 , 24 , 3 , 4 , 4 , 4 , 4 , 3              'creating "°C" character (1)
'Deflcdchar 1 , 24 , 24 , 32 , 3 , 4 , 4 , 4 , 3             'creating "°C" character (1)
Deflcdchar 2 , 4 , 10 , 21 , 4 , 4 , 4 , 4 , 4              'creating "arrow top" char (2)
Deflcdchar 3 , 4 , 4 , 4 , 4 , 4 , 21 , 10 , 4              'creating "arrow down" char (3)
Cursor Off
Waitms 100

Dim Dynamikgrenze_oben As Single
Dim Dynamikgrenze_unten As Single

Dim Toleranzgrenze_oben As Single                           ' in den Toleranzgrenzem wired nicht geregelt
Dim Toleranzgrenze_unten As Single

Dim Pausenzeit As Single                                    ' Pause zwischen den Regelungen
Dim Pausenzeit_int As Integer
Dim Pausenzeit_max As Single                                ' max. zulässige Pausenzeit
Dim Pausenzeit_faktor As Single

Dim Schrittweite As Single                                  ' um diesen Betrag wird PWM korrigiert
Dim Schrittweite_int As Integer
Dim Schrittweite_faktor As Single

Dim Pwmwert As Integer                                      ' 10-Bit PWM (0...1023)

Dim Differenz As Single

Const Eramemptymask = 255                                   'If EEprom is empty it contains 255
Const Eramfilledmask = 170                                  'If EEprom is filled it contains 170

' ------------------------------------------------------------------------------
' ----------------------- Initialisierung der Variablen ------------------------
' ------------------------------------------------------------------------------

Pausenzeit = 25                                             ' zu Beginn mittlere Pausenzeit einstellen (2 Sek.)
Pausenzeit_faktor = 1                                       ' Multiplikator für die Bestimmung der Pausenzeit
Pausenzeit_max = 50                                         ' z.B. 50 * 1/10 Sek. = 5 Sekunden

Schrittweite = 50                                           ' Anfangswert
Schrittweite_int = 50                                       ' Anfangswert
Schrittweite_faktor = 10                                    '

'-------------------------------------------------------------------------------
' EEprom operations
'-------------------------------------------------------------------------------

   If Eramempty = Eramemptymask Then                        'Default settings
      E_solltemp = 30                                       'Solltemp im EEPROM speichern
      Eramempty = Eramfilledmask
   End If

   Solltemp = E_solltemp                                    'Daten aus EEPROM lesen
   Waitms 500                                               'warte 500ms

Disable Interrupts

' ------------------------------------------------------------------------------
' Beginn Programm
' ------------------------------------------------------------------------------

Set Ledgruen                                                ' grüne LED aus
Set Ledrot                                                  'rote LED aus

Call Adc_in                                                 'Analogwerte erstmals abfragen

Pwmwert = 500
Pwm1a = Pwmwert                                             ' Lüfter halbe Kraft voraus
Cursor Off
Cls
Locate 1 , 2
Lcd "Luefter PWM V3"
Wait 5
Cls

Do
  Set Ledgruen                                              'LED grün aus
  Call Adc_in
  Call Tasten
  Call Anzeigen
  Call Regeln
  Reset Ledgruen                                            'LED grün an
  Waitms 100
Loop

End                                                         'end program

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

Sub Adc_in                                                  ' ADC lesen

 Start Adc
 Letzter_isttemp = Isttemp                                  ' letzten Messwert merken

 Adc1 = Getadc(1)                                           ' LM35
 Adc3 = Getadc(3)                                           ' für Strom IRF510

 Volt1 = Adc1 * Const5                                      ' LM35
 Templm35 = Volt1 * 100                                     ' in Celsius umrechnen (10mV je Grad über Null)
 Isttemp = Templm35                                         ' aktuelle Temperatur am LM35

 Volt3 = Adc3 * Const5                                      ' Strom durch den IRF510 berechnen
 Strom = Volt3 / 1.2                                        ' I = U / R   R=1,2 Ohm
 Strom = Strom * 1000                                       ' Ampere in mA
 Stop Adc

End Sub


Sub Regeln

' Pausenzeit außerhalb Dynamikbereichs einstellen
  If Isttemp > Dynamikgrenze_oben Then
    Pausenzeit = 0                                          ' kürzest mögliche Pause
  End If                                                    ' dann schnell regeln

' Temperatur unterhalb Solltemperatur
  If Isttemp <= Solltemp Then                               ' Temp ist kälter als erlaubt
    Locate 1 , 9
    Lcd Chr(3)
    If Isttemp < Toleranzgrenze_unten Then                  ' unterhalb Toleranzgrenze ?
      Pwmwert = Pwmwert - Schrittweite_int                  ' versuchen, ob Lüfter leiser werden kann
      If Pwmwert < 0 Then
        Pwmwert = 0
      End If
    End If
    Pwm1a = Pwmwert
  End If                                                    ' endif isttemp < solltemp

' Bereich oberhalb Solltemperatur
  If Isttemp > Toleranzgrenze_oben Then                     ' Temp zu hoch, PWM-Wert steigern
     Locate 1 , 9
     Lcd Chr(2)
     ' Schrittweite berechnen, um die der PWM-Wert korrigiert wird
     Schrittweite = Isttemp - Solltemp
     Schrittweite = Schrittweite * Schrittweite_faktor
     Schrittweite_int = Round(schrittweite)
     If Schrittweite_int < 1 Then
       Schrittweite_int = 1
     End If

     If Isttemp > Letzter_isttemp Then
         Pwmwert = Pwmwert + Schrittweite_int
     End If

     If Isttemp < Letzter_isttemp Then
         Pwmwert = Pwmwert - Schrittweite_int
     End If

     If Isttemp = Letzter_isttemp Then
         Pwmwert = Pwmwert + 10
     End If

     If Pwmwert > 1023 Then
       Pwmwert = 1023
     End If

     If Pwmwert < 0 Then
       Pwmwert = 0
     End If

     Pwm1a = Pwmwert                                        ' PWM des Motors steuern

   If Isttemp < Dynamikgrenze_oben Then                     ' im Regelbereich, in dem die Pausenzeit angepasst wird
     Set Ledrot                                             ' rote LED aus
   ' Pausenzeit berechnen für (Toleranzgrenze oben < x < Dynamikgrenze oben)
     Differenz = Dynamikgrenze_oben - Isttemp
     Pausenzeit = Pausenzeit_max / Differenz
     Pausenzeit = Pausenzeit * Pausenzeit_faktor
     If Pausenzeit > Pausenzeit_max Then
        Pausenzeit = Pausenzeit_max
     End If
     ' nun steht in Pausenzeit die Pausenzeit 1/10 Sekunden
   End If
  End If                                                    ' if Toleranzgrenze_oben < Isttemp


   If Isttemp > Dynamikgrenze_oben Then                     ' Ist > als Dynamikgrenze oben, also SEHR hoch
       Reset Ledrot                                         ' warnen
       Pausenzeit = 0
   End If

  Pausenzeit_int = Round(pausenzeit)                        ' Pausenzeit (SINGLE) in INTEGER wandeln


  If Pausenzeit_int > 0 Then                                ' Pausenzeit vergehen lassen
    For I = 0 To Pausenzeit_int
      Waitms 100                                            ' Zeit verplempern  in Einheiten von 1/10 Sekunde
      Call Tasten
    Next I
  End If

End Sub


Sub Anzeigen

 Disp_templm35 = Fusing(templm35 , "##.#")
 Disp_strom = Fusing(strom , "###.#")
 Disp_solltemp = Fusing(solltemp , "###.#")

 Locate 1 , 1                                               ' LCD 2x16
 Lcd "I:" ; Disp_templm35 ;
 Lcd Chr(1) ; "C";
 Locate 1 , 10
 Lcd " S:" ; Disp_solltemp ; " "
 Locate 2 , 1
 Lcd Disp_strom ; "mA  "
 Locate 2 , 9
 Lcd "Pwm:" ; Pwmwert ; " "

End Sub



Sub Tasten

Tasteup = Taste_up
Tastedn = Taste_dn

If Tasteup = 0 Then
   Incr Solltemp
   E_solltemp = Solltemp
   Reset Ledrot
   Waitms 300
   Set Ledrot
End If

If Tastedn = 0 Then
   Decr Solltemp
   E_solltemp = Solltemp
   Reset Ledrot
   Waitms 300
   Set Ledrot
End If

If Solltemp < 1 Then
   Solltemp = 1
End If

If Solltemp > 99 Then
   Solltemp = 99
End If

Toleranzgrenze_oben = Solltemp + 1
Toleranzgrenze_unten = Solltemp - 1

Dynamikgrenze_oben = Toleranzgrenze_oben + 4
Dynamikgrenze_unten = Toleranzgrenze_unten - 4

End Sub