Hello and welcome to our community! Is this your first visit?
Register
Page 1 of 3 123 LastLast
Results 1 to 10 of 30
  1. #1
    Administrator AeroQuad Founder Mikro's Avatar
    Join Date
    Jun 2009
    Posts
    3,238
    Downloads
    4
    Uploads
    7
    Reputation Points (Add)
    9

    New Battery Monitor

    Hey guys, based on Honk's work I implemented a battery monitor class. I did this because I wanted to do it a little different then his CHR6DM implementation.

    The v2.0 shield has a built in voltage divider (divide by 3 using 15k and 7.5k resistors). If you setup the AREF to DEFAULT, it uses 5V as the reference without any additional circuitry.

    There is a diode that protects VIN from USB power if applied, so I measured about a 0.9V drop. I added this back into the math, so when you view the voltage it is the same as should be at the battery itself. I verified this by putting a voltage monitor at the charge plug (the one that I sold at the store). It would report something like 12.1V. Then I used a DMM to measure at the output of the lipo pack itself and verified they were the same (sometimes was 0.1V off). I then left the battery monitor attached, but started viewing the voltage drop through the Configurator. They match, so I'm reasonably confident we have it working OK.

    I set a warning limit to 10V, and the alarm limit to 9.5V (similar to an external low voltage alarm I use). What happens when the warning limit is reached? The quad does a "heartbeat". It will do a tiny drop in altitude once every second, and it will blink the red LED each second too. I remember this from my old X3D-BL and really liked that I had an indication that could be seen in day as well as evening.

    If the alarm limit is reached it does an auto descend. That came from Honk and works EXTREMELY well! I also turn on a buzzer attached to LED out pin 7, but I haven't tested that yet (I lost my Radio Shack buzzer, will have to buy another).

    Thanks Honk for starting this off! I made tiny mods to your code, so could you please tell me if I messed anything up and I'll fix it? Please check here: https://github.com/AeroQuad/AeroQuad...tteryMonitor.h Also, I'm thinking about making the Auto Descent default, since it works very well. Let me know if you object.

    Please note, I should make the warning/alarm limits user definable. They guys here have been making optimizations to the code, so I dont' want to add any new EEPROM storable items yet. I plan to make a new Configurator that will load all params from file, which should eliminate the need to create a default config inside the code. So for now those values will be hardcoded but will be made configurable in a future version.

    If you have any other input, let me know so I can think about it before the next release. But no worries, if after you guys start flying with it and have any other input, we can always roll it into a future release. Thanks!

  2. #2
    Senior Pilot itod's Avatar
    Join Date
    Sep 2010
    Location
    Belgrade, Serbia, Serbia
    Posts
    731
    Downloads
    0
    Uploads
    0
    Reputation Points (Add)
    0
    Quote Originally Posted by Mikro View Post
    Hey guys, based on Honk's work I implemented a battery monitor class.
    Very nice code, clean as a whistle. Glad we are going fast in good direction.

  3. #3
    Administrator Airwolf's Avatar
    Join Date
    Nov 2010
    Location
    Nuremberg, Germany
    Posts
    1,027
    Downloads
    1
    Uploads
    0
    Reputation Points (Add)
    8
    Nice work, but I have a little problem with the code.
    I was able to set up the battery monitor with the Shield v2.0 and now it reads the battery voltage correctly (about 12,3V now, so alarm limit is not reached), but the buzzer is already turned on and the red LED is flashing. Any ideas what is wrong?

    Regards

  4. #4
    AeroQuad Core Software Developer ala42's Avatar
    Join Date
    Sep 2010
    Location
    Germany
    Posts
    1,788
    Downloads
    1
    Uploads
    0
    Reputation Points (Add)
    13
    Insert
    batteryVoltage = readBatteryVoltage(BATTERYPIN);
    at line 40 of BatteryMonitor.h behind batteryStatus = OK;.

  5. #5
    Senior Pilot
    Join Date
    Nov 2010
    Location
    Atlanta, GA
    Posts
    1,798
    Downloads
    0
    Uploads
    0
    Reputation Points (Add)
    0
    Quote Originally Posted by ala42 View Post
    Insert
    batteryVoltage = readBatteryVoltage(BATTERYPIN);
    at line 40 of BatteryMonitor.h behind batteryStatus = OK;.
    ala42, is that a bug that needs to make it into the svn issues list? I suspect so for the APM build. However, this would only work for the APM build/define because there is no readBatteryVoltage() for any other build... on a brief pass thru the code...

    Alan
    Last edited by aadamson; 01-07-2011 at 05:44 PM.

  6. #6
    Administrator Airwolf's Avatar
    Join Date
    Nov 2010
    Location
    Nuremberg, Germany
    Posts
    1,027
    Downloads
    1
    Uploads
    0
    Reputation Points (Add)
    8
    Quote Originally Posted by ala42 View Post
    Insert
    batteryVoltage = readBatteryVoltage(BATTERYPIN);
    at line 40 of BatteryMonitor.h behind batteryStatus = OK;.
    Thanks for your answer, but now it won't compile.

    Error:
    Code:
    AeroQuad.cpp.o: In function `BatteryMonitor':
    /BatteryMonitor.h:38: undefined reference to `vtable for BatteryMonitor'
    /BatteryMonitor.h:38: undefined reference to `vtable for BatteryMonitor'
    /BatteryMonitor.h:42: undefined reference to `BatteryMonitor::readBatteryVoltage(unsigned char)'
    Mentioned part of my code looks like this:
    Code:
    BatteryMonitor(void) { 
        lowVoltageWarning = 10.0; //10.8;
        lowVoltageAlarm = 9.5; //10.2;
        batteryStatus = OK;
        batteryVoltage = readBatteryVoltage(BATTERYPIN);
      }

  7. #7
    AeroQuad Core Software Developer ala42's Avatar
    Join Date
    Sep 2010
    Location
    Germany
    Posts
    1,788
    Downloads
    1
    Uploads
    0
    Reputation Points (Add)
    13
    For a quick fix use
    batteryVoltage = 11.2

  8. #8
    Administrator Airwolf's Avatar
    Join Date
    Nov 2010
    Location
    Nuremberg, Germany
    Posts
    1,027
    Downloads
    1
    Uploads
    0
    Reputation Points (Add)
    8
    That also doesn't help, LED pin 7 is still supplied with voltage.

    I don't know if it's relevant to this problem, but I've inserted a piece of code to power my LEDs connected to pins 1-4:
    Code:
    public: 
      BatteryMonitor_AeroQuad() : BatteryMonitor(){}
    
      void initialize(void) {
        analogReference(DEFAULT);
        pinMode(43, OUTPUT);
        pinMode(44, OUTPUT);
        pinMode(45, OUTPUT);
        pinMode(46, OUTPUT);
        pinMode(49, OUTPUT); // connect a 12V buzzer to pin 49
        digitalWrite(43, HIGH);
        digitalWrite(44, HIGH);
        digitalWrite(45, HIGH);
        digitalWrite(46, HIGH);
        digitalWrite(49, LOW);
        R1 = 15000.0;
        R2 = 7500.0;
        Aref = 4.98;
        diode = 0.83; // measured with DMM
        batteryScaleFactor = ((Aref / 1024.0) * ((R1 + R2) / R2));
        previousTime = millis();
        state = LOW;
      }

  9. #9
    Moderator AeroQuad Technologist Honk's Avatar
    Join Date
    Apr 2010
    Location
    Stockholm
    Posts
    5,442
    Blog Entries
    2
    Downloads
    0
    Uploads
    0
    Reputation Points (Add)
    1
    Why make the resistance a float? Fractions of Ohm's isn't quite needed here I think.

    If the alarm limit is reached it does an auto descend. That came from Honk and works EXTREMELY well!
    Great! To be honest, I'd tested so many other things that I didn't actually turn the AutoDescent on myself, but I saw no problem with it when I coded it. I just thought that was the only thing that would distinct it from any other standalone monitor - flight interaction. I assume you're running with the PWM decreasing method and not the barometer supported method?


    Also, yes, there is some bug here that needs to be sorted out. I'm glad that you kept my values for the APM setup (for any other APM user it's also good - just have to add a 3k3 resistor to it) and the calculation in whole so that there are no secret factor number which the user will have to calculate himself if other resistors/circumstances are wanted. I also like that analogReference is set individually for each hardware setup. The APM for example got a very good source of voltage reference so I wanna use that.

    But as said, there is a minor bug. In my case, if defining for ArduCopter, the LED(s) are constantly on no matter what voltage is measured. I'll probably find that bug if no one else does before me.

    The bug in the APM case (original code) was that this would either have to be a global or as Ala42 mentioned static:
    static byte batteryCounter=0;
    But it seems fixed now.


    Another thing though: I see that you made another scheme for the autoDescent. In my code I made it descend slowly in first warning, and faster in second warning as the frequency of alert is increased. You instead made it jump between -75/0 in first warning and constant descent in second warning.
    Which of these two works the best? I suppose your scheme alerts the user more, while mine could be interpreted as an annoying thing that only makes you raise the throttle manually?

    I think whatever platform you use, the same scheme/logic should be used. So that logic should be shared by both current (and the ones to come) platform usages. So it can be put in the parent class I think?


    Also no software smoothing should occur! Takes space and execution time (marginally I expect?) which is unuseful. If you want it to be smoother, use a 100nF capacitor on the analog port (one lead to analog0 and one lead to ground). But I would rather want no filtering at all because then it allows good and precise monitoring of battery voltage in specific times in the process of which useful graphs can be made, and even throttle can be regulated better with help of this, since when you're throttling up, the monitor should see fast drops of battery voltage.

    Furthermore, fast achieved battery voltage data (main battery going to the ESC's) can be used onboard to actually save energy! Evening out voltage drops by means of regulating throttle should save some % of flight times!

    It could also apart from saving energy when hover is wanted, help out with more stable hover as Ziojos has been talking about. He however made a manual discreet calculation only to match his battery/setup, but this can be made so it fits everyone's platform.
    Last edited by Honk; 01-07-2011 at 08:06 PM.
    Smart people don't need a signature.
    http://thechive.files.wordpress.com/...rd-signs-3.jpg

  10. #10
    Senior Pilot wilafau's Avatar
    Join Date
    Apr 2010
    Posts
    212
    Blog Entries
    3
    Downloads
    0
    Uploads
    0
    Reputation Points (Add)
    0
    @Honk & @Mikro - kudos for your work on this. As requested here are some enhancement ideas:

    1. Decouple response logic from battery threshold crossing logic.

      For users that have custom LEDs, a Buzzer, power drawing accessories, etc. the actions taken on battery WARNING and ALARM threshold crossings might be different than what is included in the stock code today.

      How about adding a setEventCallBack(&function(byte level)); method to the BatteryMonitor base class.

      For stock users, the instantiation of a BatteryMonitor derivitive class would automatically register a builtin function containing logic for the WARNING and ALARM levels that perform the LED & autodecent behavior that is current in todays code.

      For advanced users who wish to provide customized actions to these events, at setup they simply call setEventCallBack with the address of the function they want called and it will be stored overriding the default function address loaded at instantiation. When the callback is invoked at each threshold crossing, the current threshold level is passed in allowing the function to perform behavior specific to the current threshold level. This provides for user customization w/o having to touch the BatteryMonitor class or its derivative classes while preserving stock behavior.

    2. Specify Battery PIN option at initialization. For Quads that use a separate battery for the electronics or that have multiple batteries to drive extra motors or improve flight time it would be good to be able to instantiate a BatteryMonitor instance for each battery. This would require different Analog input pins for each.

    3. Battery Scale Factor as an initialization option. This probably falls into the classification of coders preference. There are many reasons this scale factor might vary from quad to quad (mine does). You could either create a new derived class with a custom scale factor which requires changing code in several places (e.g. BatteryMonitor.h & AeroQuad.pde) or the Scale factor could be passed as a parameter to the initialization function. This latter approach allows the generic class to be used minimizing collateral code changes. The BatteryScaleFactor equation could easily be a compile time computation using #defines rather than a runtime computation as all the elements of the equation are essentially constants.


 
Page 1 of 3 123 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •