/makita-lxt-protocol

Various notes on how to communicate with Makita 18V batteries

Notes on how to communicate with Makita 18V batteries

Makita LXT 18V batteries feature various types of battery management systems, that keeps track of cell voltage, temperature, state of charge, overload, undervoltage, which can be read out. This data can be read out through the yellow connector on the batteries.

The DC18RC fast charger uses this data connection to figure out the maximum allowed charging current.

The BTC04 likewise uses this data connection to display various battery data.

Most of the information here is the result of reverse enginering the BTC04. The rest is from Martin Jansson's Open Battery Information project.

Electrical connection

Yellow connector

Proprietary 8 pin connector with 2.54 mm pitch. Both genders can be sourced from aliexpress.

Pin Description
1
2 1-Wire data
3
4
5
6 Enable (active high)
7 N/C

Pin 1 is closest to negative battery terminal.

Both pin 2 and 6 are referenced to the negative battery terminal - the rest are probably as well.

Pin 6 must be pulled high (3.3V will do) before and during communication on pin 2. I don't know if it also serves as a open-collector output. It's probably safest to pull up through a 4.7 kiloohm resistor, and it seems to work well enough.

External pull-up on the 1-wire bus on pin 2 must be provided. A 4.7 kiloohm resistor to 3.3V seems to work. Pull-up to 5V should also work.

See also Martin Jansson's Open Battery Information project and this simple hack to use a USB to UART dongle for 1-wire communication.

1-wire protocol

Standard 1-wire timing seems to work well enough.

Every command is preceeded by a 1-wire reset sequence, to which the battery asserts presence.

Commands that begin with cc can alternatively be preceeded by a rom id command and read (send 33, receive 8 bytes) instead of just sending cc.

Example waveform capture

Here's an example of a 1-wire transaction with a BL1850B type 0 battery, using the setup with a USB TTL UART dongle described below. Captured with a Salaea Logic 16 and Sigrok/Pulseview.

Waveform capture of command cc d7 0e 02 with response

The transactions begins with a 1-wire bus reset, where the dongle pulls the line low for 500us.

The battery asserts presence by pulling the bus low from 550us to 650 us.

The command sent from the dongle at 1600 us is cc d7 0e 02 (read absolute temperature).

The response returned from the battery at 5200 us is 9d 0b 06.

Getting started

It's pretty easy to use a cheap USB to TTL UART dongle to hack on the batteries with uart1wire.

Schematic

Supported commands

Different types of batteries support different sets of commands. Most newer batteries seem to be of type 0, which has the biggest command set.

BTC04 has a somewhat convoluted way of figuring out which battery type it's talking to.

Examples with uart1wire

Reading rom id and basic battery information

% ./uart1wire.py /dev/ttyusb0 reset write 33 read 8 write f0 00 read 32
14 0a 12 64 05 05 20 c6
f1 36 b6 c3 18 58 00 00 94 94 40 21 01 80 02 09 43 d0 8e 1b f0 65 00 01 02 02 0e 60 00 40 01 d1

Reading temperature from type 0 battery

Command cc d7 0e 00 02 responds with a 16 bit little endian integer representing absolute temperature in units of 1/10 K, followed by a byte 0x06.

uart1wire supports parsing simple data structures using the standard python struct format strings. Instead of giving a length of 3 bytes to read, we here use a struct format string to describe structure consisting of a little endian short followed by a byte.

% ./uart1wire.py /dev/ttyUSB0 reset write cc d7 0e 00 02 read '<Hb'
2965 6

where 2965 corresponds to 296.5 K = 23.35 °C, and the final 6 means the command succeeded.

Read model string

% ./uart1wire.py /dev/ttyUSB0 reset write cc dc 0c read '16s'           
b'BL1850B\x00\x00\x00\x00\x00\x00\x00\x00\x00'

Here we use the struct format string 16s to let uart1wire interpret the received data as a string of 16 bytes. The model name BL1850B followed by null-padding is printed.