View previous topic :: View next topic |
Author |
Message |
Paulvk
Joined: 28 Jul 2006 Posts: 1257 Location: SYDNEY
|
Posted: Fri Feb 01, 2019 11:55 am Post subject: Measuring AC & DC current |
|
|
For a long time I have a need to measure AC & DC current in my off grid systems.
I found a number of ways to do this but most rely on a special IC and complex RMS calculations
I wanted to use a non invasive split core current transformer.
The 10 bit ADC in the AVR does not allow for good accuracy.
So I have chosen the MAX1238 12bit I2C ADC.
Next I needed to get the RMS value I found this IC LTC1966
not a cheap IC but you can get it on ebay on a board and use a analog switch to multiplex inputs
I have used the readily available SCT-013-000 split current transformers.
I have managed to get 0.06 to 70amps
By changing the burden resistor the scale can be made smaller eg 0.3 to 20amps
I also had a problem with the MAX1238 it is now only made with one I2C address
I have solved this with I2C multiplexers PCA9540BDP , PCA9544APW
these multiplexers also allow you to mix 5V & 3.3V i2c buses.
The code below is used to turn on the I2C MUX ports they are easy to use.
Regards Paul
Code: |
'======= PCA9540BDP
I2csend &HE0 , &H04 'mux chanel 0 on
'I2csend &HE0 , &H05 'mux chanel 1 on
'=======PCA9544A Note has 3 address pins so 8 in total starting at HE0
'I2csend &HE0 , &H06 'mux chanel 2 on
'I2csend &HE0 , &H07 'mux chanel 3 on
'I2csend &HE0 , &H00 'all mux chanels off
|
|
|
Back to top |
|
|
Paulvk
Joined: 28 Jul 2006 Posts: 1257 Location: SYDNEY
|
Posted: Sun Feb 03, 2019 10:00 am Post subject: |
|
|
Now a program that scans the I2C bus
then switches on channel "0" of the mux
then scans again to show its on by finding the MAX1238
also has notes on burden resistors for current clamp
Regards Paul
Code: |
$regfile = "M644pdef.dat" ' the used chip
$crystal = 8000000 ' frequency used
$baud = 57600 ' baud rate
$hwstack = 40
$swstack = 40
$framesize = 40
Const Debuging = 0
Const Wrmax1238 = &H6A '&B01101010 write to MAX1238
'--read
Const Rdmax1238 = &H6B '&B01101011 read from MAX1238
'--setup byte
'use internal reference, internal clock, unipolar mode
Const Setmax1238 = &HD2 ' &B11010010
'use external reference, internal clock, unipolar mode
Const Setmax1238x = &H22 ' &B00100010
'Declare Function Adc128_temp()as Integer
'Declare Sub Adc128setup_regs
'Declare Function Adc128read_port(byval Port As Byte)as Integer
Declare Sub Max1239_setup(byval Mo As Byte)
Declare Function Getmax1239(byval Chno As Byte ) As Word
Dim Adc128_addr As Byte
Dim B As Byte
Dim C As Integer
Dim K As Single
Dim Kk As Single
Dim D As Byte
Dim E As Word
Dim Z(2) As Byte At E Overlay
Dim F As Byte
Dim Adcprn As String * 16
Dim Adcprn2 As String * 16
Dim M As Word
Dim Mm As Word
Config Scl = Portc.0 ' we need to provide the SCL pin name
Config Sda = Portc.1 ' we need to provide the SDA pin name
$lib "glcdKS108.lbx"
'Config Graphlcd = 240x64 , Dataport = Portc , Controlport = Porta , Ce = 5 , Cd = 6 , Wr = 3 , Rd = 4 , Reset = 7 , Fs = 0 , Mode = 6
Config Graphlcd = 128 * 64sed , Dataport = Porta , Controlport = Portc , Ce = 2 , Ce2 = 3 , Cd = 7 , Rd = 6 , Reset = 4 , Enable = 5
Setfont Font8x8
$lib "i2c_twi.lbx" ' we do not use software emulated I2C but the TWI
Config Twi = 100000 'speed 100 KHz
Adc128_addr = &H3A
I2cinit 'not really requried
Wait 5
Cls Graph
Wait 2
D = 1
Print "Scan start"
Lcdat 1 , 1 , "Scan start"
For B = 0 To 254 Step 2 'for all odd addresses
I2cstart 'send start
I2cwbyte B 'send address
If Err = 0 Then 'we got an ack
Print "Slave at : " ; B ; " hex : " ; Hex(b) ; " bin : " ; Bin(b)
Lcdat D + 1 , 1 , "Slave at HEX>" ; Hex(b)
Incr D
End If
I2cstop 'free bus
Next
Print "End Scan"
I2csend &HE0 , &H04 'mux chanel 0 on
'I2csend &HE0 , &H05 'mux chanel 1 on
'=======PCA9544A Note has 3 address pins so 8 in total starting at HE0
'I2csend &HE0 , &H06 'mux chanel 2 on
'I2csend &HE0 , &H07 'mux chanel 3 on
'I2csend &HE0 , &H00 'all mux chanels off
Lcdat D + 1 , 1 , "mux chan 0 on"
Wait 4
For B = 0 To 254 Step 2 'for all odd addresses
I2cstart 'send start
I2cwbyte B 'send address
If Err = 0 Then 'we got an ack
Print "Slave at : " ; B ; " hex : " ; Hex(b) ; " bin : " ; Bin(b)
Lcdat D + 1 , 1 , "Slave at HEX>" ; Hex(b)
Incr D
End If
I2cstop 'free bus
Next
'max1239 setup
'1= internal reference, internal clock, unipolar mode
'2= external reference, internal clock, unipolar mode
Call Max1239_setup(2) 'using external 1.225v refrence
Wait 5
Cls Graph
Do
Mm = 0
For B = 1 To 4
M = Getmax1239(0)
Waitms 1
'Swap M
Mm = Mm + M
Next
Shift Mm , Right , 2
M = Mm
K = M
'convert to milivolts
'K = K * 0.0003326
'20 amp
Kk = K * 0.0317
'mV
K = K * 0.0015
'convert to amps
'Kk = K * 28.7
'========================================
'burden resistor values
'using a 200ohm 25 turn trimmer in parallel with higher
'value resistor can achieve exact value and allow to be calibrated
'10 AMP with SC015 100A/50mA 150ohm Burden
'20 AMP with SC015 100A/50mA 2 x 150ohm =75ohm Burden
'30 AMP with SC015 100A/50mA 50ohm Burden
'40 AMP with SC015 100A/50mA 37.5ohm Burden
'50 AMP with SC015 100A/50mA 30ohm Burden
'60 AMP with SC015 100A/50mA 25ohm Burden
'70 AMP with SC015 100A/50mA 22ohm (21.4) Burden
'Kk = K * 12.753
Adcprn = Str(k)
Adcprn2 = Str(kk)
Lcdat 4 , 1 , ">>" ; M
Lcdat 5 , 1 , Bin(m)
Lcdat 6 , 1 , "Volt>" ; Fusing(k , "#.####")
Lcdat 7 , 1 , "Amps >" ; Fusing(kk , "#.##")
Wait 2
Loop
End
$include "MAX1239.inc"
$include "font8x8.font"
|
Code: |
'-----------MAX1238------------------------------------------------------------------------
'--MAX1238 is a 12 bit 12 channel I2C ADC
'Const Wrmax1238 = &H6A '&B01101010 write to MAX1238
'--read
'Const Rdmax1238 = &H6B '&B01101011 read from MAX1238
'--setup byte
'use internal reference, internal clock, unipolar mode
'Const Setmax1238 = &HD2 ' &B11010010
'use external reference, internal clock, unipolar mode
'Const Setmax1238 = &HB2 ' &B10110010
'--configuration bytes
'-scan all adc inputs 0 to 11 single ended
'Const Scanall = &H17 '&B00010111
'--convert one ADC channel single ended BINARY VALUE
'Const Scan0 = &H61 '&B01100001 scan adc 0
'Const Scan1 = &H63 '&B01100011 scan adc 1
'Const Scan2 = &H65 '&B01100101 scan adc 2
'Const Scan3 = &H67 '&B01100111 scan adc 3
'Const Scan4 = &H69 '&B01101001 scan adc 4
'Const Scan5 = &H68 '&B01101011 scan adc 5
'Const Scan6 = &H6D '&B01101101 scan adc 6
'Const Scan7 = &H6F '&B01101111 scan adc 7
'Const Scan8 = &H71 '&B01110001 scan adc 8
'Const Scan9 = &H73 '&B01110011 scan adc 9
'Const Scan10 = &H75 '&B01110101 scan adc 10
'Const Scan11 = &H77 '&B01110111 scan adc 11
'--HSmode
'Const Hsmax1238 = &H08 '&B00001000
'-------------------------------------------------------------------------------
'---------------------------------------
'--These subs set up and reads the values from
'--the MAX1239 12 bit ADC
'----this takes a channel number (Chno) sets up the ADC
'----tells it to do the conversion
'----and reads the value from the channel
Function Getmax1239(byval Chno As Byte ) As Word
Local Scan_val As Byte
Local 1239w As Word
'--move the bits to the left one place as the last bit
'--is "1" as we are writing to the ADC
Shift Chno , Left , 1
'--&H61 is to read channel 0 so if we add
'--the channel number to it shifted left
'--one place we will get the byte to read
'--the channel number we want
Scan_val = &H61 + Chno
'use internal reference, internal clock, unipolar mode
'I2csend Wrmax1238 , Setmax1238
I2csend Wrmax1238 , Scan_val
'Waitms 100
'--read in the two bytes
I2creceive Rdmax1238 , 1239w , 0 , 2
Swap 1239w
'--move the word to the left 4 bits causing
'--the first 4 bits to get lost then move it
'--back 4 bits which will make them all 0s
'--giving us only the 12bits we want
Shift 1239w , Left , 4
Shift 1239w , Right , 4
Getmax1239 = 1239w 'assign the value
End Function
Sub Max1239_setup(byval Mo As Byte)
Select Case Mo
Case 1
'use internal reference, internal clock, unipolar mode
I2csend Wrmax1238 , Setmax1238 ' &B11010010
Case 2
'use external reference, internal clock, unipolar mode
I2csend Wrmax1238 , Setmax1238x ' &B00110010
'Lcdat 4 , 1 , "mode " ; Mo
End Select
End Sub
|
|
|
Back to top |
|
|
Paulvk
Joined: 28 Jul 2006 Posts: 1257 Location: SYDNEY
|
Posted: Fri Feb 22, 2019 6:52 am Post subject: |
|
|
Here is a program that uses ACS 712 20AMP hall current sensors
there are 11 battery banks in parallel it measures the current in each bank
it then adds up the total current
this is displayed on a 2x15 lcd and sent to RS232
Note bank 10 is not yet connected
Also note the MCS Bootloader is installed
bytematch is used to trigger a jump to the bootloader
This enables me upload new programs to the unit over my LAN
I am using the HLK RM04 to send the RS232 over TCPIP
Note the same baud rate needs to be set in bootloader , main program and HLK RM04
Regards Paul
Code: |
$regfile = "M168pdef.dat" ' the used chip
$crystal = 8000000 ' frequency used
$baud = 9600 ' baud rate
$hwstack = 40
$swstack = 40
$framesize = 40
Const Test = 2
Const Batt = 1
Config Lcdpin = Pin , Db4 = Portd.5 , Db5 = Portd.4 , Db6 = Portd.3 , Db7 = Portd.2 , E = Portb.0 , Rs = Portb.1
Config Lcd = 16x2
Config Scl = Portc.5 ' we need to provide the SCL pin name
Config Sda = Portc.4 ' we need to provide the SDA pin name
$lib "i2c_twi.lbx" ' we do not use software emulated I2C but the TWI
Config Twi = 100000 'speed 100 KHz
Const Wrmax1238 = &H6A '&B01101010 write to MAX1238
'--read
Const Rdmax1238 = &H6B '&B01101011 read from MAX1238
'--setup byte
'use internal reference, internal clock, unipolar mode
Const Setmax1238 = &HD2 ' &B11010010
'use external reference, internal clock, unipolar mode
Const Setmax1238x = &H22 ' &B00100010
'Declare Function Adc128_temp()as Integer
'Declare Sub Adc128setup_regs
'Declare Function Adc128read_port(byval Port As Byte)as Integer
Declare Sub Max1239_setup(byval Mo As Byte)
Declare Function Getmax1239(byval Chno As Byte ) As Word
Dim Adc128_addr As Byte
Dim B As Byte
Dim C As Integer
Dim K As Single
Dim Kk As Single
Dim D As Byte
Dim E As Word
Dim Z(2) As Byte At E Overlay
Dim F As Byte
Dim Adcprn As String * 16
Dim Adcprn2 As String * 16
Dim M As Word
Dim Mm As Word
Dim Ampsval As Word
Dim Amps As Word
Dim Ampo As Word
Dim Amp As Single
Dim Bankamp(12) As Single
Config Portb.2 = Output
Set Portb.2
Enable Interrupts
Config Serialin0 = Buffered , Size = 20 , Bytematch = 123
Cls
Do
' used later
F = Ischarwaiting()
If F = 1 Then
D = Inkey()
End If
#if Test = 2
For D = 0 To 10
Amps = 0
For B = 1 To 4
Ampsval = Getmax1239(d)
Amps = Amps + Ampsval
Waitms 2
Next
Shift Amps , Right , 2
Amp = Amps
Amp = Amp * .0012
Amp = Amp - 2.448
Amp = Amp * 10
Bankamp(d + 1) = Amp
Next
Amp = 0
For D = 1 To 9
Amp = Amp + Bankamp(d)
Next
Amp = Amp + Bankamp(11)
Cls
Lcd Fusing(bankamp(1) , "#.##") ; "*" ; Fusing(bankamp(2) , "#.##") ; "*" ; Fusing(bankamp(3) , "#.##")
Lowerline
Lcd Fusing(bankamp(4) , "#.##") ; "*" ; Fusing(bankamp(5) , "#.##") ; "*" ; Fusing(bankamp(6) , "#.##")
Wait 3
Cls
Lcd Fusing(bankamp(7) , "#.##") ; "*" ; Fusing(bankamp(8) , "#.##") ; "*" ; Fusing(bankamp(9) , "#.##")
Lowerline
Lcd Fusing(bankamp(10) , "#.##") ; "*" ; Fusing(bankamp(11) , "#.##")
Wait 3
Cls
Lcd "Total Aps"
Lowerline
Lcd " " ; Fusing(amp , "#.###")
Wait 3
For D = 1 To 11
Print Fusing(bankamp(d) , "#.###") ; "<>";
Next
Print
Print "Total Amps = " ; Fusing(amp , "#.###")
#endif
Amps = 0
'code for wireless +-200amp current sensor
'output of hall sensor 2.5v zero amps +- 2v for 100amp
#if Batt = 2
For B = 1 To 4
Ampsval = Getmax1239(11)
Amps = Amps + Ampsval
Waitms 2
Next
Ampo = Amps
Shift Amps , Right , 2
Amp = Amps
Amp = Amp - 2030
Amp = Amp * .124
Bankamp(12) = Amp
Print "Battery current is >" ; Bankamp(12) ; " Amps"
Cls
Lcd "Amps>" ; Fusing(amp , "#.#")
Lowerline
Lcd "amps=" ; Ampo
Wait 3
#endif
Loop
End
Serial0charmatch:
Cls
Lcd "BOOT VECTOR"
Wait 1
'here you need to read the data sheet
'to find the correct address
Goto &HC00
Return
$include "MAX1239.inc"
|
|
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Fri Feb 22, 2019 1:16 pm Post subject: |
|
|
hi Paul
interesting project.
I hope to implement off grid in the future as well.
Thanks for sharing the code. it seems you use both Max1239 and 1238? _________________ Mark |
|
Back to top |
|
|
Paulvk
Joined: 28 Jul 2006 Posts: 1257 Location: SYDNEY
|
Posted: Sat Feb 23, 2019 11:59 am Post subject: |
|
|
albertsm wrote: | hi Paul
Thanks for sharing the code. it seems you use both Max1239 and 1238? |
The max1238 is for 5V and the max1239 for 3.3V
The big cost now with off grid is the batteries but if there is a need for a UPS
the all in one inverter , grid charger , solar charger units make a lot of sense. |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Sat Feb 23, 2019 2:05 pm Post subject: |
|
|
yes i know the batteries are expensive. One would need an old one from en electric car.
the other issue with batteries is that the do not last long.
Tesla is making off grid batteries too. not really affordable.
Too bad that the angle of my roof is not suited for solar panels. But at some stage the day light panels are low cost enough to make it work for my roof too. _________________ Mark |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|