Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Measuring AC & DC current

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM Project Blog
View previous topic :: View next topic  
Author Message
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1101
Location: SYDNEY

australia.gif
PostPosted: Fri Feb 01, 2019 11:55 am    Post subject: Measuring AC & DC current Reply with quote

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
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1101
Location: SYDNEY

australia.gif
PostPosted: Sun Feb 03, 2019 10:00 am    Post subject: Reply with quote

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
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1101
Location: SYDNEY

australia.gif
PostPosted: Fri Feb 22, 2019 6:52 am    Post subject: Reply with quote

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
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 4705
Location: Holland

blank.gif
PostPosted: Fri Feb 22, 2019 1:16 pm    Post subject: Reply with quote

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
View user's profile Visit poster's website
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1101
Location: SYDNEY

australia.gif
PostPosted: Sat Feb 23, 2019 11:59 am    Post subject: Reply with quote

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
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 4705
Location: Holland

blank.gif
PostPosted: Sat Feb 23, 2019 2:05 pm    Post subject: Reply with quote

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
View user's profile Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM Project Blog All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
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