Since Metabo doesn't make a 12V car charger for their power tool batteries I tried using one designed for RC model batteries by just connecting it directly to the positive and negative terminals of the battery pack.
This seemed to work fine for the smaller batteries (<=4.0Ah) that I had.
However when I tired to charge the 2 large 8.0Ah batteries the charging current never went above ~500mA until the battery shuts off internally after a few minutes.
The only thing that was missing / different during the charging process with the RC charger was the lack of communication between the charger and battery.
This prompted me to look into what exactly the charger does and to try and replicate the communication.
The battery has 5 pins in total that are helpfully labeled as well.
| Pin | Discription |
|---|---|
| - | Battery negative |
| T- | Temperature sensor negative |
| T+ | Temperature sensor positive |
| D | Data Pin, bidirectional uart, 2400 baud, 18N1, 5V |
| + | Battery positive |
The only pins we care about are the positive and negative battery terminals and the data pin.
It would be ideal to monitor the battery temperature during charging as well but since the charging current in my case is limited to less than 1C (5A for 8Ah battery since that’s all my charger can do) I decided to ignore that.
The data pin is a bidirectional UART (the same pin for TX and RX) running at 2400 baud and using 5V logic levels.
Since the microcontroller I picked only uses 3.3V logic levels and the battery itself doesn’t have an internal "pull up" I decided to try my luck with that.
As it turns out that works just fine as well.
The protocol is rather simple. 4 bytes in, 4 bytes out. Nothing more, nothing less.
Example using the "cell layout" command:
Command:
| Value | Description | Note |
|---|---|---|
| 0x04 | Command Id | Cell layout |
| 0x00 | Value byte 1 | |
| 0x00 | Value byte 2 | |
| 0xFC | Checksum |
Response:
| Value | Description | Note |
|---|---|---|
| 0x04 | Command Id | Cell layout |
| 0x03 | Value byte 1 | Unknown |
| 0x51 | Value byte 2 | 5 = 5 cells series 1 = 1 cells in parallel |
| 0xA8 | Checksum |
For all messages that I was able to observe the charger always sent an empty message so I’m not sure if anything can be done by sending values to the battery.
The checksum is calculated using an 8 bit unsigned integer.
This is important since the calculation uses the underflow of this datatype.
Example using the response message from above:
uint8_t checksum = 0;
checksum -= 0x04; // Command Id
checksum -= 0x03; // Value 1
checksum -= 0x51; // Value 2
printf("0x%02X", checksum);0xA8
The communication that happens between the battery and the charger (SC 30 in my tests) is fortunately pretty basic.
In total there are 11 different messages of which 2 are continuously repeated during the entire charging process.
There is no logic or dependence of messages on each other of any kind that I was able to observe.
All messages function completely independently and only exchange the 2 bytes of data.
I also wasn’t able to observe any changes in the values between different recorded transactions.
| Message Id | Purpose |
|---|---|
| 0x04 | Get cell layout |
| 0x80 | Keep alive |
| 0x08 | Unknown, Reponse is the same for all tested batteries |
| 0x0A | Unknown, Reponse is the same for all tested batteries |
| 0x0C | Unknown, Reponse is the same for all tested batteries |
| 0x0E | Something related to battery capacity |
| 0x10 | Something related to battery capacity |
| 0x12 | Something related to battery capacity |
| 0x14 | Something related to battery capacity |
| 0x16 | Might indicate manufacturing country |
| 0x30 | Unique for each battery Repeated alternately with keep alive during charging |
When the battery is first connected to the charger the charger will poll message 0x04 Get cell layout until a valid response is received.
After that a 0x80 Keep alive is sent.
Following that messages 0x08 to 0x30 from the table above are sent in the order in which they appear in the table.
From then on 0x80 Keep alive and 0x30 are repeated in a burst about once every second during the entire charging process.
Between individual messages I used about 100ms which seems to work fine and gives the battery plenty of time to respond.
I didn’t measure the actual time between messages that the charger uses after arbitrarily picking 100ms and finding that it worked.
Armed with the above knowledge I decided to throw together some code for the Raspberry Pi Pico and build up a simple circuit on the breadboard.
The choice of resistor and diode were again completely arbitrary since it was just what I had laying around on my desk.
The resistor is 3.3k and the diode is some random small signal type glass diode.
With this circuit connected to the battery and the Pi Pico pretending to be the real charger I was finally able to charge the battery properly with the RC charger without it shutting itself off after a while.
To make things more convenient I decided to modify the existing SC 30 charger as follows.
I added 2 banana jacks for connecting the RC charger and installed an internal 230V relay to switch between the external charger connection and the internal one depending on if mains power is connected or not.
The same relay also switches the data pin of the battery between the externally connected Pi Pico and the internal logic of the charger.
Here is the schematic of what I ended up with:
And of course a picture of the whole setup ready to go:


