Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. General Discussion
  3. Measuring battery voltage, which way is best?

Measuring battery voltage, which way is best?

Scheduled Pinned Locked Moved General Discussion
24 Posts 6 Posters 313 Views 5 Watching
  • 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.
  • BearWithBeardB Offline
    BearWithBeardB Offline
    BearWithBeard
    wrote on last edited by BearWithBeard
    #12

    The URL is in an inline code HTML element and the CSS rule #article code {white-space: nowrap;} prevents long lines from breaking the layout, causing the (visual) truncation depending on the window size. Double-clicking or marking the whole line with the cursor gives you the full link, but you can't simply click on it to open the URL. A hyperlink would wrap (and be clickable).

    mysensors-code-link-wrap.png

    I assume this is only a temporary solution. It might be better though to replace it with a hyperlink tag or better, embed it like the external measurement example in the section below it (once it's added to the examples repo).

    @mfalkvidd Okay, understood. Managing external libraries in ArduinoIDE projects can be cumbersome and confusing. Just brainstorming here - two ways of clarifying that external libraries are required in a provided example sketch:

    • After including an external library, add a conditional #error preprocessor directive that checks if the library-specific header guard is defined. This doesn't address backwards compatibility issues though:
    #include <Vcc.h>
    #ifndef VCC_H
    #error You need to install Arduino_VCC version 1.x (URL)
    #error How to install libraries in ArduinoIDE: (URL)
    #endif
    
    • Provide a "Notice" box or something like that above the embedded sketch on the website: (quickly hacked together):
      mysensors-external-lib-note.png
    YveauxY 1 Reply Last reply
    1
    • BearWithBeardB BearWithBeard

      The URL is in an inline code HTML element and the CSS rule #article code {white-space: nowrap;} prevents long lines from breaking the layout, causing the (visual) truncation depending on the window size. Double-clicking or marking the whole line with the cursor gives you the full link, but you can't simply click on it to open the URL. A hyperlink would wrap (and be clickable).

      mysensors-code-link-wrap.png

      I assume this is only a temporary solution. It might be better though to replace it with a hyperlink tag or better, embed it like the external measurement example in the section below it (once it's added to the examples repo).

      @mfalkvidd Okay, understood. Managing external libraries in ArduinoIDE projects can be cumbersome and confusing. Just brainstorming here - two ways of clarifying that external libraries are required in a provided example sketch:

      • After including an external library, add a conditional #error preprocessor directive that checks if the library-specific header guard is defined. This doesn't address backwards compatibility issues though:
      #include <Vcc.h>
      #ifndef VCC_H
      #error You need to install Arduino_VCC version 1.x (URL)
      #error How to install libraries in ArduinoIDE: (URL)
      #endif
      
      • Provide a "Notice" box or something like that above the embedded sketch on the website: (quickly hacked together):
        mysensors-external-lib-note.png
      YveauxY Offline
      YveauxY Offline
      Yveaux
      Mod
      wrote on last edited by
      #13

      @BearWithBeard said in Measuring battery voltage, which way is best?:

      This doesn't address backwards compatibility issues though

      Nor forward compatibility, as "#pragma once" is much more common these days than using an include guard

      http://yveaux.blogspot.nl

      1 Reply Last reply
      0
      • V Offline
        V Offline
        virtualmkr
        wrote on last edited by
        #14

        Hello all, may be I did not get the point of this thread, but a very similar code to measure the AVR CPU voltage is already part of the MySensors library: MyHwAVR.cpp#L289

        I use it in some of my PIR sensors and it works fine. Simply call hwCPUVoltage() to get it.
        This is from my code:

        void sendBatteryLevel()
        {
          // This calls the internal voltage measurement
          uint16_t voltage = hwCPUVoltage(); 
        
          // Li AAA Cell Voltage range: discharged - full 2.6V - 3.0V
          uint16_t batteryPcnt = map(voltage, 2600, 3000, 0, 100);
          batteryPcnt = constrain(batteryPcnt, 0, 100);
        
          // This MySensors function sends the "internal battery info" to the gateway
          sendBatteryLevel(batteryPcnt);
        }
        
        

        BR Immo

        skywatchS 1 Reply Last reply
        4
        • V virtualmkr

          Hello all, may be I did not get the point of this thread, but a very similar code to measure the AVR CPU voltage is already part of the MySensors library: MyHwAVR.cpp#L289

          I use it in some of my PIR sensors and it works fine. Simply call hwCPUVoltage() to get it.
          This is from my code:

          void sendBatteryLevel()
          {
            // This calls the internal voltage measurement
            uint16_t voltage = hwCPUVoltage(); 
          
            // Li AAA Cell Voltage range: discharged - full 2.6V - 3.0V
            uint16_t batteryPcnt = map(voltage, 2600, 3000, 0, 100);
            batteryPcnt = constrain(batteryPcnt, 0, 100);
          
            // This MySensors function sends the "internal battery info" to the gateway
            sendBatteryLevel(batteryPcnt);
          }
          
          

          BR Immo

          skywatchS Offline
          skywatchS Offline
          skywatch
          wrote on last edited by
          #15

          @virtualmkr Thanks - I did not know that - it is really helpful! :)

          The original purpose was that the 'build' section on 'battery power' was missing anything about the 'internal voltmeter' and only mentioned the external components method.

          V 1 Reply Last reply
          0
          • skywatchS skywatch

            @virtualmkr Thanks - I did not know that - it is really helpful! :)

            The original purpose was that the 'build' section on 'battery power' was missing anything about the 'internal voltmeter' and only mentioned the external components method.

            V Offline
            V Offline
            virtualmkr
            wrote on last edited by
            #16

            @skywatch Thank you for clarifying. And nice that you like my implementation :-)

            I also find it very good and helpful for beginners to show the internal battery measurement method on the "Battery Power" page from MySensors. When I started with MySensors I followed the instructions for measuring via analog pin and 2 resistors. The more simple internal measurement I discovered way much later.

            BTW there are some more built in functions, e.g. for the current CPU frequency and the current free heap size. With the MYSController you can query these values from the individual nodes:

            2021-02-19 21_40_28-MYSController 1.0.0beta (build 3316).png

            You need only to add the #define for this functionality in your Node sketch:

            // Enable support for I_DEBUG messages.
            #define MY_SPECIAL_DEBUG
            
            skywatchS 1 Reply Last reply
            2
            • V virtualmkr

              @skywatch Thank you for clarifying. And nice that you like my implementation :-)

              I also find it very good and helpful for beginners to show the internal battery measurement method on the "Battery Power" page from MySensors. When I started with MySensors I followed the instructions for measuring via analog pin and 2 resistors. The more simple internal measurement I discovered way much later.

              BTW there are some more built in functions, e.g. for the current CPU frequency and the current free heap size. With the MYSController you can query these values from the individual nodes:

              2021-02-19 21_40_28-MYSController 1.0.0beta (build 3316).png

              You need only to add the #define for this functionality in your Node sketch:

              // Enable support for I_DEBUG messages.
              #define MY_SPECIAL_DEBUG
              
              skywatchS Offline
              skywatchS Offline
              skywatch
              wrote on last edited by skywatch
              #17

              @virtualmkr Thanks - this is really useful stuff which is 'hidden away' and should really be seen by all coming to mysensors for the first time. I hope @mfalkvidd will find a way to get this into the battery section.

              I modified your implementation a little to better suit my needs, as follows....

              void sendBatteryLevel()
              {
                // This calls the internal voltage measurement and converts to Volts.
                 wait(250);                                        //Allow power lines to settle.
                 float voltage = hwCPUVoltage()/1000; 
                 wdt_reset();
                 batteryPcnt = map(voltage, brown_out_voltage, BattMax, 0, 100);
                //batteryPcnt = constrain(batteryPcnt, 0, 100);
              
                // This MySensors function sends the "internal battery info" to the gateway
                if(batteryPcnt != oldBatteryPcnt){
                sendBatteryLevel(batteryPcnt);
                oldBatteryPcnt = batteryPcnt;
                }
              }
              

              I wanted it all in volts and not mV and also not send unless there is a change in % level to further reduce battery usage. For some reason the 'constrain' function gives a warning in minicore so I leave it out for now.

              The image you posted shows frequency as "cHz". I am not familiar with that term, do you know what it is?

              V 1 Reply Last reply
              0
              • skywatchS skywatch

                @virtualmkr Thanks - this is really useful stuff which is 'hidden away' and should really be seen by all coming to mysensors for the first time. I hope @mfalkvidd will find a way to get this into the battery section.

                I modified your implementation a little to better suit my needs, as follows....

                void sendBatteryLevel()
                {
                  // This calls the internal voltage measurement and converts to Volts.
                   wait(250);                                        //Allow power lines to settle.
                   float voltage = hwCPUVoltage()/1000; 
                   wdt_reset();
                   batteryPcnt = map(voltage, brown_out_voltage, BattMax, 0, 100);
                  //batteryPcnt = constrain(batteryPcnt, 0, 100);
                
                  // This MySensors function sends the "internal battery info" to the gateway
                  if(batteryPcnt != oldBatteryPcnt){
                  sendBatteryLevel(batteryPcnt);
                  oldBatteryPcnt = batteryPcnt;
                  }
                }
                

                I wanted it all in volts and not mV and also not send unless there is a change in % level to further reduce battery usage. For some reason the 'constrain' function gives a warning in minicore so I leave it out for now.

                The image you posted shows frequency as "cHz". I am not familiar with that term, do you know what it is?

                V Offline
                V Offline
                virtualmkr
                wrote on last edited by
                #18

                @skywatch Thank you for the minicore tip. I was not aware of this project.
                Implementation of constrain() in minicore differs from constrain() implementation in the original Arduino core.
                So maybe it is a minicore issue. Or may be your batteryPcnt type is float?
                Neverless one should prevent battery percentage below 0% or above 100% because it makes no much sense.

                "cHz" is actually strange but it means 0.1 x MHz, so for my ESP8266 I get 1600 x 0.1 MHz = 160 MHz:

                2021-02-20 12_32_10-MYSController 1.0.0beta (build 3316).png

                This way the frequency value fits well into uint16_t type.

                skywatchS 1 Reply Last reply
                0
                • V virtualmkr

                  @skywatch Thank you for the minicore tip. I was not aware of this project.
                  Implementation of constrain() in minicore differs from constrain() implementation in the original Arduino core.
                  So maybe it is a minicore issue. Or may be your batteryPcnt type is float?
                  Neverless one should prevent battery percentage below 0% or above 100% because it makes no much sense.

                  "cHz" is actually strange but it means 0.1 x MHz, so for my ESP8266 I get 1600 x 0.1 MHz = 160 MHz:

                  2021-02-20 12_32_10-MYSController 1.0.0beta (build 3316).png

                  This way the frequency value fits well into uint16_t type.

                  skywatchS Offline
                  skywatchS Offline
                  skywatch
                  wrote on last edited by skywatch
                  #19

                  @virtualmkr Thanks for the information, very interesting.

                  My batteryPcnt is an int. The voltage is defined as a float but as I understand it any math between a float and an int will always result in an int, expecially if the variable it is being stored in is an int.

                  cHz! Well I learn something new, so that is good! ;)

                  As for minicore, it does get a mention in the bootloader page on this site and I like it as it is easy to use and I don't need to keep going to the command line or avrdudess all the time, it all works within arduino ide. As a big plus it was upgraded to version 2.1.0 today and the constrain issue has been fixed!

                  1 Reply Last reply
                  0
                  • mfalkviddM Offline
                    mfalkviddM Offline
                    mfalkvidd
                    Mod
                    wrote on last edited by mfalkvidd
                    #20

                    My pull request has now been merged to the MySensors development branch. I have updated the battery page to show the example sketch for internal measurement. Note that the internal measurement method does not work on all supported mcus (not esp8266 for example) but I don't think it matter much since the battery page recommends a Pro Mini which works.

                    Special thanks to @hek for tracking down a tricky display problem with the sketch inclusion, and to @Yveaux, @user2684 and @tekka for feedback on the pull request.

                    skywatchS 1 Reply Last reply
                    1
                    • mfalkviddM mfalkvidd

                      My pull request has now been merged to the MySensors development branch. I have updated the battery page to show the example sketch for internal measurement. Note that the internal measurement method does not work on all supported mcus (not esp8266 for example) but I don't think it matter much since the battery page recommends a Pro Mini which works.

                      Special thanks to @hek for tracking down a tricky display problem with the sketch inclusion, and to @Yveaux, @user2684 and @tekka for feedback on the pull request.

                      skywatchS Offline
                      skywatchS Offline
                      skywatch
                      wrote on last edited by
                      #21

                      @mfalkvidd Good News! :)

                      But I am curious where the "+ 0.5" vomes from in this line.....

                      int batteryPcnt = batteryMillivolts / FULL_BATTERY / 1000.0 * 100 + 0.5;
                      

                      ???

                      zboblamontZ mfalkviddM 2 Replies Last reply
                      0
                      • skywatchS skywatch

                        @mfalkvidd Good News! :)

                        But I am curious where the "+ 0.5" vomes from in this line.....

                        int batteryPcnt = batteryMillivolts / FULL_BATTERY / 1000.0 * 100 + 0.5;
                        

                        ???

                        zboblamontZ Offline
                        zboblamontZ Offline
                        zboblamont
                        wrote on last edited by
                        #22

                        @skywatch Rounding up to the nearest int ?

                        1 Reply Last reply
                        0
                        • skywatchS skywatch

                          @mfalkvidd Good News! :)

                          But I am curious where the "+ 0.5" vomes from in this line.....

                          int batteryPcnt = batteryMillivolts / FULL_BATTERY / 1000.0 * 100 + 0.5;
                          

                          ???

                          mfalkviddM Offline
                          mfalkviddM Offline
                          mfalkvidd
                          Mod
                          wrote on last edited by mfalkvidd
                          #23

                          @skywatch as @zboblamont said, it makes sure we have ”proper” rounding. In C, floating point numbers are always rounded down Ehrn converted to an integer. So 42.8 becomes 42. By adding 0.5, we get the rounding expected by most humans in most cases.

                          To read about different rounding methods, see https://en.wikipedia.org/wiki/Rounding#Rounding_to_the_nearest_integer

                          My personal favorite is called ”banker’s rounding” but I did not use it in this sketch.

                          1 Reply Last reply
                          0
                          • skywatchS Offline
                            skywatchS Offline
                            skywatch
                            wrote on last edited by skywatch
                            #24

                            @zboblamont & @mfalkvidd - Thank you for that. It never occured to me that rounding might need some help. But now it makes logical sense.

                            @mfalkvidd I guess if you used 'bankers rounding' you would always end up with 0.

                            1 Reply Last reply
                            1
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            24

                            Online

                            11.7k

                            Users

                            11.2k

                            Topics

                            113.1k

                            Posts


                            Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • MySensors
                            • OpenHardware.io
                            • Categories
                            • Recent
                            • Tags
                            • Popular