I made this device to measure the total daily charge of a portable solar panel with a 5V output via a USB-A socket. Each of several was tested for weeks. Another solar panel keeps the included battery charged.

After this use it is presently unused but could be used for another test, perhaps with a modified program.

Solar Current Meter Transmitter Picaxe Basic Program

Declarations and Data

#rem SolarCurrentMonitor.bas Transparent box with a 

DC-9S for the Universal Transmitter and programming

5.5 x 2.1 coax socket for an external shunt

The multipliers (11*61) + (30*59) + padding = reference diode in mv

LM385 measured at 2.482V

John Saunders 3/19/2021

#endrem


#picaxe 08M2

rem ports

symbol refPort  = 2    'Reference diode LM385 nominal 2.5V

symbol refDrive = 1    'LM385 only turned on during measurement

symbol currPort = 4    'Connects to external shunt resistor of 10 ohms


rem variables

symbol iter    = b1    'For FOR..NEXT loops

symbol indx    = b2    'To distinguish between current and battery voltage measurements

symbol digit   = b3

symbol ChckSum = b4

symbol ChckHex = b5


symbol fudge   = w8    'To compensate, on average for not measuring the fractionals

symbol vRef    = w9    'Measured only once a period since it is stable

symbol Vcc     = w10    'Accumulated to get required multil\plier

symbol curr    = w11    'Measured at 42 equal intervals per period for averaging and multiplication

symbol genVal  = w12

symbol remdr   = w13


rem constants

symbol VccPad   = 41

symbol currPad  = 9    'Modified value to compensate for 10 ohm shunt inaccuracy

symbol keyCode = "p"    'Logged as 

symbol interval = 56    'To get 90-second period

Init and  Main

init:

SETFREQ k125        'To reduce battery current drain to 200 microamps

LOW refDrive

LET Vcc = 0

LET curr = 0


main:

HIGH refDrive

PAUSE 1

READADC10 refPort,vRef

LOW refDrive

LET fudge = vRef / 2    'One-half

#rem The measurement is made in steps for these reasons:

1. The solar current changes frequently in cloudy days

2. Limited to 16-bit variables and no floating point

3. Generates a multiplication for the reference voltage

#endrem

rem Once a period calculation makes up tje sum and then transmits

LET genVal = 1024 * VccPad + fudge

LET Vcc = genVal/vRef + Vcc    'Final accumulation for battery voltage

READADC10 currPort,genVal    'Then for solar current

LET genVal = currPad * genVal + fudge

LET curr = genVal / vRef + curr

LET indx = 0    'Just a flag

GOSUB store

LET indx = 4

GOSUB store

GOSUB transmit

LET Vcc = 0

LET curr = 0

PAUSE interval

#rem The first of 2 multiplication steps.

The multipliers are chosen to be prime, 

 to be near to 63 (the limit) for 16 bits

 to be the same for both Vcc and current

 to be within 63 for both Vcc and current

#endrem

FOR iter = 1 TO 30

    READADC10 currPort,genVal

    LET genVal = 59 * genVal + fudge

    LET curr = genVal / vRef + curr 

    LET genVal = 59 * 1024 + fudge

    LET Vcc = genVal / vRef + Vcc

    PAUSE interval

NEXT

FOR iter = 1 TO 11

    READADC10 currPort,genVal

    LET genVal = 61 * genVal + fudge

    LET curr = genVal / vRef + curr 

    LET genVal = 61 * 1024 + fudge

    LET Vcc = genVal / vRef + Vcc

    PAUSE interval

NEXT

GOTO main

Sub-programs

store:    'Imaging the transmitter message in ram

IF indx = 0 THEN

    LET bptr = 28

    LET genVal = curr

ELSE

    LET bptr = 34

    LET genVal = Vcc

ENDIF

LET digit  = genVal/1000        'Digit #3

LET digit  = digit + "0"        'Ascii

LET @bptrinc = digit            

IF indx = 4 THEN

    LET @bptrinc = "."

ENDIF

LET remdr    = genVal//1000        'Remainder for digit #3

LET digit  = remdr/100            'Digit #2

LET digit  = digit + "0"        'Ascii

LET @bptrinc = digit            

LET genVal   = remdr//100        'Remainder for digit #2

LET digit  = genVal/10            'Digit #1

LET digit  = digit + "0"        'Ascii

LET @bptrinc = digit            

IF indx = 0 THEN

    LET @bptrinc = "."

ENDIF

LET digit  = genVal //10        'Least significant digit

LET digit  = digit + "0"        'Ascii

LET @bptrinc = digit             

LET @bptrinc = ","                

RETURN


transmit:

rem calculate the checksum and add to message

LET ChckSum = 0

FOR bptr = 28 TO 38

    LET ChckSum = ChckSum + @bptr 

NEXT


LET bptr = 39

LET @bptrinc = ","            '37

LET ChckHex = ChckSum / 16

IF ChckHex < 10 THEN

    LET ChckHex = ChckHex + "0"

ELSE

    LET ChckHex = ChckHex + "7"

ENDIF

LET @bptrinc = ChckHex            

LET ChckHex = ChckSum & $F

IF ChckHex < 10 THEN

    LET ChckHex = ChckHex + "0"

ELSE

    LET ChckHex = ChckHex + "7"

ENDIF

LET @bptr = ChckHex

SETFREQ m4

rem transmit by UHF radio with sync pulse, message type character (p) and message length code (G)

LET bptr = 28

HIGH C.0

PAUSE 20

LOW C.0

PAUSE 10

rem length char = ASCII of 60 + chars between and not including the bracketing end commas

rem                                              curr3  curr2    curr1    period   curr0  | comma  | Vcc3   | period |  Vcc2     Vcc1     Vcc0  | comma |     ChckSum     |

rem                                               28     29       30        31      32       33       34       35        36       37       38       39      40      41                   

SEROUT C.0, N2400_4,("14L1776",keyCode,",G,",@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, @bptrinc,@bptrinc,@bptr,     13,         10)

SETFREQ k125

RETURN