1S-6S Battery Voltage Monitor (ROS)
by Duncan Iglesias in Circuits > Sensors
20865 Views, 72 Favorites, 0 Comments
1S-6S Battery Voltage Monitor (ROS)
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).
Materials Required
Materials:
- Arduino Nano
- Perf Board
- Arduino Cable
- 3" Heat Shrink Tubing
- 90 Degree Header Pins
- Variety of Resistors
- 560kΩ x 5
- 470kΩ x 1
- 330kΩ x 1
- 180kΩ x 1
- 150kΩ x 1
- 100kΩ x 1
- 56kΩ x 1
- Bread Board & Pins
Tools:
- Volt Meter
- Soldering Iron
- Solder
- Heat Gun
- Snips
- Knife
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.
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.
Programming the Arduino
This tutorial assumes that you already have ROS installed and running on your system. If not, follow these links to get your system up to date:
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(); nh.advertise(batteryState); // 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) batt_state.power_supply_health = 3; // dead else batt_state.power_supply_health = 1; // good // Publish data to ROSSERIAL. batteryState.publish( &batt_state ); nh.spinOnce(); delay(1000); }
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.
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.
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!