From Dooba Wiki
Revision as of 21:03, 23 September 2020 by Eresse (talk | contribs) (Dangers of LiPo)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
Example LiPo battery (with protection circuit)
Typical LiPo battery for R/C (no protection circuit)


When you want to take your project on the go, not many options are available. If you want to maximize energy density or if you want to be able to recharge easily, LiPo batteries are simply the best choice today.

LiPo batteries come in many different shapes and sizes, but the most important aspect is the number of 'cells'. A typical LiPo cell will produce from around 4.2V when fully charged down to about 2.7V when discharged.

So we can get LiPo battery packs with different voltages by combining more cells. This is very common in the R/C world where big motors often need higher voltages. When dealing with embedded electronics, it is much more common to see single-cell batteries (often called '1S'), since we don't really need such higher voltages.

The capacity of a battery is measured in milliamps per hour (mAh). If a battery contains 500mAh, that means it can deliver a current of 500mA during one hour. That is a current of 1C - one time the capacity. It means it can also supply a current of 250mAh (0.5C) for two hours. If the current is 50mA (0.1C), the battery can last for 10 hours.

These batteries are pretty much everywhere nowadays. They power your smartphone, tablet, laptop computer, headphones, and many more.

Dangers of LiPo

Fact: LiPo batteries are dangerous. They can heat up and burst into flames if handled improperly.

What exactly do we mean by "heat up"? The images below provide some examples:

This battery was not handled properly

While this may be scary (and it should) we still use LiPos everywhere all the time.

If handled properly, LiPo batteries are incredibly useful and can provide consistent power after re-charging for hundreds or even thousands of cycles.

Mostly, this all comes down to three key aspects:

  • thermal - Don't expose the battery to extreme cold / hot (keep it between 0 and 50 deg. C)
  • mechanical - don't puncture, cut, hit, crush or otherwise torture the battery
  • electrical - don't over-draw it (pull too many amps or get it below ~2.7V) and carefully follow the charging curve

The thermal and mechanical parts shouldn't usually be a problem. For the electrical part, there are two things we need to look at:

LiPo battery and protection circuit (separated)
  1. discharging - should not pull more than 1C and should not go below 2.7V
  2. re-charging - should be done according to a precise voltage / current curve

The protection circuit

LiPo batteries can be equipped with a protection circuit which ensures it only operates within allowed thresholds. Most batteries used for embedded electronics feature these protection circuits.

In the R/C world

Because protection circuits effectively limit the current that can be pulled from a battery, those are not suited for high-power applications like R/C vehicles. These simply go without any protection and it's basically up to the user to make sure they don't push the battery beyond its limits (though the vehicle's electronics often provide some assistance).

Keep it safe

We only use batteries with protection circuits here at Dooba, and highly recommend you do the same unless you are very experienced with this technology.


In addition to limiting the discharge, we need to precisely control the voltage and current (amps) in order to correctly and safely charge a battery.

While this precise control could be done by hand or using some arrangement of discrete components, many IC's (integrated circuits) today provide exactly this functionality and are much smaller, cheaper and easier to integrate.

Nomad - LiPo battery management module

The Nomad module

The Nomad is a small LiPo battery management module. It's purpose is to make using LiPo batteries as easy as possible.

Get it in the Dooba Shop!

To do this, it provides the following:

  • charge control (voltage/current curve)
  • charge indicator output
  • clean dual output (5.0V & 3.3V)
  • battery level indicator output
The Nomad module

Basically, you hook a battery to one side of the module and your application to the other side. The module also accepts a 5.0V input to charge the battery - this is usually connected to USB power (for example through the ioNode) to allow charging simply by plugging the USB.

[!] WARNING - make sure the VIN-VUSB jumper on the ioNode is removed when using VIN and VUSB separately! Have a look at ioNode's VIN-VUSB jumper to know more.

The Nomad will provide two stabilized outputs: 5.0V and 3.3V. When the input is present (and the battery is not full), the module will charge the battery at a rate of 100mA.

Attaching the battery

Nomad module with battery attached trough a JST connector

Note: the Nomad module does NOT include a battery, you need to provide one. Any single-cell LiPo with protection circuit (not the kind used for most R/C stuff) of minimum 100mAh will do.

Ebay is a good place to look for LiPo batteries.

We need to attach the battery's positive terminal (RED wire) to the "BAT+" pin of the Nomad, and the battery's negative terminal (BLACK wire) to the "BAT-" pin of the Nomad.

The picture below shows exactly this:


We can either attach the battery wires directly, or use a standard connector (such as JST, JR, or any other). In any case, always watch the polarity! Again, Red wire goes to "BAT+", black wire goes to "BAT-".

Battery wires can be quite fragile. One recommendation if you are having mechanical failures on the battery wires is to add some glue (hot glue or similar) around the solder points to "strengthen" the whole assembly.

Complete power system

Let's use what we saw above to setup an ioNode with a Nomad for a portable project which we can charge via USB.


The wiring for this setup is pretty simple. First, we want the Nomad to provide power to the ioNode, so we need to connect the 5.0V output from the Nomad to the VIN of the ioNode.

Nomad wiring output.gif

Next, we want the ioNode's USB to power the Module for charging the battery, so we need to connect the ioNode's VUSB to the Nomad's VIN.

Whenever the ioNode's USB is plugged to a computer or power source, the module will be able to charge the battery if needed.

Nomad wiring input.gif

Then, we want to be able to monitor the battery's state from our application.

For this, we will need to connect the Nomad's CHARGING indicator output to any digital input (GPIO) on the ioNode.

To determine the current battery level we will also need to connect the Nomad's BAT_LEVEL output to any analog input (ARD) on the ioNode.

Nomad wiring monitoring.gif

You might notice in this example that we used pins P0 and P1 for BAT_LEVEL and CHARGING. While BAT_LEVEL is an analog signal (therefore requiring an analog input pin), CHARGING is a digital signal that may be connected to any GPIO.

We used P1 (which can also serve as analog input) to keep the wires short and the example simple, but we could've used any other pin.

Finally, just like for any digital design, we need to have a common ground between the Nomad module and our ioNode - let's make sure all the grounds are connected together.

Nomad wiring ground.gif

That's it! Below is the final result showing all connections:

Nomad ionode wiring.png


As seen previously, we wired up two signals from the Nomad module to our ioNode:


These allow us to monitor the battery from our code. We can use the 'nomad' library to do just that, so let's start by adding it to our list of dependencies in dfe.conf:

# ...
  - nomad

Now we can initialize the library. As always, we can do this through the substrate or manually from C code. Using the substrate is recommended as it will keep our code shorter and simpler.

Substrate initialization

We can define our Nomad battery module and its wiring in our substrate file:

# Nomad battery module using pins 0 & 1
uses :nomad, name: 'bat0', bat_level_pin: 0, charging_pin: 1

This will create a nomad structure pointer 'bat0' (struct nomad *bat0;).

Manual initialization (without substrate)

We can achieve the same results as above manually from our C code:

 1 #include <nomad/nomad.h>
 3 // Nomad module
 4 struct nomad bat0_data;
 5 struct nomad *bat0;
 7 void main()
 8 {
 9     // Initialize Nomad module (using pins 0 & 1)
10     nomad_init(bat0, 0, 1);
12     // ...
13 }

Reading battery voltage, percentage & charging status

Now that we're all set up, we can actually monitor the battery:

 1 void main()
 2 {
 3     uint16_t v;
 4     uint8_t pct;
 6     // ...
 8     // Get battery voltage (in millivolts)
 9     v = nomad_get_vbat(bat0);
11     // Get battery percentage
12     pct = nomad_get_bat_pct(bat0);
14     // Check charging status
15     if(nomad_is_battery_charging(bat0))    { /* Battery is charging */ }
16     else                                   { /* Battery is NOT charging */ }
18     // ...
19 }