SOC Display

State of Charge % display for 2011-2012 Nissan Leafs

1 May 2021 - showing the 1.54 inch OLED

The first generation Leafs did not show the battery State of Charge accurately on the dash. There's the 12 blue bars on the right by the range estimate but that's all. After 2012 they added a SOC% feature to the main dash. This project replicates that feature.

Most people just use the LeafSpy app on a phone to address this shortcoming. In my case the phone I was using stopped connecting to the Bluetooth dongle I had. I also didn't like faffing about with a phone to get this basic information. The phone needs to be mounted on the dash, it needs to be kept charged, and the user interface on LeafSpy isn't great.

So my goal is to have a SOC display integrated into the dash with no extra fiddling about. It should just turn on when the car does and require zero effort on my part.

7 November 2019

This project is based on the CANa Display for Nissan LEAF project which is beautifully simple and straightforward. All I've done is change the code to make it work with a nice OLED display that will fit inside the eyebrow dash. It is powered by the OBD2 port in such a way that it only works when the car is turned on. [Note: the dongles that are used with LeafSpy run 24/7 unless you manually turn them off - which is a security risk.]

[Note: the SOC figure shown on this display is the same as is shown on LeafSpy, which is slightly different from that shown on the dash of the 2013 Leaf! This project displays raw SOC as reported by the EV-Can bus. In my case when I do a full charge it displays 94.8%. Whereas a 2013 Leaf (and newer) will adjust the SOC displayed so that it shows 100% after a full charge - even if you've lost battery capacity. This means you can't see the slow battery degradation reflected in the stock SOC% figure, but you can on the display from this project.]

Parts list

  1. 10-16V to 5V DC-DC step down Buck converter
  2. NiRen MCP2515_CAN bus board 8MHz
  3. Arduino Pro Micro, 5V/16MHz or Arduino Pro Mini 328, 5V/16MHz
  4. 1.30 inch OLED display 128x64 pixel monochrome OLED display
  5. OBD2 plug (male)
  6. 7-way ribbon cable
  7. 40 Pin 2.54 mm Right Angle Single Row Pin Header Male
  8. Dupont-style jumper wires
  9. a plastic box to house the electronic bits (I 3d printed one)


Note: these links are to Aliexpress - if you want the items to arrive faster search for similar items on Amazon, EBay, TradeMe, Banggood, etc.

Circuit description

Power for the system is provided from the OBD2 port - pin 4 (ground) and pin 8 (switched +12 from battery). Note pin 8 is a switched +12 on the Leaf. The OBD2 standard power is on pin 16 - but it's always on 24/7.

The power goes straight into a step down module that provides 5V for everything; the MCP2515_CAN, the Arduino Pro Mini and the OLED display.

The Leaf EV-CAN signals come via OBD2 pins 12 and 13. The OBD2 standard CAN bus signals are on pins 6 and 14 - which, in the case of the Leaf gives the Car-CAN bus.

The EV-CAN signals go into the MCP2515_CAN module - which is connected to the Arduino via 5-wire SPI.

Software and STL files

You will need some or all of:

I've also got some STL files on Github for a 3D printed frame to hold 0.96, 1.30 and .54 inch OLED 128x64 OLED displays. You can just frame it with black electrical tape but the 3D printed frame holds it in position better.

DisplayDriver chipArduino codeSTL file
0.96 inch OLED 128x64 SPI bsSSD1306YesYes
1.3 inch OLED 128x64 SPI busSH1106YesYes
1.54 inch OLED 128x64 SPI busSSD1306YesYes

And that's about it. I'm assuming you already know how to get code onto the Arduino.


I chose to install the OLED display over the top of the efficiency trees on the Leaf's "eyebrow" dash. The trees don't serve a critical function so it's no great loss. I stuck a piece of wide black electrical tape over the trees, then used double sided tape to stick the OLED display onto the black tape. (Note: electrical tape is usually easy to remove so you could remove all this if you needed to.)

To install the display inside the dash you'll need to remove the dash and unclip the clear plastic front. See Nissan Leaf Instrument Cluster Removal for an explanation of how to remove the dash.

I also used a craft knife to trim 1mm off edge of the dash to allow the 7-wire ribbon cable to exit cleanly. Clip the dash front back on thread the ribbon cable down past the lower dash.

Next you'll want to remove the lower dash panel, see Nissan Leaf 020 - ETC replacement options. Once that's open you can attach the OLED ribbon to the Arduino and zip-tie the electronic modules (in a plastic box maybe) somewhere where they won't rattle and then connect the OBD2 plug to the socket.

Some pictures to help:

The eye brow dash removed and separated into three parts (they just unclip apart)

Wide black electrical tape over the trees part of the display - try to avoid including any dust particles, or you'll get bumps like I did.

0.96 inch display mountain inside 3D printed frame. Held in place with double sided tape. I also cut out a small segment of the dash edging to let the wires pop out.

Clip the dash back to together and plug the display into a 60 cm long extension cable. Use whatever connectors you can find. Ideally they should clip together so they can't just wiggle loose.

Feed the extension cable down past the steering column and put the dash back in place.

In a right-hand drive Leaf partially remove the right knee panel beside/below the steering column to find your extension cable.

Plug the OBD2 plug in and carefully throw the Arduino and bits in there somewhere and slap the panel back in place. (Or you could spend more time and do a tidy job.)

Turn the car on and enjoy the extra info.

Further reading

I hope you found this helpful.

Cheers, Paul


  • DONE - Swap for 1.3 inch OLED display (still 128 x 64 pixels but larger pixels so easier to see from the drivers seat distance
  • DONE - Remove start up screens. The CAN connection error page should stay on forever though.
  • DONE - Rename variables in code so that rawGids = Gids value from EV-Can and rawSOC = SOC value from EV-Can (currently the variable for Gids is called "Soc")
  • DONE - Only start displaying numbers once they have been loaded from the CAN module , Michelle looked at the display when she started the car and saw it was zero, so assumed it was broken and therefore did not look at it again. To avoid this user confusion it’s best not to show zeros during the loading period. [So only display digits when they are do not equal zero (if !=0 then display)]
  • DONE - Low Gids mode (below 25 Gids = Very Low Battery Warning)
    • Invert screen pixels
    • Force lower/secondary info line to show Gids and Gids-8 in brackets (Turtle mode occurs at 6-8 Gids)
  • DONE - Low SOC mode - when Gids goes below 25 (ie, Very Low Battery Level Warning)
    • DONE - invert display pixels
    • DONE - indicate Gids turtle, and in brackets () indicate how many Gids till turtle mode [assuming Turtle mode hits at 8 Gids)]
    • DISREGARD - show SOC to 2 decimal places [even though the SOC can be presented to two decimal places it's not accurate enough to justify that level of precision. Sometimes vagueness is more truthful.]
  • DONE - show regen kW whenever kW is below -1. But then I changed my mind and removed it. A bit too unnecessary.
  • DONE. Have my SOC be based on the raw SOC from the EV-CAN bus initially... at least until I receive the Gids data. The raw SOC number is fed onto the CAN bus every 100 ms, whereas Gids is 500 ms. So my CAN receiver usually sees a SOC message well before a Gids message comes along.
  • Can I get my SOC% at the top end to match with SOC% targets.
  • What about a high temp mode - for when the temp goes above 50 degrees C?
    • show highest temp from battery pack
  • DONE - Set km per kWh via the Climate controls
  • DONE - Set Max Gids automatically. Write the initial Gids reading into EEPROM for 60 car starts. Then use the highest value as Max Gids. So Max Gids will = the highest Gids value over the last 60 car starts (roughly 20 to 30 days). This scheme assumes you charge to 100% once a week.


Here's the first version with the 0.96 inch OLED 128x96 display oriented in normal "landscape" mode:

This version also used black electrical tape to hold the display in place - which works surprisingly well. The 3D printed frame looks more professional though.


  • Theoretical Max Gids: 281 Gids (In a "24" kWH 2011/2012 model Leaf)
  • My Max Gids: 235 Gids Oct? 2019 (In my 17 kWH 2011 model Leaf)
  • My Max Gids: 220 Gids Jul 2020 (mid -winter)
  • Low Bat Warning: 49 Gids (Range starts flashing)
  • Very Low Bat Warning: 24 Gids {Range shows three dashes)
  • Turtle: somewhere between 4 and 8 Gids
  • Car stops: when lowest cell voltage drops below some 3.? Volts

Theoretically 1 Gid = 80 Wh but others say 74.73 Wh. I'm currently using 1 Gid = 75 Wh.

  • Discharge Low Battery Warning: 3.77V
  • Discharge Very Low Battery Warning: 3.625V
  • Discharge Turtle Mode (Protect): 3.22V
  • Discharge Dead (Shutdown): 3.20V
  • Charge Termination: 4.10V (Dala has worked out how to increase the upper limit to 4.20V using the Muxsan CAN bridge. This would add another 1-2 kWh!, although you wouldn't want to charge that high every day.)

27 Aug 2020 tweaks and updates

  • changed page switching code to count millis so that I can implement long and short press functions. Short press now used for scrolling between "pages" and long press used to reset the arduino
  • added a slide switch (pulls digital pin 8 low when "on", uses internal pull up for "off") on my motherboard to toggle "testing mode" on/off. In testing mode I provide a artificial value for rawGids. This lets me fiddle with design elements away from the car.
  • added a potentiometer (to Arduino pin A1) to allow me to adjust the value of my artificial rawGids when testing/fiddling.

23 July 2020

I drove the car down to 0% SOC on my display tonight. My display shows "8 (0) Gids" - the number in brackets() is Gids minus 8 which means you hit turtle mode when that number reaches zero]. LeafSpy said 7.4% SOC. Given that Turtle mode hits at 6-8 Gids it's misleading for LeafSpy (and therefore the car's MCU) to say 7.6% SOC It may be accurate but that's pretty useless if the car drops in to turtle mode at that point. I prefer to show 0% SOC at the point where you can no longer drive the car normally - ie, you're at 0% usable charge.

The big downside of my usable SOC% formula is that it does not line up with the SOC targets produced by plans. And then there's the SOC shown on fast chargers - which seems to be calculated independently as well. The upshot all that is if I want to drive several hundred kms using a plan from - it'll say "Charge here to 87%". Then I tell the fast charger to charge to "Max" and it'll indicate it's SOC, which doesn't match my SOC, or the LeafSpy SOC! Currently I take whichever is the highest and cross my fingers.

Attach:LeafSOCdisplay_0SOC-360x265.jpg Δ|0% SOC and 9 (1) Gids. Note: the number in the bracket shows how many Gids till Turtle mode is about to hit.

Attach:Leafspy-20200723-360x640.jpg Δ|Leafspy indicates 7.4% (and a couple of weaker cells).

12 April 2021

To convert a bitmap image (like the battery "image") to an XMB file for the Arduino code I used:

  • Microsoft Paint to create a monochrome BMP image
  • to create an XBM file
  • opened the XBM in Programmers Notepad then copy-n-pasted that into the Arduino code

1 May 2021

1 May 2021

I'm using a larger 1.54 inch OLED display now ( with the display separated from it's backing board, which is now dangling outside the dash housing. It works surprisingly well. Looks great too. I've ordered a 1.3 inch OLED display and will try that to see if it fits more elegantly.

As you can see I've shifted the prime focus of this to be showing the Range. Now the SOC% and kWh are secondary elements.

My rationale for this change went like this: I wanted the SOC% display because it gave me more info to better guess the Range. But... now my range estimator is working so much better, that the SOC% info is less important now.

Now that my has turned out so well I don't really need the SOC% at all - so I might (a) go back to the smaller 0.96 inch OLED display and just show the battery SOC%, or (b) remove it completely.

One of the negatives of this system is the paging code seems to clash with reading the CAN bas so that it can take ages to get the first reading. I may not have the motivation to fix that - given that the Range display does not have page switching and therefore starts up with no delay.

12 May 2021

I finally managed to get a 1.30 inch OLED display installed. This is by far the best solution. It's the biggest OLED I've found that fits (it's a tight fit) into the dash space without having to resort to separating the OLED unit from it's backing board (as I had to with the 1.54 inch display).

The 1.30 inch display is also large enough that it's still easy to read the smaller font info. The perfect balance.

Page last modified on June 06, 2021, at 02:30 am
Powered by PmWiki