# 1S-6S Battery Voltage Monitor (ROS)

6,082

58

8

The ability to remotely monitor the health of a battery provides the user with the convenience of knowing when it is time to bring their drone back for recharging. Currently, there are devices on the market such as the Hobby King LiPo Alarm or the more common 3DR Power Module used for drones/UAVs. However, neither product allows for real time monitoring of individual cell health over a serial connection. Not to mention that the 3DR PM cannot handle more than a 4S battery. This project will show how to construct a serial enabled power monitoring system that publishes messages over rosserial to a ROS master.

Note: This chip can be expanded to an 18S Cell LiPo battery by using three 8:1 analog multiplexers (MAX4617).

### Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

## Step 1: Materials Required

Materials:

Tools:

• Volt Meter
• Soldering Iron
• Solder
• Heat Gun
• Snips
• Knife

## Step 2: Understanding the Circuit

Since the Arduino analog pins operate in the 0-5V range and the voltage of a Lithium Polymer battery is compounding voltage with respect to ground as you advance pins, we need to use a voltage step down circuit using resistors. The equation for this circuit goes as follows:

Vout = (Vin * R2 ) / ( R1 + R2 )

Where,

Vin --> Supply Voltage

R1 --> Resistor One

R2 --> Resistor Two

Vout --> Scaled Voltage

By adjusting the ratio between R1 and R2 you can control the output voltage. Knowing that each consecutive pin will provide approximately ~3.7V more than the pin before it, you can design for the required voltage inputs to ensure that the Arduino pins will always get the required 0-5V. A demonstration design chart is HERE.

## Step 3: Building & Testing the Circuit

Following the resistor values from the wiring schematic above, plug in the resistors on a bread board so they all share a common ground. Before wiring any of the wires to the Arduino Nano, use the multimeter to check that all the voltages fall within 0-5V. If not, check your circuit and repeat.

## Step 4: Programming the Arduino

Install from Source (Recommended)
Navigate to your ROS package directory (usually called your Sandbox) and create a new package for this project.

```\$ git clone git@github.com:djiglesias/ros-utilities.git
\$ cd ros-utilities/```

Navigate into the new package and clone the project from GitHub or download it HERE.

`\$ cd ros_battery_monitor/\$ make`

That's it! Now let's upload the code to the Arduino. Open ros-utilities/ros_battery_monitor/src/main/main.ino in your Arduino IDE and select the board type and port. Click the check mark to verify that you have all required dependencies and upload to the board!

Install Manually
This code is an adaptation of the Hello World (publisher) example and this post from RC Groups. For this example, the cell_const[] are drawn from the scaling factors on the chart above.

```#include <ros.h>
#include <sensor_msgs/BatteryState.h>

#define K           0.00472199
#define CELLS       6
#define MAX_CELLS   12

double cell_const[MAX_CELLS] =
{
1.0000,
2.1915,
2.6970,
4.1111,
4.7333,
6.6000,
6.6000,
7.8293,
8.4667,
9.2353,
11.0000,
11.0000
};

ros::NodeHandle nh;
sensor_msgs::BatteryState batt_state;
ros::Publisher batteryState("battery_state", &batt_state);

void setup()
{
// Initialize the ROS node.
nh.initNode();

// Populate battery parameters.
batt_state.design_capacity = 2200;      // mAh
batt_state.power_supply_status = 2;     // discharging
batt_state.power_supply_health = 0;     // unknown
batt_state.power_supply_technology = 3; // LiPo
batt_state.present = 1;                 // battery present

batt_state.location = "Crawler";        // unit location
batt_state.serial_number = "ABC_0001";  // unit serial number
batt_state.cell_voltage = new float[CELLS];

}

void loop()
{<br>  // Battery status.
double battVoltage = 0.0;
double prevVoltage = 0.0;

// Populate battery state message.
for (int i = 0; i < CELLS; i++)
{
// Read raw voltage from analog pin.
double cellVoltage = analogRead(i) * K;

// Scale reading to full voltage.
cellVoltage *= cell_const[i];
double tmp = cellVoltage;

// Isolate current cell voltage.
cellVoltage -= prevVoltage;
battVoltage += cellVoltage;
prevVoltage = tmp;

// Set current cell voltage to message.
batt_state.cell_voltage[i] = (float)cellVoltage;

// Check if battery is attached.
if (batt_state.cell_voltage[i] >= 2.0)
batt_state.present = 1;
else
batt_state.present = 0;
}

// Update battery health.
batt_state.voltage = (float)battVoltage;

if (batt_state.voltage > CELLS * 4.2)
batt_state.power_supply_health = 4; // overvoltage
else if (batt_state.voltage < CELLS * 3.0)
else
batt_state.power_supply_health = 1; // good

// Publish data to ROSSERIAL.
batteryState.publish( &batt_state );
nh.spinOnce();
delay(1000);

}```

## Step 5: Reading From the Arduino

Installed from Source
If you install this project from GitHub, then you can run the following command to launch the battery monitor.

```\$ roslaunch ros_battery_monitor battery_monitor.launch &
\$ rostopic echo /battery/info```

Manual Installation

Once the code is uploaded to the Arduino, plug it into your computer (Linux system) without the battery. If not already running, instantiate an instance of ROS master.

`\$ roscore &`

Run the serial_node.py node from the rosserial_python package passing in the appropriate USB port as an argument.

`\$ rosrun rosserial_python serial_node.py /dev/ttyUSB0 &`

If you received errors warning about insufficient permissions, then run the following commands and try again.

```\$ sudo usermod -a -G dialout client
\$ sudo chmod a+rw /dev/ttyUSB0```

Now, to view the incoming data from the Arduino you can simply run the echo command to display all new messages being published on /battery_state.

`\$ rostopic echo /battery/info`

At first, the messages should come in stating 0.00V and Present = False for the battery. Once you plug the battery in, these fields will populate accordingly. For more information on the sensor_msgs::BatteryState, please view the documentation.

Note: I have not included diodes, so if you plug the battery in the wrong way there is a chance you will fry your Arduino and entire computer.

## Step 6: Assembling the Circuit

Once your circuit is confirmed working, you should mount it to a perforation board to make it a more permanent solution. My project has limited space so I made the board as small as I could without making a PCB board. Notice the common ground rail on the underside of the board, this allowed me to keep the board clean and organized.

Note for Improvement:

• Use diodes to make the board polarity protected.
• Use the proper JST socket to prevent short circuiting.

## Step 7: Final Touches

To prevent short circuiting, use 3 inch heat shrink tubing to encase the circuit board. Label the polarity of the pinout accordingly, and cut a hole for the USB socket.

Boom! You are done. Plug it into your ROS Robot and enjoy!

## Recommendations

• ### Internet of Things Class

21,571 Enrolled

## 8 Discussions

Hello, thank you for sharing with as this information. I have a batteri bank from 14s 3,6v. I want to use arduino mega + ethernet shield for monitor (not BMS) my batteri voltage, can you tell me if this is possible using your solution?

Hello, your question is already answered in the first paragraph. Since you're using a Mega you'll have 16 analog pins, so yes this should theoretically work. Also, the calculations for that are already included in Step 2. Good luck.

There's something wrong. If you add all the voltages you'll get arround 80V, with a bridge of 560k/100k this gives more than 14V on the A5 input which won't appreciate !