'*******************************************************************************
' Scooter Control V1.0
' A. Grah
' Stand 24.01.2006
'
' Zielhardware: ScooterControl V1.0
'
'*******************************************************************************

'*** Deklarationen *************************************************************
$regfile = "at26def.dat"                                    'Chipdefinition
$crystal = 8000000                                          'Int. Osc. Speed 1Mhz

'*** Portinitialisierung *******************************************************
Porta = &H00                                                'porta hochohmig schalten
Portb = &H00                                                'portb hochohmig schalten

Config Porta.0 = Input                                      'Spannungsmessung Batteriespannung Analog
Config Porta.1 = Input                                      'Spannungsmessung Sollwert (Poti) Analog
Config Porta.2 = Output                                     'nix
Config Porta.3 = Output                                     ' AREF !!
Config Porta.4 = Output                                     'Treiberstufenversorgung
Porta.4 = 0                                                 'Treiberstufe AUS
Config Porta.5 = Output                                     'LED rot
Config Porta.6 = Output                                     'LED gelb
Config Porta.7 = Output                                     'LED gruen

Config Portb.0 = Output                                     'ISP MOSI
Config Portb.1 = Output                                     'PWM SOLL OUT
Config Portb.2 = Output                                     'ISP SCK
Config Portb.3 = Output                                     'X6-6 (nix, DEBUG)
Config Portb.4 = Input                                      'Taste für Halbgas
Config Portb.5 = Input                                      'Taste für Volldampf
Config Portb.6 = Input                                      'Überstrom Eingang Interrupt 0 !
Config Portb.7 = Output                                     'X6-1, RESET PIN, nix

Portb.4 = 1                                                 'Pull up für Taster
Portb.5 = 1                                                 'Pull up für Taster
Portb.6 = 1                                                 'Pull up Stromeingang an

'*** ADC konfigurieren *********************************************************
Config Adc = Single , Prescaler = Auto                      ' reference 5V, single wegen getadc, auto macht höchste rate automatisch
Start Adc

'*** Variablen / Alias *********************************************************
Led_rot Alias Porta.5                                       'Benennung der LEDs
Led_gelb Alias Porta.6
Led_gruen Alias Porta.7

Volldampf Alias Pinb.5                                      'Taste volldampf gedrückt
Halbgas Alias Pinb.4                                        'taste halbgas gedrückt

Dim Batspannung As Word                                     '10 Bit Batteriespannung
Dim Potiwert As Word                                        '10 Bit Potiwert
Dim Batspannung8 As Byte                                    '8 Bit Batteriespannung
Dim Potiwert8 As Byte                                       '8 Bit Potiwert
Dim Istwert8 As Byte                                        'Istwert Rampenfunktion (Abweichung zu PWMspannung)
Dim Strompeak As Word                                       'Zähler für Überstromerkennung
Dim Timer1sek As Word                                       'Zähler für Sekundenanzeige
Dim Stromreset As Byte                                      'Zähler für Reset von Strompeak alle 3 sek
Dim Imax As Bit                                             'Merker für Überstrommodus
Dim Togglegruen As Bit                                      'Merker für blinkende LED
Dim Togglegelb As Bit
Dim Pwmzwischen As Word                                     'Zwischenberechnung
Dim Pwmspannung As Byte                                     'Berechnete PWM Spannung Lowbyte
Dim Pwmspannung16 As Word                                   'Berechnete PWM Spannung WORD
Dim Unterspannung1 As Bit                                   'Merker für kleine Unterspannung
Dim Unterspannung2 As Bit                                   'Merker für zu große Unterspannung
Dim Sollwert As Byte                                        'sollwert nach tasteneingabe
Dim Masteroverride As Bit                                   'Merker für Wiedereinschalten bei niedrigem Batteriestand
Dim Watchdogmerker As Bit

Watchdogmerker = 0
Masteroverride = 0
Sollwert = 0
Togglegruen = 0
Togglegelb = 0
Unterspannung1 = 0
Unterspannung2 = 0
Imax = 0
Stromreset = 0
Timer1sek = 0
Strompeak = 0
Istwert8 = 0

'*** Initialisierung / PWM / Timerinterrupt ************************************

Ocr1a = 0                                                   'PWM =0
Ocr1c = 255                                                 'PWM Phasenlänge
Set Tccr1a.com1a0                                           'OC1A auf compare match reset stellen (modus)
Set Tccr1a.pwm1a                                            'PWM1A enable / PWM einschalten
Set Tccr1b.ctc1                                             'clear timer on compare match with OCR1C (periodendauer)
Set Tccr1b.cs11                                             'Prescaler =CLK/2 (16000@8MHZ)

Enable Interrupts                                           'Globale Interrupts einschalten
Enable Int0                                                 'INT0 einschalten für Überstromerkennung
Config Int0 = Rising                                        'kommt bei steigender Flanke
On Int0 Strom_isr                                           'Interruptroutine aufrufen

Enable Timer1                                               'Interrupt Timer1 einschalten (alle 16kHz)
On Timer1 Hilfssekunde                                      'ISR aufrufen (bei jedem PWM Zyklus, Timer1 macht die PWM)

'Watchdog einrichten ***********************************************************
Config Watchdog = 2048                                      'Watchdog auf 2 sekunden stellen
Start Watchdog                                              'und starten

'Hauptschleife *****************************************************************
Do

If Watchdogmerker = 1 Then                                  'Wenn in der ISR der Merker gesetzt wurde, Watchdog resetten
   Reset Watchdog                                           'So ist sichergestellt, das Interrupt UND Mainprogramm laufen
   Watchdogmerker = 0
End If

Waitms 18                                                   'Rampengeschwindigkeit (siehe Rampenberechnung, INCR zähler)

'*** Einlesen der Analogwerte **************************************************
Batspannung = Getadc(0)                                     'Wert einlesen (10 Bit)
Potiwert = Getadc(1)
Shift Batspannung , Right , 2                               'Wandeln in 8Bit
Shift Potiwert , Right , 2
Batspannung8 = Low(batspannung)                             'lowbyte dem 8bit wert zuweisen
Potiwert8 = Low(potiwert)
'*******************************************************************************

'*** Tastenabfrage *************************************************************
If Volldampf = 1 And Halbgas = 1 Then                       'keine Taste gedrückt, Null PWM
   Sollwert = 0
End If
If Volldampf = 0 And Halbgas = 1 Then                       'nur vollgas gedrückt
   Sollwert = 253
End If
If Halbgas = 0 And Volldampf = 1 Then                       'nur halbgas gedrückt
   Sollwert = Potiwert8
End If
If Volldampf = 0 And Halbgas = 0 Then                       'beide tasten gedrückt (quittierung) Null PWM
   Sollwert = 0
End If
'*******************************************************************************

'*** Erkennung Betriebsspannung ************************************************
If Batspannung8 < 170 Then                                  '170 entspricht 21,8V
   Unterspannung1 = 1
Else
   Unterspannung1 = 0
End If

If Batspannung8 < 130 Then                                  'ca 16,5V
   Unterspannung2 = 1
   Unterspannung1 = 0
Else
   Unterspannung2 = 0
End If

'*******************************************************************************

'*** Einschalten des Treibers **************************************************
If Sollwert > 0 Then                                        'nur wenn pwm soll, geht die treiberstufe an
   Porta.4 = 1
Else
   Porta.4 = 0
End If
'*******************************************************************************

'*** Ausschalten Überstrom *****************************************************
If Sollwert = 0 Then                                        'wenn keine sollwert mehr, dann imax resetten
   Imax = 0
End If
'*******************************************************************************

'*** Berechnung PWM Wert *******************************************************
Pwmzwischen = Sollwert * 185
Pwmspannung16 = Pwmzwischen / Batspannung8
If Pwmspannung16 > 255 Then                                 'wenn berechnungsergebnis WORD > 255 dann 253...
   Pwmspannung16 = 253
End If
Pwmspannung = Low(pwmspannung16)
If Pwmspannung > 253 Then                                   'maximal pwm für flipflopreset
   Pwmspannung = 253
End If
'*******************************************************************************

'*** Rampenberechnung (Softstart) **********************************************
If Pwmspannung > Istwert8 Then                              'ansteigende rampe
   Incr Istwert8
End If
If Pwmspannung < Istwert8 Then                              'abfallende rampe
   Decr Istwert8
End If
'*******************************************************************************

'*** PWM Füttern ***************************************************************
If Imax = 0 Then                                            'nur wenn kein überstrom ist, pwm wert laden
   Ocr1a = Istwert8
Else
   Ocr1a = 0
End If
'*******************************************************************************

'*** Auswertung Überstrom ******************************************************
If Strompeak > 8000 Then                                    'wenn 8000mal der strompeak kam (halbe sekunde) gehe in überstrom !
   Imax = 1                                                 'überstrombit setzen
   Strompeak = 0                                            'stromzähler resetten
End If
'*******************************************************************************

'*** Anzeige *******************************************************************

If Unterspannung1 = 0 And Unterspannung2 = 0 Then           'alles ok gruene lampe an
   Led_gruen = 1
End If

If Unterspannung1 = 1 Then                                  'spannung unter 21,8V grünes blinken
   Togglegruen = 1
Else
   Togglegruen = 0
End If

If Unterspannung2 = 1 Then                                  'Spannung unter 16,5V gelbes blinken
   Led_gruen = 0
   Togglegelb = 1
   If Masteroverride = 0 Then                               'Verriegelung bei erstmaligem Unterschreiten der Unterspannung2
      Ocr1a = 0                                             'Motor abstellen
      Led_rot = 1                                           'Software wartet auf quittieren des Zustandes

      Do                                                    'durch drücken beider tasten
         If Watchdogmerker = 1 Then                         'erst dann wird der Motor wieder freigegeben
            Reset Watchdog
            Watchdogmerker = 0
         End If
         Waitms 500
         If Volldampf = 1 And Halbgas = 1 Then
            Goto Tasten_losgelassen
         End If
      Loop
      Tasten_losgelassen:

      Do
         If Watchdogmerker = 1 Then
            Reset Watchdog
            Watchdogmerker = 0
         End If
         Waitms 500
         If Volldampf = 0 And Halbgas = 0 Then
            Goto Override
         End If
      Loop
      Override:
      Led_rot = 0
      Masteroverride = 1
   End If
Else
   Led_gelb = 0
   Togglegelb = 0
End If

If Imax = 1 Then                                            'Überstromanzeige
   Led_rot = 1
Else
   Led_rot = 0
End If

Loop
End
'*******************************************************************************
'*******************************************************************************
'*******************************************************************************

'*** ISR`s *********************************************************************

Strom_isr:                                                  'Wenn Überstrom (INT0) war, wird hier ein Zähler inkrementiert
Incr Strompeak
Return

Hilfssekunde:
If Timer1sek >= 16200 Then                                  'Eine Sekunde um
   Timer1sek = 0
   '*** Platz für sekündliche Programmteile
   Watchdogmerker = 1                                       'setzen des interupt-watchdogmerkers

   If Togglegruen = 1 Then
      Toggle Led_gruen
   End If
   If Togglegelb = 1 Then
      Toggle Led_gelb
   End If

   If Stromreset >= 3 Then                                  'nach 3 sekunden
      Strompeak = 0                                         'Strompulscounter resetten
      Stromreset = 0                                        'stromreset resetten
   Else
      Incr Stromreset                                       'stromreset hochzählen
   End If
   '*** Ende sekündliche Aufrufe
Else
   Incr Timer1sek
End If
Return

'*******************************************************************************