Hi all, On popular request, here's a short tutorial on how to make a low battery warning on my hexa with blinking leds, as you can see at the end of the following video :
EDIT : The software changes in this blog are now outdated and not necessary anymore. For the new software see my new blog with much more possibilities (without using the relay) : U4eake's showleds, arming and low battery warning leds
Furthermore I'll use this as a reminder on what to change in my code when new versions come out :-)
First I'll give proper credit where credit is due, this code was originally written by Bill Sanford and posted on rcgroups here : Bill Sanfords running lights. They are originally intended to be run with a brushed esc, so they can pulsate.
I never found an explanation on the 'attraction mode' leds on standard arducopters, so I modified Bill's code it a little and used the onboard relay to drive my hobbyking 12V leds : http://www.hobbyking.com/hobbyking/store/__8941__Turnigy_High_Density_R_C_LED_Flexible_Strip_Red_1mtr_.html
I have a lot of them, so they draw much more current then the outputs of the APM can provide, but the relay has no problem with it.
General principle :
I have the leds setup as follows : on arming motors, the leds go on, indicating the copter is armed. On disarming they go out.
When battery voltage reaches 10.6V the leds start blinking slowly (2 Hz). From experimenting I know that I now have about 1 min of flighttime left with my battery. You may need to experiment yourself to find out how much you have left.
When voltage goes down to 9.9V, it's really time to land (about 15s left) and the leds start blinking rapidly (5hz). This is also the time when the copter will go into RTL, unless you modify the code (will get to that later on, see software, point 3. event.pde)
Hardware :
First the hardware. I soldered a 3S balancing connector to the relay ports of the IMU as shown in the pictures. Yellow wire goes to pin AN0 on the imu. Red wire goed to middle pin of relay.
PAY ATTENTION : on the 3S connector, swap the black and yellow wires if you use standard 3S balancing connectors !!! Standard 3S balancing connectors have the black wire on the rightside end in the picture below. On the imu however, the third pin is ground and the rightmost pin is AN0 which should be connected to +12V. So swap the wires if you're using a standard 3S balancing connector or you'll invert polarity and damage your board !
Then on the other side of the imu, solder the ground pin together with relay pin 0 with a solder bridge. Also solder a short wire, connecting the pin AN0 (yellow wire) to the right side relay pin (pin 1).
Now connect Yellow to battery +12V and black to battery minus. Connect red to leds+ en blue to leds-. All leds should be connected in parallel to the red and blue wire. Don't overdo it though, the relay must be able to handle the amps. 60 hobbyking leds (1m) is still fine. If you want more, check ampdraw en relay specifications.
With relay in pos 0, the red wire (led+) is connected to ground, so leds are off.
With relay in pos 1, the red wire (led+) gets fed +12V comming from Yellow wire at AN0.
Furthermore AN0 is constantly connected to +12V from battery so it can monitor battery voltage.
Your hardware changes are now done.
DISCLAIMER : I assume if you do this that you have sufficient knowledge about soldering and electronics. Even though I tried to explain as best as I could, I take NO responsability if you destroy your board doing this. Do this at your own risk !
Software : These changes are no longer valid, see my new blog mentioned above for recent code !
You'll need to make the following modifications the the firmware and then compile and upload with arduino.
1. In ArduCopterMega.pde
Find the medium_loop() function and in it find case 4. There is a call to the read_battery() function there.
Insert a call to handle_relay_lights() right after the read_battery() call. See red text below.
// This case controls the slow loop
//---------------------------------
case 4:
loop_step = 5;
medium_loopCounter = 0;
delta_ms_medium_loop = millis() - medium_loopTimer;medium_loopTimer = millis();
if (g.battery_monitoring != 0){
read_battery();
handle_relay_lights();
}
ArduCopterMega.pde is now ready. Don't forget to save it !
2. APM_config.h
Add the following code :
#ifndef BATTERY_EVENT
# define BATTERY_EVENT ENABLED
#endif
#ifndef LOW_VOLTAGE# define LOW_VOLTAGE 9.9
#endif
#ifndef MID_VOLTAGE# define MID_VOLTAGE 10.6
#endif
#ifndef VOLT_DIV_RATIO# define VOLT_DIV_RATIO 3.33
#endif
#ifndef INPUT_VOLTAGE# define INPUT_VOLTAGE 5.26
#endif
// global variables for motor leds and battery monitoring through onboard relay
int rl_state = 0 ; // this global variable is used to save the on/off state of the relay
int rl_counter = 0 ; // this global variable is used for the flash rate timer
I know the variables should probably be defined in parameters.h but upto now I've been too lazy to do so... If you want to, pls do so, but bear in mind that it's an extra file to modify each time a new firmware comes out.
That concludes the APM_config.h modifications. MID_VOLTAGE is when the lights start flashing slowly, LOW_VOLTAGE is when they flash rapidly and when copter goes into RTL.
You may have to experiment a little to find the right values for you. See also the wiki about battery monitoring.
3. Events.pde As of version 2.0.38 this step is already implemented in Events.pde, no need to change it.
Since I now have leds to warn me when battery gets low, I don't want the copter to unexpectedly go into RTL cause my leds have been blinking and I didn't land in time. One time when I was testing this, hoovering low with blinking lights, my copter suddenly took of and flew into the hedge. Luckily I wasn't in between.
So I only want the copter to go into RTL when he's flying on an automatic mode (auto, loiter), not when I'm in control.
Find the line void low_battery_event(void) in the event.pde file.
Change the whole function to look like this (red text changed) :
void low_battery_event(void)
{
gcs.send_text_P(SEVERITY_HIGH,PSTR("Low Battery!"));
if (control_mode > ALT_HOLD) { set_mode(RTL); }
}
I am thinking hard if it wouldn't be better (if possible) to change it into set_mode(Land); to have the copter land on an empty battery instead of attempting to get home with no juice left (which will probably end in disaster if the copter is more then 15sec away from home)
4. RunningLights.pde
Add the file RunningLights.pde to the directory where ArduCopterMega.pde is located. This is a new file to add. You can download it below.
That's it !!! Compile and upload with arduino, enable battery monitoring to battery volts in setup (type setup in CLI and then battery 3) or choose battery volts in mission planner -> hardware setup -> monitor.
Enjoy and feel free to ask questions !
Comments
I've tried this again now with v2.5 and I still cant get it to work. Please help???
Cheers Chris!
We'll support this in the next release. The dev team is on it.
In file included from /config_channels.h:20,
from ArduCopter.cpp:89:
APM_Config.h:108: error: redefinition of 'int rl_state'
APM_Config.h:108: error: 'int rl_state' previously defined here
APM_Config.h:109: error: redefinition of 'int rl_counter'
APM_Config.h:109: error: 'int rl_counter' previously defined here
Im now getting errors again with 2.4.
Anybody else perhaps got it working?
Got it to work on 2.3!
After my step 4 find & replace "battery_voltage" with "battery_voltage1" in "RunningLights.pde"...
Anyone get this working under 2.3?, Im getting compile errors, where Ive followed the same process thats worked for me before which whats exactly in the previous post
I managed to get this working with v2.2 and the following steps:
1. Add "handle_relay_lights();" to "ArduCopter.pde" as mentioned in step 1.
2. Adding the code to "APM_config.h" as mentioned in step 2.
3. Copy "RunningLights.pde" to Arduino Sketchbook folder where "ArduCopter.pde" is located.
4. Then I had to open "RunningLights.pde" and change every "relay_on" / "relay_off" to "relay.on" / "relay.off".
5. Lastly I had to verify & compile it using "arduino-0022-relaxpatch.zip" as the other one gave errors...
Works like a dream, thank you very much for the knowledge...
u4eake, got it sorted, just applied the tweak you suggest on rcgroups with changing the relay_ to relay., will test in the next few days
I love the relay option as Im using quite a few LED's