' {$STAMP BS2} ' {$PBASIC 2.5} ' ' Title: Experiments with Solar Panels ' File: Parallax_Solar_Auto_Charger_Exp.bs2 ' Copyright: LearnOnLine, Inc. ' Author: J. Gavlik ' Last Updated: 08-15-2009 '------------------------------------------------------------------ ' Declarations '------------------------------------------------------------------ ' ' General VARs ' tempByte VAR Byte tempWord VAR Word i VAR Byte j VAR Byte voltage VAR Word oneOhmDrop VAR Word current VAR Word ckSum VAR Byte innerLoopSolar VAR Word innerLoopOneOhm VAR Word 'adjust the following two constants depending on your lighting conditions 'larger numbers provide more averaging - slower display speed 'smaller numbers provide less averaging - faster display speed innerLoopLimit CON 16 '1 is minimum - 16 is maximum outerLoopLimit CON 4 '1 is minimum - 16 is maximum 'average = innerLoopLimit x outerLoopLimit = 16 x 4 = 64 ' ' VARs for MCP3208 8 channel, 12 bit multiplexed A/D Converter ' a2dClk CON 0 'clock (P0) a2dDout CON 1 'data out (P1) a2dDin CON 2 'data in (P2) a2dCs CON 3 'chip select (P3) a2dId0 CON %1000 'A/D Channel 0 ID a2dId1 CON %1001 'A/D Channel 1 ID a2dId2 CON %1010 'A/D Channel 2 ID a2DId3 CON %1011 'A/D Channel 3 ID a2dId4 CON %1100 'A/D Channel 4 ID a2dId5 CON %1101 'A/D Channel 5 ID a2dId6 CON %1110 'A/D Channel 6 ID a2DId7 CON %1111 'A/D Channel 7 ID a2dIdShiftOut VAR Nib 'A/D Channel ID to shift out a2dResult VAR Word '16-bit result of A/D conversion ' ' On Demand VARs ' fullChargeVolts CON 1200 '1.20 volts (1200 millivolts) fullDischargeVolts CON 750 '0.75 volts (750 millivolts) Q1 CON 5 'HIGH when charging, LOW when not chargeLed CON 4 'HIGH when charging, LOW when not minEnergy CON 7350 '7350 milliamp minutes accumulated current measuredEnergy VAR Word 'accumulated current values every minute charging VAR Bit '0 = not charging, 1 = charging energyLoopCtr VAR Byte 'energy loop counter '------------------------------------------------------------------ ' On Demand Battery Charge Algorithm '------------------------------------------------------------------ ' ' Test_Battery_Voltage: 'stay in this loop as long as the battery is above min voltage ' Disable charging (Q1 = LOW) and extinguish LED ' Get voltage reading ' if voltage readng is >= fullChargeVolts, loop back ' else, goto Charge_Battery ' ' Charge_Battery: 'stay in this loop until a minimum charge is delivered into the battery ' Enable charging (Q1 = HIGH) and illuminate LED ' acquire a minimum battery charge ' when minimum battery charge is acquired, branch to Verify_Battery_Charged ' ' Verify_Battery_Charged: 'stay in this loop until the battery is at full voltage ' if voltage reading is >= fullChargeVolts, goto Test_Battery_Voltage ' else, loop back to Verify_Battery_Charged - charging is still taking place ' ' NOTE1: Current, power or resistance values are NOT displayed when the battery ' is NOT being charged. Only voltage is displayed. ' ' NOTE2: The displayed voltage output is NOT that of the solar panel. Rather it is that of the battery. ' Test_Battery_Voltage: LOW Q1 'disable charging LOW ChargeLed 'extinguish charging LED charging = 0 'disable current reading GOSUB Solar_Exp 'get averaged voltage and current IF (oneOhmDrop < fullDischargeVolts) THEN 'test battery voltage for below minimum measuredEnergy = 0 'if so, clear accumulated energy value GOTO Charge_Battery 'branch to begin charging ELSE GOTO Test_Battery_Voltage 'else, keep looping ENDIF Charge_Battery: HIGH Q1 'enable charging HIGH ChargeLed 'illuminate charging LED charging = 1 'enable current reading FOR energyLoopCtr = 1 TO 80 'loop for 1 minute and output data to PC GOSUB Solar_Exp 'get averaged voltage and current NEXT 'each gosub to Solar_Exp takes 0.75 sec x 80 = 60 seconds measuredEnergy = measuredEnergy + current 'add latest current reading to measuredEnergy var IF (measuredEnergy >= minEnergy) THEN 'test for accumulated ampMinutes GOTO Verify_Battery_Charged 'branch if minimum energy level is met ELSE GOTO Charge_Battery 'loop back ENDIF Verify_Battery_Charged: TOGGLE ChargeLed GOSUB Solar_Exp 'get averaged voltage and current IF (oneOhmDrop >= fullChargeVolts) THEN 'test against fully charged voltage GOTO Test_Battery_Voltage 'if there, then disable charging ELSE GOTO Verify_Battery_Charged 'else, maintain charging state ENDIF '------------------------------------------------------------------ ' Solar Experiment Algorithm '------------------------------------------------------------------ ' ' Sample the solar panel input voltage ' Sample the voltage across the 1 ohm sense resistor ' Repeat above xx times (innerLoopLimit x outerLoopLimit)to reduce voltage ripple from AC lights ' Convert the voltage counts to millivolts ' Test to see if the solar panel voltage > voltage drop across the 1 ohm resistor ' if so, continue ' if not,ignore readings and loop back to the top ' Convert the 1 ohm voltage drop to current in milliamps ' Transmit the voltage and current values to the computer ' Return ' '------------------------------------------------------------------ Solar_Exp: GOSUB Get_Average_Voltages 'acquire solar panel and voltage drop across 1 ohm sense resistor 'and take an average of 64 readings to smooth out ripple IF (charging = 0) THEN 'test for charging or not current = 0 'if not, set current = 0 and plot readings GOTO Solar_Exp_Plot_It ENDIF IF (voltage < oneOhmDrop) THEN 'test for catching voltage drop > input voltage GOTO Solar_Exp 'which can occur when voltage has ripples or changes fast ENDIF current = (voltage - oneOhmDrop) / 1 'compute the voltage drop across the 1 ohm sense resistor 'which is automatically now in milliamps by the following: ' ' I = E / R where ' I = current in milliamps ' E = voltage in millivolts Solar_Exp_Plot_It: ' R = resistance in ohms GOSUB Plot_It ' transmit the value to the computer RETURN '------------------------------------------------------------------ ' Get Average Voltages '------------------------------------------------------------------ Get_Average_Voltages: voltage = 0 'clear outer loop voltages oneOhmDrop = 0 FOR j = 1 TO outerLoopLimit innerLoopSolar = 0 'clear inner loop voltages innerLoopOneOhm = 0 FOR i = 1 TO innerLoopLimit a2dIdShiftOut = a2dId2 'set the a/d converter to ch2 (top of 1 ohm sense resistor) GOSUB A2D 'get A/D count innerLoopSolar = innerLoopSolar + a2dresult 'add result to average a2dIdShiftOut = a2dId5 'set the a/d converter to ch5 (bottom of 1 ohm sense resistor) GOSUB A2D 'get A/D count innerLoopOneOhm = innerLoopOneOhm + a2dresult 'add result to average NEXT voltage = voltage + (innerLoopSolar / innerLoopLimit) 'get average voltage count for inner loop oneOhmDrop = oneOhmDrop + (innerLoopOneOhm / innerLoopLimit) 'and add to outer loop counts NEXT voltage = voltage / outerLoopLimit 'get average voltage count for outer loop oneOhmDrop = oneOhmDrop / outerLoopLimit oneOhmDrop = oneOhmDrop */$0138 'convert to millivolts (1.22mv / count) voltage = voltage */$0138 'convert to millivolts (1.22mv / count) RETURN '------------------------------------------------------------------ ' Plot Acquired Data '------------------------------------------------------------------ Plot_It: ckSum = (oneOhmDrop.HIGHBYTE + oneOhmDrop.LOWBYTE + current.HIGHBYTE + current.LOWBYTE) 'compute checksum DEBUG oneOhmDrop.HIGHBYTE, oneOhmDrop.LOWBYTE, current.HIGHBYTE, current.LOWBYTE ,ckSum 'Transmit data to computer RETURN '------------------------------------------------------------------ ' A/D Converter Routine ' Enter with a2dIdShiftOut as the channel to convert ' Return with 12-bit result in a2dResult - right shifted '------------------------------------------------------------------ A2D: 'Initialize signals HIGH a2dCs 'Disable A/D chip select HIGH a2dDin 'Initial state of data in LOW a2dClk 'Initial state of clock a2dResult = 0 'Clear the 10-bit result A2D_Start_Conversion: 'Start the conversion process LOW a2dCs 'Enable A/D chip select A2D_Shift_Out_Channel_ID: 'Shift out the Channel ID value PULSOUT a2dClk,10 'Send first clock with Din high SHIFTOUT a2dDin,a2dClk,MSBFIRST,[a2dIdShiftOut\4] A2D_Shift_In_Result: 'Shift in the result PULSOUT a2dClk,10 'clock out null bit PULSOUT a2dClk,10 'clock out null bit SHIFTIN a2dDout,a2dClk,MSBPRE,[a2dResult\12] A2D_End_Conversion: HIGH a2dCs 'Disable A/D chip select RETURN '------------------------------------------------------------------ ' Program End '------------------------------------------------------------------ END