Wednesday, June 6, 2012

avr solar counter

To log the harvested energy from your solar cells, you need a counter device. Here is my low cost counter (10$) with AVR micro controller, LCD and SD card for small solar cells upto 25W.
This is an ongoing project. Therefore more features and improvements will follow.

Features (so far):
-current upto 2A
-display of actual current
-display of harvested mA hours since begin of logging
-easy firmware update of the device through com port 

features not implemented yet:
-logging of hourly harvested energy to SD card
-upload of SD card data through serial connection (com port)



Time is displayed in the upper left,  iv = instant value for current - here 12mA in the evening of a rainy day, second line shows the total harvested Energy in mAh.





Current from the solar cell to the rechargeable battery is measured over R2. Resistor 2 is about 0.1 Ohm which is suitable for measurements upto 2A. If you wish to measure currents over 2A a smaller Resistor is needed otherwise the resistor will get too hot and will waste your energy. Calculate the power wasted by the resistor by the formula:
P= I² *R  At 2 Amperes and 0.1Ohm  this gives 0.4 Watt over the resistor.
The LM358 (2 op amps in a 8 pin package) amplifies the voltage of R2 and feeds the ADC of Atmels Atmega8. Note that Atmega 48, 88, 168 are pin compatible replacements.
Compiled hex file and source code in bascom are on the bottom of this page.

UPDATE:
new feature: SD card logging

The eeprom logging feature will not been implemented as the memory capacity of the standard 2 wire eeproms 24Cxx is insufficient.
Therefore logging to SD card will be the only choice. SD cards give a virtually unlimited storage space for this purpose. Data can be written directly to sectors and read out via the serial connection of the logger.
Electrically the card should be connected as shown in the schematic. Pin 1 to 7 are connected. When soldering the wires directly to the card, take care not to connect pin 7 and 8.

SD cards are specified for a voltage upto 3.6V. MMC cards are pin compatible and might work from 1.8V to 3.6V.
Source code and more description will follow.













Source code versions

version 1
 basic version, no logging feature, time, instant current value and collected energy will be displayed on LCD until next reset of the logger


 *********************** start of version 1 *************************

   $regfile = "m8def.dat"
$crystal = 4096000
$hwstack = 100
$swstack = 100
$framesize = 100




'******************* LCD-  ************************

 Config Lcdpin = Pin , Db4 = Portd.6 , Db5 = Portd.7 , Db6 = Portb.0 , _
   Db7 = Portb.1 , E = Portd.4 , Rs = Portd.3
Config Lcd = 16 * 2
Cursor Off




Dim Displayflag As Bit                                      'update display 1s set flag in timer1 isr

Dim Adcflag As Bit                                          'adc flag will be set to 0 by timer 1s
Dim A As Byte                                               ' count variable for ADCmeasure

Dim Second As Byte
Dim Minute As Byte
Dim Hour As Byte
Dim Day As Byte
Dim Hourvalue As Word                                       'value per hour
Dim Instvalue As Word                                       ' value of adc measurement

Dim Sumvalue As Long                                        'sum of all adc measurements

Dim Totalseconds As Long                                    'seconds since start of measurement
Dim Totalcharge As Long                                     'totalcharge since beginning of measurement
  ' - - - - - - - - Timer1 - - - - - - - - - - - - - - - -
Config Timer1 = Timer , Prescale = 256                      'config Timer1
Enable Timer1                                               'turn on t1
On Timer1 Isr_von_timer1                                    'verzweige bei Timer1 überlauf zu   Isr_von_Timer1
Enable Interrupts
Timer1 = 49535                                              'timer value to get 1s-- 65535´-16000 = 49535
 Second = 0

  ' - - - - - - - - int0 - - - - - - - - - - set clock


 On Int0 Int0isr                                            'on interrupt0 goto  INT0ISR
 Config Int0 = Falling
  Enable Int0
 Enable Interrupts                                          'Interrupts enabled


Config Pind.2 = Input                                       'int0 pin

Portd.2 = 1                                                 'enable pullup for Interrupt0 pin



  '------------adc-----------------


  Config Adc = Single , Prescaler = Auto , Reference = Avcc ' AVCC = 3V - for SD card






'------------main-------------------
    Do

  '- lcd values 1x /s

  If Displayflag = 1 Then
Totalcharge = Sumvalue / 3600                               'total charge until now
Locate 1 , 1
 Cls
Lcd Hour ; "H" ; Minute ; " iv " ; Instvalue ; "mA"         'display 00H00_iv_xxxxmA  displays minute, hours, instant value,
 Locate 2 , 1

 Lcd Totalcharge ; "mAh Total"                              '1024_T2048mAh
                                                            'will be updated next second again, timer1 resets flag
  Displayflag = 0




  End If

  '- count minutes up

 If Second = 60 Then

 Second = 0
 Incr Minute


End If

  '-  count hours up and calculate values
If Minute = 60 Then
Incr Hour
Minute = 0



End If

 '-count days up

If Hour = 24 Then
Hour = 0
Incr Day
End If


 '- measure adc once per second
If Adcflag = 0 Then Gosub Adcmeasure













 Loop





   '----------timer1  -------------

 Isr_von_timer1:                                            '
Timer1 = 49535                                              'Timer1 counts from 34285 to get 1second
Adcflag = 0                                                 'to read ADC value in main programm after timer interrupt
Incr Second
Incr Totalseconds

Displayflag = 1                                             'update lcd once per second in main program
Return

  '----------set clock  -------------
Int0isr:                                                    'to set clock

Incr Minute

Return

 '----------measure current -----------------
 Adcmeasure:
  Instvalue = 0                                             ' reset instvalue for next getadc

   For A = 1 To 2
Instvalue = Instvalue + Getadc(0)                           ' instvalue = mA
     Next A
                                  'instvalue is reset to 0 in timer1 isr

  Sumvalue = Sumvalue + Instvalue                           'adc sum of seconds since start of device

   Adcflag = 1                                              ' prevent main programm to do measurement again in this second



  Return


*********************** end of version 1 *************************