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

    Getting battery consumption from ADC

    Scheduled Pinned Locked Moved LoPy
    6 Posts 5 Posters 269 Views 6 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.
    • S Offline
      StijnK
      last edited by

      Re: Always reading same battery voltage

      Hi,
      I'm also trying to get this to work.
      For the moment I've got a LoPy connected to an expansion board v3.1. I created the function as stated in another example:

      def ADCloopMeanStdDev():
          numADCreadings = const(100)
          adc = machine.ADC(0)
          adcread = adc.channel(attn=3, pin='P16')
          samplesADC = [0.0]*numADCreadings; meanADC = 0.0
          i = 0
          while (i < numADCreadings):
              adcint = adcread()
              samplesADC[i] = adcint
              meanADC += adcint
              i += 1
          meanADC /= numADCreadings
          varianceADC = 0.0
          for adcint in samplesADC:
              varianceADC += (adcint - meanADC)**2
          varianceADC /= (numADCreadings - 1)
          print("%u ADC readings :\n%s" %(numADCreadings, str(samplesADC)))
          print("Mean of ADC readings (0-1023) = %15.13f" % meanADC)
          print("Mean of ADC readings (0-1400 mV) = %15.13f" % (meanADC*1400/1024))
          print("Variance of ADC readings = %15.13f" % varianceADC)
          print("10**6*Variance/(Mean**2) of ADC readings = %15.13f" % ((varianceADC*10**6)//(meanADC**2)))
      

      I call this function at the time wanted...

      As stated in some posts that the expansionboard had a builtin voltage divider and that the attenuation should be set to 3 I get this as output:

      100 ADC readings :
      [2832, 2823, 2825, 2825, 2829, 2826, 2823, 2826, 2826, 2831, 2823, 2827, 2827, 2853, 2825, 2826, 2823, 2830, 2830, 2829, 2823, 2822, 2831, 2831, 2827, 2829, 2824, 2823, 2827, 2832, 2822, 2821, 2826, 2827, 2829, 2827, 2827, 2828, 2822, 2825, 2829, 2823, 2827, 2823, 2817, 2826, 2831, 2823, 2828, 2827, 2822, 2831, 2826, 2828, 2831, 2821, 2828, 2827, 2825, 2821, 2827, 2829, 2826, 2823, 2828, 2829, 2819, 2826, 2823, 2823, 2829, 2832, 2822, 2824, 2833, 2831, 2830, 2827, 2830, 2827, 2821, 2823, 2832, 2830, 2831, 2831, 2826, 2829, 2832, 2823, 2823, 2823, 2826, 2826, 2819, 2819, 2827, 2831, 2832, 2827]
      Mean of ADC readings (0-1023) = 2826.6498565673828
      Mean of ADC readings (0-1400 mV) = 3864.5603179931641
      Variance of ADC readings = 19.8257484436035
      10**6*Variance/(Mean**2) of ADC readings = 2.0000000000000
      range: mm  718.55
      

      The range is another sensor that is connected.
      This is the reading I'm getting when the LoPy is connected trough USB with no battery...

      When connecting a battery (3,7V, 1200mAh) as well:

      100 ADC readings :
      [2752, 2756, 2753, 2754, 2756, 2765, 2759, 2766, 2754, 2765, 2759, 2754, 2758, 2752, 2756, 2764, 2748, 2763, 2754, 2759, 2754, 2765, 2754, 2757, 2753, 2754, 2757, 2759, 2756, 2763, 2754, 2764, 2763, 2757, 2757, 2756, 2753, 2753, 2755, 2759, 2757, 2759, 2746, 2761, 2753, 2752, 2752, 2763, 2753, 2765, 2762, 2758, 2759, 2755, 2767, 2754, 2763, 2751, 2763, 2766, 2766, 2757, 2754, 2757, 2763, 2758, 2759, 2756, 2751, 2755, 2750, 2759, 2763, 2754, 2762, 2757, 2752, 2765, 2753, 2755, 2759, 2749, 2763, 2778, 2763, 2762, 2726, 2767, 2767, 2754, 2764, 2759, 2758, 2762, 2757, 2775, 2755, 2754, 2762, 2755]
      Mean of ADC readings (0-1023) = 2757.8399181365967
      Mean of ADC readings (0-1400 mV) = 3770.4842090606689
      Variance of ADC readings = 40.2569675445557
      10**6*Variance/(Mean**2) of ADC readings = 5.0000000000000
      range: mm  1172.5
      

      I get the above...

      My questions:

      • what am I reading here? What is the difference between those 2 lines (0-1023 and 0-1400 mV)?
      • is the 3770 (in line 2, 0 - 1400mV) my battery and thus saying how much voltage it is providing?
      • how do i know what the overall consumption is and how to measure it with a multimeter? (what contacts, when LoPy is connected to Expansion board)

      Sorry for the N00bness, just trying to figure this out.
      Kindest regards and thank you for the help.

      1 Reply Last reply Reply Quote 0
      • G Offline
        Gijs
        last edited by

        Hey,

        No worries, everybody was a beginner once ;)
        I tried to recreate your sample, but I do not have a battery so it just read the supply voltage.
        The maximum input voltage on the ADC is 1.1V. For a 12 bit resolution, this would give 4095 as a result (I think your example is for a 10 bit ADC with max value of 1023)
        Attenuation of 3dB would half the power, so we can read up to 2.2V.
        However there is already a voltage divider present on the board, already allowing us to read values up to 3.3V without attenuation (the resistor divide the voltage by 3.
        Of course, battery voltages are generally higher, up to 4.2V, which is why you would need the attenuation.
        In this case, the input voltage can be up to 6.6V with 3dB attenuation, that would return 4095. Your samples give around 2755, and doing the calculation, give 4.4V.

        You could check your reading against a multimeter reading to verify the result. I believe the built in charging circuit is supplying voltage to the rail when the battery is not connected?

        Let me know if it works for you

        Gijs

        robert-hhR 1 Reply Last reply Reply Quote 0
        • K Offline
          KenM
          last edited by KenM

          Based on the voltage you can know how much is left in the Lipo battery, but it's an indication more like 10%, 20% etc. not very accurate 3.54V is like 20% , 4.12V is like 100%

          import machine
          adc = machine.ADC()             # create an ADC object
          apin = adc.channel(pin='P16', attn=adc.ATTN_11DB)   # create an analog pin on P16, only with expansion board
          
          def getVoltage(): # Voltage on the Battery
              voltage = (apin.voltage() + apin.voltage() + apin.voltage() + apin.voltage()) / 4 # average 4
              return round(2*voltage/1000,2)
          
          1 Reply Last reply Reply Quote 0
          • robert-hhR Offline
            robert-hh @Gijs
            last edited by robert-hh

            @Gijs There was some confusion about the voltage divider on the Expansion board 3.1. But I think the latest result was, that it consists of two 1 MOhm resistors, whatever the documentation tells, giving a division factor of 2.
            About the attenuation levels of the ADC, taken from the ESP32 specs:

            0db for a full-scale voltage of 1.1V (default)
            2.5db for a full-scale voltage of 1.5V
            6db for a full-scale voltage of 2.2V
            11db for a full-scale voltage of 3.9V
            

            That again divided (or better multiplied) by the hardware attenuation factor.

            G 1 Reply Last reply Reply Quote 0
            • rcolisteteR Offline
              rcolistete
              last edited by rcolistete

              I recommend :

              • reading the Pycom MicroPython docs :
                Firmware & API Reference > Pycom Modules > machine > ADC
                Tutorials & Examples > All Pycom Device Examples > ADC
              • using the 'statistics' MicroPython module.

              Code I've been using :

                  import machine
                  import statistics
                  
                  NUM_ADC_READINGS = const(50)
              
                  adc = machine.ADC()
                  adc.vref(1126)  # put here ESP32 VRef measured in mV with a voltmeter
                  # adcP16 = adc.channel(pin='P16', attn=machine.ADC.ATTN_6DB) # For Expansion Board v2.x
                  adcP16 = adc.channel(pin='P16', attn=machine.ADC.ATTN_11DB) # For Expansion Board v3.x
                  samples_voltage = [0]*NUM_ADC_READINGS
                  for i in range(NUM_ADC_READINGS):
                  #    samples_voltage[i] = (171*adcP16.voltage())//56     # Expansion Board v2.x has voltage divider (115K + 56K) converting to integer voltage, [0, 6702] mV
                      samples_voltage[i] = (2*adcP16.voltage())//1   # Expansion Board v3.x has voltage divider (1M + 1M) converting to integer voltage, [0, 6600] mV
                  batt_mV = round(statistics.mean(samples_voltage))
                  batt_mV_error = round(statistics.stdev(samples_voltage))
              

              My "MicroPython Samples". My "MicroPython Firmwares" with many options (double precision, ulab, etc).

              1 Reply Last reply Reply Quote 1
              • G Offline
                Gijs @robert-hh
                last edited by

                @robert-hh Thanks for clearing that up. I was confused with the dB scale for power.

                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 / 1
                • First post
                  Last post

                Pycom on Twitter

                Pycom