Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    Current sensor 15A SCT-013

    Scheduled Pinned Locked Moved LoPy
    sensorcurrentlopy
    28 Posts 3 Posters 3.7k Views 3 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • V Offline
      Vicky_
      last edited by

      Hi,
      I bought a current sensor from here. 15A SCT-013
      and I made a circuit following this link.

      below are my current sensor specification:
      Model: SCT-013-015
      Input current: 0A-15A
      Rated output: 15A/1V
      Opening size: 13 x 13mm
      Output plug: 3.5mm
      Dielectric strength: 6000V AC/1min
      Mechanical strength: >= 1000 times
      Working temperature: -25C ~ +70C(-13F~ +158F)
      Cable length: 1.0m
      Anti-flaming rate:UL94-V0
      Size: 57 x 32 x 21mm

      I connected the input voltage to 3.3V, GND to GND and analog output to P13 at LoPy. something like this:

      alt text

      my coding as below:

      import machine
      from machine import ADC
      import time
      
      adc = machine.ADC() 
      apin = adc.channel(pin='P13',attn=ADC.ATTN_11DB)
      
      for i in range(100):
          val = apin()
          print(val)
          time.sleep(1)
      

      but the value I got is random numbers. when no current pass through it will has random numbers, same when current pass through it gets 0. I try connect the input voltage to 5v at LoPy but it is the same. I read a lot of post about sensors connect to LoPy but I cant find current sensor.

      Can anyone help? Thank you so much.

      robert-hhR 2 Replies Last reply Reply Quote 0
      • robert-hhR Offline
        robert-hh @Vicky_
        last edited by

        @vicky_ For use with the LoPy, you have to attach it to use the 3.3v Pin instead of the 5V pin. The output of the sensor is a sine wave with the frequency of the AC current you're measuring. This sensor is made for AC only, and typically at low frequencies, like 50 or 60 Hz.
        The ADC input of the ESP32 is noisy. So you have to average over a few measurements for DC measurements. For AC it is more difficult. If you just want to take the current of the mains signal at a fixed frequency, you can do something like a fixed frequency amplitude analysis. Look out for the "goertzel-Algorithm", which does that w/o needing to sample a buffer full of data. A sample implementation is below:

        #
        import gc
        import math
        import array
        from utime import sleep_ms, sleep_us
        from machine import ADC, Timer, idle, enable_irq, disable_irq, Pin
        
        #
        # acquire ADC values. The paramters of the constructor are:
        # 1. the mains frequency (number, typically 50 or 60)
        # 2. the sampling period (ms). The default is 2 ms.
        #
        class Acquire:
            def __init__(self, freq=50, *, sample_period=2):
                self.sample_period = sample_period
                self.omega = 2.0 * math.pi * freq / (1000 / sample_period)
                self.coeff = 2.0 * math.cos(self.omega)
                self.adc = ADC(bits=9)
        
            def start(self, pin, time=200):
                gc.collect() # avoids automatic gc during sampling
                self.pin_adc = self.adc.channel(pin=pin, attn=ADC.ATTN_11DB)
                self.samples = time // self.sample_period
                self.count = 0
                self.busy = True
                self.q1 = 0.0
                self.q2 = 0.0
                self.alarm = Timer.Alarm(self.read_adc, 0, ms=self.sample_period, periodic=True)
        
            def stop(self):
                self.alarm.cancel()
        
            def read_adc(self, alarm):
                self.q0 = self.pin_adc() + self.coeff * self.q1 - self.q2
                self.q2 = self.q1
                self.q1 = self.q0
                self.count += 1
                if self.count >= self.samples:
                    self.alarm.cancel()
                    self.busy = False
        
            def result(self):
                while self.busy == True:
                    sleep_ms(self.sample_period)
        
                amplitude = 2 * math.sqrt(self.q1 * self.q1 +
                                          self.q2 * self.q2 -
                                          self.q1 * self.q2 * self.coeff) / self.count
                # if phase is required:
                # real = self.q1 - self.q2 * math.cos(self.omega)
                # imag = self.q2 * math.sin(self.omega)
                # amplitude = 2 * math.sqrt(real * real + imag * imag) / self.count
                # phase = math.atan2(real, imag)
                #
                return amplitude
        
            def reading(self, pin, time):
                self.start(pin, time)
                return self.result()
        #
        
        while True:
            acq = Acquire(50) # 50 Hz
            value = acq.reading("P13", 1000)
            print (value)
        
        1 Reply Last reply Reply Quote 0
        • robert-hhR Offline
          robert-hh @Vicky_
          last edited by

          @vicky_ I shoud add that I used another way of connecting the sensor, which also limits the input voltage, which can go up to +/-10 V in over current conditions:

          0_1524387256576_connecting.jpg

          Input voltage w/o limitation:_
          0_1524387333918_without_limiting.jpg

          Input voltage with limitation:

          0_1524387368300_with_limiting.jpg

          V S 2 Replies Last reply Reply Quote 1
          • V Offline
            Vicky_ @robert-hh
            last edited by

            @robert-hh Hello, thanks for your reply! sorry for late reply because I was trying to digest your information. I have read up a bit about "goertzel-Algorithm" but Im not very understand the coding and the diagram. Why adc bits=9? Can I get the DC voltage using that coding? by diving the value obtained 512 and times with 3.3. like this (x/512)x3.3

            I also confused with the connection of the current sensor. can I use back my own connection because this can work with Arduino.
            https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/interface-with-arduino?redirected=true
            just that i dont have the Emon Lib.

            Sorry if I ask silly questions! I really appreciate your help!

            robert-hhR 2 Replies Last reply Reply Quote 0
            • robert-hhR Offline
              robert-hh @Vicky_
              last edited by

              @vicky_ I used adc=9 bits, because thats the useful resolution for the ESP32 ADC. You may also go for 12 bits, but all you will get is more noise, not more precision.
              Yes, you can use also your circuit, as long as you connect it to 3.3V and not to 5V. The two circuits are effectively the same. The reason I prefer mine is, that one side of the sensor output is connected to GND. But that is more a flavour than technical need. I strongly reccomend the protection circuit. The sensor is a low impedance source, and saturates at +/- 10V, which, when applied to the ESP32, will most likely kill your LoPy.
              Bot the sensor and the software work with AC only. The sensor if an AC transformer. With DC the output is 0. The software returns the amplitude of a fixed frequency in the input signal. Since the sensor is used for mains current, typical frequencies are 50 or 60 Hz.
              maybe a note for using the sensor: You must feed only a single wire though the sensor. Loads are connected typicall with at least two wires. Only one of them must be passed through the sensor. Otherwise, the output signal of the sensor is 0.

              V 2 Replies Last reply Reply Quote 1
              • V Offline
                Vicky_ @robert-hh
                last edited by

                @robert-hh Thanks for your clear explanation! I will try it and see how.
                Yea, I only feed one single wire which is the live wire. Thanks for your remind. Thank you

                1 Reply Last reply Reply Quote 0
                • V Offline
                  Vicky_ @robert-hh
                  last edited by Vicky_

                  @robert-hh Hello. The coding you shared, it works! Thanks a lot.
                  I use it to measure a hairdryer rated 1000w to 1200w.
                  when hairdryer is off I get 0.something.
                  when I open level 1 I get 10. something.
                  when I open level 2 I get 45. something.
                  when I open level 3 I get 71. something.
                  I chose the maximum value 71.something and divide 512 (9 bits ADC) times with 3.3v and 15A.

                  eg:
                  ((71.22/512)*3.3)*15 = 6.86A

                  but the maximum current should be 1200/240v =5A, right?

                  or my calculation is wrong?

                  I used it to measure a phone charger but it has no different with when it is off, maybe the current is too small.

                  once again, thanks

                  alt text

                  robert-hhR 1 Reply Last reply Reply Quote 0
                  • robert-hhR Offline
                    robert-hh @Vicky_
                    last edited by robert-hh

                    @vicky_ The transfer ratio is hard to guess, because there are some unknown figures in between, like the transfer function of your sensor. That is 1Veff at 15A. So at 5 A it should deliver 0.333Veff. But i did never determine the remainder of the transfer function.
                    What you should do is to take the current of the hairdryer with an known good Multimeter and determine a factor from that. The ESP32 ADC is non-linear, especially at 11 dB attenuation. But the mid range values should be OK. Using 6 dB attenuation the linearity is better. But then you'll need a different interface circuit.
                    Yes, at low currents the ADC noise and the phase noise of the sampling steps in. If the time for reading a value is larger, you'll have somewhat less noise. This time should be a integer multiple of the wave period. For 50 Hz, a multiple of 20 is fine, for 60 Hz a multiple of 50. So taking a multiple of 100 is good for both frequencies.

                    V 1 Reply Last reply Reply Quote 1
                    • V Offline
                      Vicky_ @robert-hh
                      last edited by

                      @robert-hh Thanks for your suggestion! I understand what you trying to say until this part "If the time for reading a value is larger, you'll have somewhat less noise. This time should be a integer multiple of the wave period. For 50 Hz, a multiple of 20 is fine, for 60 Hz a multiple of 50. So taking a multiple of 100 is good for both frequencies."

                      do you mean that at the coding the time I should modify it
                      time1 = time x 100 and all time change it to time1?
                      sorry.

                      robert-hhR 1 Reply Last reply Reply Quote 0
                      • robert-hhR Offline
                        robert-hh @Vicky_
                        last edited by robert-hh

                        @vicky_ in my example, the time for reading is 1000 = 1000ms. If that is too slow, you may take any multiple of 100, like 100, 200, 300, .... instead. Besides that, you can freely select the total measuring time.

                        V 1 Reply Last reply Reply Quote 0
                        • V Offline
                          Vicky_ @robert-hh
                          last edited by

                          @robert-hh ok thank you so much!

                          1 Reply Last reply Reply Quote 0
                          • S Offline
                            StefanoF @robert-hh
                            last edited by StefanoF

                            @robert-hh

                            Hi,
                            sorry Robert, because this schema is different of schema di Vicky? 957fd326-fdd1-45bf-b8b6-0878191859ce-image.png ,,
                            can you kindly let me know which schema I need used?

                            Many thanks

                            robert-hhR 2 Replies Last reply Reply Quote 0
                            • robert-hhR Offline
                              robert-hh @StefanoF
                              last edited by

                              @StefanoF They are identical in that they shift up the signal to be measured by Vdd/2. The difference:

                              • In my schematic the sensor is directly tied to GND, here it is tied to a virtual GND at Vdd/2 with a impedance at 50 Hz of about 30 Ohm.
                              • I added in my schematics overvoltage protection, which is missing here.

                              As long as there is no excess current you are try to measure, both will work. In case of a shortage in the sensed circuit, there is a high risk that the connected Pycom device will be damaged.

                              P.S.: To get a result for measuring, only C1, R1 and R2 are needed in my circuit. Everything else is for protection.

                              S 1 Reply Last reply Reply Quote 0
                              • robert-hhR Offline
                                robert-hh @StefanoF
                                last edited by

                                @StefanoF The schema in your post and the one of Vicky are identical, just differently sketched.

                                S 1 Reply Last reply Reply Quote 0
                                • S Offline
                                  StefanoF @robert-hh
                                  last edited by

                                  @robert-hh Thanks for your suggestion!

                                  1 Reply Last reply Reply Quote 0
                                  • S Offline
                                    StefanoF @robert-hh
                                    last edited by robert-hh

                                    @robert-hh

                                    StefanoF 2 days ago
                                    Hi ,
                                    I've used this the electronic schema , I've in out 1.65 volt at empty, the sensor is at 15A (STC 013-015)
                                    Can you kindly help me with easy code,

                                    apin = adc.channel(pin='P13', attn=ADC.ATTN_11DB)
                                    
                                    peakVoltage = float(0)
                                    ACCurrtntValue = float(0)
                                    for i in range(5):
                                        peakVoltage += apin.voltage()
                                        utime.sleep_ms(1)
                                    peakVoltage = (peakVoltage / 5)
                                    voltageVirtualValue = (peakVoltage / 1000)
                                    print(round(voltageVirtualValue,2))
                                    

                                    result 1.65

                                    Many thanks

                                    robert-hhR 1 Reply Last reply Reply Quote 0
                                    • robert-hhR Offline
                                      robert-hh @Vicky_
                                      last edited by

                                      This post is deleted!
                                      1 Reply Last reply Reply Quote 0
                                      • robert-hhR Offline
                                        robert-hh @StefanoF
                                        last edited by

                                        @StefanoF You code snippet calculates the average DC voltage at the input. But what you need is the amplitude of the 50 Hz (or 60 Hz) AC voltage. So you have to do some kind of frequency analysis for that frequency. The most simple algorithm for doing that is the so called goertzel algorithm. If you scroll back in this thread, you will find an example which I posted there. I used that and it works fine, except for very small currents. But that is not the problem of the algorithm, that caused by the noise of the ADC capture, both amplitude and phase noise.

                                        S 1 Reply Last reply Reply Quote 0
                                        • S Offline
                                          StefanoF @robert-hh
                                          last edited by robert-hh

                                          @robert-hh

                                          Hi Robert,
                                          I've used this my code e variabile ma è valido:
                                          Thanks you

                                          def readACCurrentValue():
                                              global RANGE_AMPS, ADJUST_VOLTAGE
                                              peakVoltage = float(0)
                                              ACCurrtntValue = float(0)
                                              for i in range(5):
                                                  peakVoltage += apin.voltage()
                                                  utime.sleep_ms(1)
                                              peakVoltage = (peakVoltage / 5) 
                                              voltageVirtualValue = round(peakVoltage / 1000,2) - 1.65   
                                              if(math.fabs(voltageVirtualValue)>0.1):
                                                  ACCurrtntValue = (math.fabs(voltageVirtualValue) * 15)   #15 A
                                              return round(ACCurrtntValue,2)
                                          
                                          robert-hhR 1 Reply Last reply Reply Quote 0
                                          • robert-hhR Offline
                                            robert-hh @StefanoF
                                            last edited by robert-hh

                                            @StefanoF I think your code is not useful. It does not determine the value of the 50HZ AC component. Instead it calculate the average value of a 5ms time window somewhere in the 20ms period of a 50 Hz wave. For a given constant current you will get a largely varying output value, if you repeat the call several time non-synchronous with the mains frequency. And even is the value is in the synchronous case seemingly constant, it may be totally wrong.
                                            I tried similar approaches, e.g. finding the highest and lowest value and then calculating the difference, like a Vpp determination. But that was not robust at all. The only robust approach was using a FFT approach, like the mentioned Goertzel algorithm.

                                            S 1 Reply Last reply Reply Quote 0

                                            Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                                            Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                                            With your input, this post could be even better 💗

                                            Register Login
                                            • 1
                                            • 2
                                            • 2 / 2
                                            • First post
                                              Last post

                                            Pycom on Twitter

                                            Pycom