'******************************************************************************
'                                                                             *
'    Filename: attiny861_volt.bas                                             *
'    Date: 20-11-2011                                                         *
'    Last update: 15-12-2011                                                  *
'    File Version: 0.3                                                        *
'    Memory usage: 31%                                                        *
'                                                                             *
'    Author: Roland van Leusden                                               *
'                                                                             *
'******************************************************************************


'********** Configuration Settings **********
$regfile = "attiny861.dat"                                  ' use ATTiny861
$crystal = 8000000

Config Pina.3 = Output                                      'Operates fet to switch between high & low current
Pina.3 = 1                                                  'Turn fet on, start with high current setting

Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.7 , Db5 = Portb.6 , Db6 = Portb.5 , Db7 = Portb.4 , E = Portb.3 , Rs = Portb.2
Deflcdchar [0] , 7 , 5 , 5 , 7 , 32 , 32 , 32 , 32          ' For temperature sign

Dim Voltage As Word
Dim Current As Word
Dim Temp_adc As Word
Dim Current_adc As Word
Dim Voltage_adc As Word
Dim Offset_adc As Word
Dim Offset As Byte

Dim Temperature As Word
Dim Power_out As Long
Dim Fan_on As Byte
Dim Current_range As Byte
Dim Temp As Byte

Dim Voltage_lcd As String * 5
Dim Current_lcd As String * 5
Dim Temp_lcd As String * 5
Dim Power_lcd As String * 5

'*********** Functions ***********************

Declare Sub Do_measurement()

Current_range = 1                                           'Start with high current range first, if needed switch to low

'*********** Main program ********************
Do
   Call Do_measurement()

'*********** Voltage ******************
   Voltage = Voltage * 47                                   'Max voltage = 1023 * 47 = 48081
   Shift Voltage , Right , 4                                'Voltage / 16 => max 3004
   Temp_lcd = Str(voltage)

   If Voltage >= 1000 Then
      Voltage_lcd = Format(temp_lcd , "00.00")
   Else
      Voltage_lcd = Format(temp_lcd , " 0.00")              'remove preceding zero
   End If

'*********** Current ******************


   If Current_range = 1 Then                                'High current  0.01 Ohm

      If Current < 2400 Then
         Current_range = 0                                  ' If current below 200 mA, next measurement low range
      End If

      Current = Current / 12

      If Current > 150 Then                                 'Error correction, see excel sheet for details
         Offset = Current / 140
         Current = Current - Offset
      End If

   End If

   If Current_range = 0 Then                                'Low current 0.22 Ohm

      If Current > 57600 Then
         Current_range = 1                                  'If current above 220 mA, next measurement high range
      End If

      Shift Current , Right , 6                             'Divide by 64

      Current = Current / 4

      If Current > 50 Then                                  'Error correction, see excel sheet for details
         Offset = Current / 40
         Current = Current - Offset
      End If

   End If


   'Remove own power consumption
   'Current = Current - 5


   Temp_lcd = Str(current)

   If Current >= 1000 Then
      Current_lcd = Format(temp_lcd , "0.00")               'Amps
   Else
      Current_lcd = Format(temp_lcd , "000")                'mA
   End If

'*********** Power ********************
   Power_out = Voltage * Current
   Power_out = Power_out / 1000
   Power_lcd = Str(power_out)

   If Power_out >= 1000 Then
      Power_lcd = Format(power_lcd , "00.00")
   Else
      Power_lcd = Format(power_lcd , "0.00")                'remove preceding zero
   End If

'*********** Temperature **************

'Vref 1.1V  LM35 => 10mV / Degree => max 110 degrees
   Temperature = Temperature * 10                           'max: 10230
   Temperature = Temperature / 93                           'max: 110

'*********** Display ******************
   Cls
   Upperline

   If Current >= 1000 Then
      Lcd Voltage_lcd ; "V " ; Current_lcd ; "A"
   Else
      Lcd Voltage_lcd ; "V " ; Current_lcd ; "mA"
   End If

   Lowerline

      Lcd "ADC: " ; Current_adc ; " Offset: " ; Offset_adc

   'Lcd Power_lcd ; "VA " ; Temperature ; Chr(0) ; "C"

'*********** Fan Controll **************

   'If Temperature >= 35 Then
'      Oc1a = 128
'      Fan_on = 1
'   End If

'   If Temperature <= 30 And Fan_on = 1 Then
'   Oc1a = 0
'   End If

Loop

End                                                         'end program

'*********** Functions ***********************
Sub Do_measurement()

Config Adc = Single , Prescaler = Auto , Reference = Internal_1.1
Start Adc


'now read the temperature sensor

Temperature = Getadc(4)                                     'LM35 10mV / degree


'*********** Voltage ************************************************************************
'now read A/D value from channel 3

Voltage = Getadc(3)

'The first conversion results after changing settings should be discarded.

Voltage = Getadc(3)

If Current_range = 1 Then
   '*********** Current High ********************************************************************
   ' Settings for full range: I = 5A Rshunt = 0.011 Ohm Gain = 20 => 5 * 0.011 * 20 = 1,1V (Vref)

   ' MUX5:0 Differential Input Positive    Negative   Gain
   ' 100000                    ADC0 (PA0)  ADC1 (PA1) 20x

   'measure offset ADC0

   Offset_adc = Getadc(&B111000)
   Offset_adc = Getadc(&B111000)

   'now read A/D value from channel 0,1

   Current = Getadc(&B100000)
   Current = 0

   For Temp = 1 To 59
      Temp_adc = Getadc(&B100000)
      Temp_adc = Temp_adc - Offset
      Current = Current + Temp_adc
   Next
Else
   '*********** Current Low *********************************************************************
   ' Settings for full range: I = 250mA Rshunt = 0.22 Ohm Gain = 20 => 0,25 * 0.22 * 20 = 1,1V (Vref)

   ' MUX5:0 Differential Input Positive    Negative   Gain
   ' 001110                    ADC2 (PA2)  ADC1 (PA1) 20x

   'measure offset ADC2

   Offset_adc = Getadc(&B111011)
   Offset_adc = Getadc(&B111011)

   'now read A/D value from channel 1,2

   Current = Getadc(&B001110)
   Current = 0

   For Temp = 1 To 64
      Temp_adc = Getadc(&B001110)
      Temp_adc = Temp_adc - Offset
      Current = Current + Temp_adc
   Next

End If

Stop Adc

End Sub