Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 21:06 14 Nov 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Best way to measure solar input power?

Author Message
BrianP
Senior Member

Joined: 30/03/2017
Location: Australia
Posts: 292
Posted: 05:00am 07 Sep 2020
Copy link to clipboard 
Print this post

Hi team

I desire to use a 'Mite (which one yet to be decided) to measure & accumulate the daily solar output.

This is a 24volt system; over the last 7 years or so I have managed to accumulate 3 dissimilar solar panel banks & regulators, only 1 of which will store a daily total. All feed into the common 24 volt battery bank / inverter circuitry, hence the desire to combine them all into a daily totals record.

Using a shunt on the common negative (probably a short length of suitable cable as combined input on a good day can be 150 amps) my options would seem to be:

1. Use a single hall effect sensor (would likely still need a shunt because of the current)

2. Amplify the shunt voltage drop & measure on the 'Mite.

3. Use 3 hall effect sensors - 1 on each regulator - max. amps then would be 80.

On the 'Mite I would be measuring the input voltage & current to calculate the batteries input KWH & archiving over time. Not looking for maximum accuracy here.

If anyone has any thoughts / suggestions / ideas / musings / experiences to share they will be most welcome.

B
 
Chopperp

Guru

Joined: 03/01/2018
Location: Australia
Posts: 1106
Posted: 05:09am 07 Sep 2020
Copy link to clipboard 
Print this post

I assume you have checked out the SOLAR forum on TBS.

Lots of stuff to wade through there.

Brian
ChopperP
 
Gizmo

Admin Group

Joined: 05/06/2004
Location: Australia
Posts: 5160
Posted: 05:44am 07 Sep 2020
Copy link to clipboard 
Print this post

A negative rail shunt is the easiest solution. Or the Alegro shunt sensors, work great with microcontrollers, see https://www.thebackshed.com/windmill/articles/Alegro.asp.

Glenn
The best time to plant a tree was twenty years ago, the second best time is right now.
JAQ
 
BrianP
Senior Member

Joined: 30/03/2017
Location: Australia
Posts: 292
Posted: 01:06am 12 Sep 2020
Copy link to clipboard 
Print this post

Thanks Glenn / Brian

I'm thinking I might use 3 of these so each bank can be individually monitored & archived. Once you have a 'Mite involved the world is at your feet...

B
Edited 2020-09-12 11:07 by BrianP
 
MikeO
Senior Member

Joined: 11/09/2011
Location: Australia
Posts: 275
Posted: 10:28am 12 Sep 2020
Copy link to clipboard 
Print this post

Hi Brian, I have had a Garden Solar Battery system for several Years, using ACS714 type sensors, they just work. A Maximite (that's how long ago I first stated the system) controls the system. I used to use Xbee's to transmit the results but last year was converted to ESP8266 running ESPeasy sending to my wifi network and the Emoncms data base running on a RPI4.

I have attached the maximite code below , sorry there is an awfull lot of redundent code still in there from the previous Xbee's that were used but the acquisition code may be usefull. The lines like xbsend "TaskValueSet, 1,2," + str$(wpvAmps)" are the serial strings to the ESP8266 (ESPEasy).
The are some photos of the system on my web page including some live data feed.

Mike


'MMEDIT!!! Basic Version = Maximite_V4.5
'MMEDIT!!! Port = COM5:38400:30,150
'MMEDIT!!! Device = Maximite_V4.5
'MMEDIT!!! Config = 1001111011210001111010110100110
 ' *******************************
 ' ***** PV Solar System Monitor ) *****
 ' *******************************
   '    Filename:              pvmonxx.bas
 '    Date:
 '    Org File Version:   0.5
 '    Written by:     M.Ogden, www.Codenquilts.com.au
 '    Function:        PV Solar Monitor
 '    *******************************
 '09 now running ESP8266/espeasy
 
 ' Global Variables
 wBattAmps=0
 wBattWatts=0
 wPVAmps=0
 wPVWatts=0
 wPVvolts=0
 wBattVolts=0
 wTime = 0
 wTotalSecs=0
 WattHours = 0
 sample=0
 TotalCharge=0
 averageamps=0
 ampSeconds=0
 ampHours=0
 BackLight=24
 c$=","
 'cGreenLed=b.3
 'cPowerOn=b.7
 iNewdayFlag=0
 icheckTimeFlag=1                   'get time from network when set
 iXbeeFlag=0                        'clear Xbee data flag
 iXbeeAreaFlag=0                     'clear Xbee Area flag
 lastline$=""
 ibytecount=0
 inewline=0
 pvtest=0
 sVersion$="0.7"
 iRefOffset=0.01
 
 
 ''I/O pin configuration
 SetPin 1,1           ' Pin 1 - PV Voltage
 SetPin 2,1           ' Pin 2 - Battery Voltage
 SetPin 3,1           ' Pin 3 - Battery Load current
 SetPin 4,1           ' Pin 4 - PV supply Current
 SetPin 5,8           ' Pin 5 - Sample Led
 setpin 9,1            'Pin 9 - 5vdc supply
 'setpin 10,din
 'SETPIN 23,DOUT       ' Pin 23 - LCD Backlight
 
 'libraries
 'Library Load "shlbut00.lib"
 'Library Load "sernet04.lib"
 'Library Load "shlLcd00.lib"
 
 DIM MTH$(12) length 3 'Setup array for handling the months of the year
 MTH$(1)="JAN":MTH$(2)="FEB":MTH$(3)="MAR":MTH$(4)="APR":MTH$(5)="MAY":MTH$(6)="JUN"
 MTH$(7)="JUL":MTH$(8)="AUG":MTH$(9)="SEP":MTH$(10)="OCT":MTH$(11)="NOV":MTH$(12)="DEC"
 
 'Keyboard and Display Initialise
 'Lcd Init 25,26,27,28,29,30
 'LCDBacklight (1)
 'Lcd 2,1,"Initialising..."
 'Lcd 1,1, "mmDevice v" + sVersion$
 'Pause 5000
 'Lcd 2,1, "Running..           "
 'Lcd 3,1, "Line 3  "
 'Lcd 4,1, "Line 4              "
 
 'Init xb communications
 InitxbComm        'initialise comms
 iDeviceID=21    'Device ID
 xbWake         'Xbee wake
 Pin(5)=0              'Heartbeat led off
 
 'develop area
 
 'end develop area
 
 'Interrupts
 SetTick 1000, Heartbeat,1         'Heartbeart LED
 SetTick 60000, SendDataUpdate,2   ' Data update to network each minute
 
 
 'Program Start
 Randomize timer   'seed random number routine
 ' xbopenconsole
 logdata "Restart"
 sample
 SendDataUpdate
 'Main Program loop
 Do
   if iCheckTimeFlag=1 then ReqNetworkTime   'Periodic time Update from Server
   Sample        'Sample Voltage and currents sensors
   ' wait for the 10 second mark to come up
   pause 10000
 Loop
 
 
 'Typical use where Device reads some sensors
 ' Sample , reads sensors and updates stored variables for Voltage, current and power
sub Sample
 Pulse 5,5   'Pulse led
 wRefVdc=ReadVoltage(9,1,64)+ iRefOffset          'RefVdc as 5vdc/2
 'print wRefVDC
 ResetWatchDog    'Reset watchdog first
 wPVVolts = ReadVoltage(1,7.7,64)            'PV Voltage
 'wPVvolts=rand(22,0) 'test
 Print"PV Volts=",wPVVolts 'DEBUG
 
 wPVAmps=ReadCurrent(4,wRefVDC,0.04,64)        'PV current
 'wPVAmps=rand(6,1.34) 'test
 Print "PV Current=",wPVAmps 'DEBUG
 
 wBattVolts = ReadVoltage(2,7.7,64)            'Battery Voltage
 'wBattVolts=rand(15,10) 'test'test
 Print"Battery Volts=",wBattVolts 'DEBUG
 
 wBattAmps=ReadCurrent(3,wRefVDC,0.04,64)        'Battery Load current
 'wBattAmps=rand(10,0.34) 'test
 Print "Battery Current=",wBattAmps 'DEBUG
 
 wBattWatts=wBattAmps*wBattVolts  'Calc instantaneous watts
 wPVWatts=wPVAmps*wPVVolts  'Calc instantaneous watts
 
 'Calculate slice in Watthours for Battery Usage
 FractionalBattWattHours=wBattWatts*0.00138      'Watts/(5/3600)
 
 'Calculate slice in Watthours for PV Charge
 FractionalPVWattHours=wPVWatts*0.00138      'Watts/(5/3600)
 
 Print "FracBattWattHours=",FractionalBattwatthours 'DEBUG
 Print "FracPVWattHours=",FractionalPVWatthours 'DEBUG
 
 'Add wattHour slices to total Watt Hours
 BattWattHours = BattWattHours+FractionalBattWattHours
 PVWattHours = PVWattHours+FractionalPVWattHours
 Print "BattWattHours=",Battwatthours 'DEBUG
 Print "PVWattHours=",PVwatthours 'DEBUG
 print "" 'DEBUG
end sub
 
 
 'Typical use where on request a data update is sent to network
Sub SendDataUpdate
 
 'CallHome
 
 ' ***** Do other things here ******
'  wpvvolts=19.5
'  wpvamps=2.5
'  wBattvolts=13.8
'  wBattamps=1.5
'  Battwatthours=23
'  pvwatthours=67
 
 bhigh=Maxint(wpvvolts)
 blow=remainder(wpvvolts)
 'xbsend (iAreaTX,93,iDeviceID,bhigh,blow)
 xbsend "TaskValueSet, 1,1," + str$(wpvvolts)
 
 
 bhigh=Maxint(wpvAmps)
 blow=remainder(wpvAmps)
 'xbsend (iAreaTX,87,iDeviceID,bhigh,blow)
 xbsend "TaskValueSet, 1,2," + str$(wpvAmps)
 
 bhigh=Maxint(wBattVolts)
 blow=remainder(wBattVolts)
 'xbsend (iAreaTX,88,iDeviceID,bhigh,blow)
 xbsend "TaskValueSet, 1,3," + str$(wBattVolts)
 
 bhigh=Maxint(wBattAmps)
 blow=remainder(wBattAmps)
 'xbsend (iAreaTX,89,iDeviceID,bhigh,blow)
 xbsend "TaskValueSet, 1,4," + str$(wBattAmps)
 
 
 bSTR$=left$(wNumber$(wBattWatts),8)
 hhigh= BinToDec(bSTR$)
 bSTR$=right$(wNumber$(wBattWatts),8)
 blow= BinToDec(bSTR$)
 ' xbsend (iAreaTX,90,iDeviceID,bhigh,blow)
 
 
 bhigh=Maxint(Battwatthours)
 blow=remainder(Battwatthours)
 'xbsend (iAreaTX,91,iDeviceID,bhigh,blow)
 xbsend "TaskValueSet, 2,1," + str$(Battwatthours)
 
 bhigh=Maxint(PVwatthours)
 blow=remainder(PVwatthours)
 'xbsend (iAreaTX,92,iDeviceID,bhigh,blow)
 xbsend "TaskValueSet, 2,2," + str$(PVwatthours)
 
 Print time$;c$;wpvvolts;c$;wpvamps;c$;wbattvolts;c$;wbattamps;c$;wbattwatts;c$;battwatthours;c$;pvwatthours
 Logdata str$(wpvvolts)+c$+str$(wpvamps)+c$+str$(wbattvolts)+c$+str$(wbattamps)+c$+str$(wbattwatts)+c$+str$(battwatthours)+c$+str$(pvwatthours)
 
 
End Sub
 
 
 'UserProcess routine (programmed by User) is called by XBreceive routine when a complete data packet
 'is received , to check for commands.
Sub UserProcess 'User Subroutine to process incomming communications data
 'update
 'Data pkt  DeviceID:CommandID:High:Low
 ' Print "Process new Packet:" + newline$ 'DEBUG
 inewline=0                    'reset the flag
 ipktDeviceID=val(parse$(newline$,1))
 iCommandID=val(parse$(newline$,2))
 DataHi$=parse$(newline$,3)
 DataLo$=parse$(newline$,4)
 'print "User process data:"+ Str$(icommandID) + " " + Datahi$ + " " + datalo$ 'DEBUG
 if ipktDeviceID<>iDeviceID then exit sub   'reject not this device
 ' print "User process data for this device:"+ Str$(icommandID) + " " + Datahi$ + " " + datalo$ 'DEBUG
 If icommandID=17 Then             'process Time Sync request
   validatetime
   if validtime=0 then exit sub
   Time$=Datahi$ + ":" + datalo$ + ":00"
   ' Print "Corrected Time:" + Time$
   xbAck
   iCheckTimeFlag=0
 EndIf
 If icommandID=117 Then             'request Time Sync
   ReqNetworkTime             'request Time Sync
   xbAck
 EndIf
 If icommandID=199 Then             'Start open console mode
   xbAck
   xbOpenConsole
 EndIf
 If icommandID=20 Then             'Request data Update to Network
   xbAck
   SendDataUpdate
 EndIf
 'DisplaySysSettings
End Sub
 
 'general purpose routines
function wNumber$( sNumber)             'creates binary string of Whole Number
 local tNumber
 tNumber=cint(sNumber)                   'rounded Integer
 wNumber$= right$("0000000000000000" + bin$(tnumber),16)
 'print wnumber$
end function
 
Function DecToBin$(DecNum$)
 Local BinNum$
 Local lDecNum
 Local I
 I = 0
 lDecNum = Val(DecNum$)
 Do
   If lDecNum And 2 ^ I Then
     BinNum$= "1" + BinNum$
   Else
     BinNum$ = "0" + BinNum$
   EndIf
   I = I + 1
 Loop Until 2 ^ I > lDecNum
 DecToBin$ = BinNum$
End Function
 
Function BinToDec(BinNum$)
 local I , DecNum
 '  Loop thru BinString
 For I = Len(BinNum$) To 1 Step -1
   '     If bit is 1 then raise 2^LoopCount and add it to DecNum
   If val(Mid$(BinNum$, I, 1)) And 1 Then
     DecNum = DecNum + 2 ^ (Len(BinNum$) - I)
   EndIf
 Next I
 '  Return DecNum as a String
 BinToDec = DecNum
End Function
 
 
 
Function Rand(Low , High )
 Rand = ((High - Low + 1) * Rnd) + Low
End Function
 
function MaxInt(iNum)
 MaxInt=int(iNum)
 if MaxInt>255 then MaxInt=255
end function
 
sub ResetWatchDog
 setpin 10,dout
 pause 200
 setpin 10,din
end sub
 
sub LogData (msg$)
 LFILE$="B:\LOG\" + MID$(DATE$,1,2) + MTH$(VAL(MID$(DATE$,4,2))) + MID$(DATE$,9,2) + ".LOG"
 LDT$=DATE$ + "," + TIME$ + ">" + " " + msg$ + CHR$(13)
 OPEN LFILE$ FOR APPEND AS #3:FlagSD=1
 PRINT #3,LDT$:CLOSE #3:FlagSD=0
end sub
 
Sub LCDbackLight(N)
 pin(BackLight)=N
end sub
 
sub ValidateTime
 validtime=1
 if val(datahi$)<0 or val(datahi$)>23 then validtime=0
 if val(datalo$)<0 or val(datalo$)>59 then validtime=0
end sub
 
Function Parse$(s$,FieldNumber)
 Local stringArg$
 StringArg$ = S$ + ","
 intOldY = 1:intX=0:intY=0
 Parse$ = ""
 While intY < Len(StringArg$) And intX < FieldNumber
   intY = Instr(intOldY, StringArg$, ",")
   intX = intX + 1
   If intX = FieldNumber Then
     Parse$ = Mid$(StringArg$, intOldY, intY - intOldY)
   EndIf
   intOldY = intY + 1
 Wend
End Function
 
sub Heartbeat
 Pin(0) = 1
 Pause 100
 Pin(0) = 0   'Pulse Heartbeat led
 'Lcd 3,1, time$
 itime= 3600*(Val(Left$(Time$,2)))
 itime=itime + (60*(Val(Mid$(Time$,4,2)))) + Val(Right$(Time$,2))
 'Print itime
 If itime<=3 Then ' midnight so reset for new day
   Battwatthours=0:pvWattHours=0
   iCheckTimeFlag=1  'sync Clock
 EndIf
End Sub
 
Function Remainder (wNumber)
 wNumber=Abs(wNumber)  'return absolute number
 Remainder=Val(Mid$(Str$(wNumber-Fix(wNumber)),3,2))
 if remainder>255 then remainder=255
End Function
 'end General routines
 
 'sensor routines
Function ReadCurrent(InputPin,VoltageOffset,Cal,Smoothing)
 Local Count
 Local Voltage
 Local AccVoltage
 For Count = 1 To Smoothing    'take mulpiple reads
   Voltage=Pin(InputPin)
   AccVoltage = AccVoltage+Voltage
 Next Count
 ' print  ((AccVoltage/smoothing)-VoltageOffset)
 AccVoltage = ((AccVoltage/smoothing)-VoltageOffset)/cal '
 If AccVoltage<0 Then accvoltage=0   'trap negative numbers
 Readcurrent=AccVoltage
End Function
 
Function ReadVoltage(InputPin,Cal,Smoothing)
 Local Count
 Local Voltage
 Local AccVoltage
 For Count = 1 To Smoothing    'take mulpiple reads
   Voltage=Pin(InputPin)
   AccVoltage = AccVoltage+Voltage
 Next Count
 'print accVoltage/smoothing
 AccVoltage = (AccVoltage/smoothing)*cal '
 If AccVoltage<0 Then accvoltage=0
 ReadVoltage=AccVoltage  'trap negative numbers
End Function
 'end Sensor routines
 
''$INCLUDE: mmsernet.lib
 ' ***************************************************************
 ' ******************** Maximite Wireless  ***********************
 ' ***************************************************************
 '    Filename:              MMsernet.bas
 '    Date:          09/10/2011
 '    Org File Version:   1.01
 '    Written by:     M.Ogden, www.Codenquilts.com.au
 '    Function:              Xbee wireless communications for Maximite
 '                         using SerialNet protocol.
 '
 '                  SerialNet consists of a simple 6 byte
 '                  packet developed for use with Picaxe
 '                  Packet is Sync,Area,DestID,CallID,HiData,LoData
 '                  Area byte allows for transmission areas.
 '    Pin 6 is Xbee sleep, file#5 is used for handle
 '
 ' Revision:
 ' ***************************************************************
 '1.01 30/6/13 partially updated to user defined routines
 '1.02 added constants for sleep pin, added OpenConsole mode
 
 
 'Initialise routines
Sub initxbcomm
 iAreaTX=86:iArea=85:iDeviceID=21    'Transmision out of local Area, local area,  of Device and Device ID (set to suit)
 icheckTimeFlag=1                   'get time from network on start up
 iXbeeFlag=0                        'clear Xbee data flag
 iXbeeAreaFlag=0                     'clear Xbee Area flag
 lastline$=""
 ibytecount=0
 inewline=0
 iSleep=6  ' Sleep pin# , nb. set correct pin in Initialise routine "initxbcomm"
 SetPin 6,DOUT 'set digital output for Sleep pin connection
 Open "com1:19200,1024,xbreceive"  As #5 'initialise comms
End Sub
 
Sub xbwake
 Pin(iSleep)=0
End Sub          'xbee wake
 
Sub xbsleep
 Pin(iSleep)=1
End Sub    'Xbee sleep
 
Sub closexbComm
 Close #5
 'SetPin 23,0
End Sub   'close comms and xbee
 
Sub xbOpenConsole
 Closexbcomm 'close xb comms handle
 xbwake  'wake up xbee module
 Open "com1:2400" As console  'open console mode
End     'stop running program
End Sub
 
 'Sub xbsend (AreaTX,IDdestinationprocess,IDCallerprocess,IDdataHigh,IDdataLow)
 ' print  IDdestinationprocess;IDCallerprocess;IDdataHigh;IDdataLow
 ' msgFrame$ = "U" + Chr$(AreaTX) + Chr$(IDdestinationprocess) + Chr$(IDCallerprocess) + Chr$(IDdataHigh) + Chr$(IDdataLow)
 ' Print #5, msgframe$
 'End Sub
 
Sub xbsend (msgframe$)
 'on error skip
 print "xbsend:" + msgframe$
 Print #5,msgframe$
End Sub
 
 
Sub xbreceive
 a$=Input$(1,#5)    'user supplied processing routine
 If iXbeeFlag=1 And iXbeeAreaFlag=1   Then  GoTo CompletePacket  'read rest of data packet
 If iXbeeFlag=1 And iXbeeAreaFlag=0 Then 'check for correct area flag
   'print asc(a$)
   If Asc(a$)=iArea Then  'check for correct Area (for this device)
     iXbeeAreaFlag=1       ' correct so set flag
   Else
     iXbeeFlag=0 And iXbeeAreaFlag=0   'not correct so clear flags and look again
   EndIf
   Exit Sub 'exit
 EndIf
 If iXbeeFlag=0 And iXbeeAreaFlag=0   Then
   If a$="U" Then        'check for xBee sync byte
     iXbeeFlag=1               'got sync byte so set flags, now we need correct area flag
   EndIf
   Exit Sub 'exit
 EndIf
 Exit Sub 'exit          'invalid so exit
CompletePacket:
 temp$=Str$(Asc(a$)) 'add leading zero as required
 lastline$=lastline$+","+temp$    'store data packet
 ibytecount=ibytecount+1   'count databytes
 If ibytecount=4 Then GoTo processPacket
 Exit Sub 'exit get more bytes
 'data line received - now process
processPacket:
 lastline$=Mid$(lastline$,2)
 'print "packet:" + lastline$
 Newline$=Lastline$             'store data
 inewline=1                      'new line available flag
 ' Print newline$ '-TESTING ONLY
 If Left$(newline$,2) = "14" Then  'PixBee network is requesting a data slot
   AreaTX$ = parse$(newline$,3)
   xbAck 'call RXslot routine to allow Device to Send data
   goto ClearFlags
 EndIf
 '******** Call external user routines to parse line data packet here *********
 If inewline=1 Then Userprocess
 'End of packet clear flags
ClearFlags:
 iXbeeFlag=0                          'clear Xbee data flag
 iXbeeAreaFlag=0               'clear Xbee Area flag
 lastline$=""
 ibytecount=0
End Sub 'from xbreceive
 
sub Callhome
 'xbsend (iAreaTX,8,iDeviceID,iArea,2)    'Call Home with counter value (status), ie 2 mins in dataLow
end sub
 
Sub CmdSlot
 'xbsend (iAreaTX,13,iDeviceID,iArea,0)    'request Network command slot
End Sub
 
Sub xbAck  'Sub RxSlot , responds to Pixbee network data transfer request by Sending a ID "15"
 'xbsend (iAreaTX,15,iDeviceID,iCommandID,1)    'Network command acknowledge
End Sub
 
Sub ReqNetworkTime
 ' xbsend (iAreaTX,17,iDeviceID,iArea,0)    'request Network time update
End Sub
 
 'UserProcess routine is called by XBreceive routine when a complete data packet is received , to check for commands
 'Sub UserProcess 'User Subroutine to process incomming communications data
 'End Sub
 
 'End of Maximite wireless library'End INCLUDE

Codenquilts
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025