Page 1 of 1
IVT Shunt TFT Display with ESP32 and 3.5" TFT
Posted: Mon Feb 02, 2026 2:34 pm
by Alibro
For anyone out there using the Isabellenhuette shunt this might be helpful.
I wanted to have real time display of voltage, current and power along with SOC so after many hours fighting to make Deep Seek do all the hard work I have something working.
It might not be (it really isn't) perfect or even particularly good but from the small amount of testing I've done it seems to work. Maybe you can use it as the basis of a decent display.
Requirements are:-
1 x 38 pin ESP32 Wroom
https://s.click.aliexpress.com/e/_c45H9pLV
1 x SN65HVD230 CAN transciever
https://s.click.aliexpress.com/e/_c3gFRCKr
1 x TFT display, I used a 3.5"
https://s.click.aliexpress.com/e/_c3O36uVd
I also used a small 5V buck converter connected directly to the 5V pin of the ESP32 but added filters and diodes
https://s.click.aliexpress.com/e/_c3rjjZ11
So here is what you need to do.
1. Install ESP32 support in the Arduino IDE and select it.
2. Install the TFT_eSPI library.
3. Change the User_Setup.h in the TFT_eSPI library to match your TFT display. I have included one here that worked with my setup
4. Connect the display as described in the Readme file.
Re: IVT Shunt TFT Display with ESP32 and 3.5" TFT
Posted: Mon Feb 02, 2026 2:44 pm
by jrbe
Nice! Do you have a link to the code if you're willing to share?
Re: IVT Shunt TFT Display with ESP32 and 3.5" TFT
Posted: Mon Feb 02, 2026 4:29 pm
by Alibro
jrbe wrote: ↑Mon Feb 02, 2026 2:44 pm
Nice! Do you have a link to the code if you're willing to share?
I got called away before I could finish the last post.
I'll try to complete it with files in the next day or two
Re: IVT Shunt TFT Display with ESP32 and 3.5" TFT
Posted: Tue Feb 03, 2026 4:59 pm
by Alibro
Sorry for the delay getting back guys, my mum had a nasty fall yesterday and broke her hip. I was posting here when I got the call.
She is comfortable in hospital and it's my sisters turn to visit so I have a bit of free time.
Here is the ESP32 code I used
These are the connections to the ESP32
This is the Usersetup.h file with the changes from default. This needs to go in the TFT_eSPI library
So the TFT_eSPI is the only library you need for this to work.
If anyone wants to start from basics this is first successful attempt at reading the IVT shunt for an Arduino Uno R4 WiFi using a transciever on pins 10 and 13. It will display the voltage and current in the serial console
Code: Select all
// IVT-S meter using Arduino Uno R4 WiFi built-in CAN controller
// Reads both Current and Voltage from IVT-S sensor
#include <Arduino_CAN.h>
// IVT-S CAN message IDs (check your documentation to confirm)
static const uint32_t IVT_CURRENT_ID = 0x521; // Current message ID
static const uint32_t IVT_VOLTAGE_ID = 0x522; // Voltage message ID (common alternative: 0x522)
// Variables to store readings
int32_t current_ma = 0;
int32_t voltage_mv = 0;
unsigned long lastUpdate = 0;
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Initializing CAN at 500kbps...");
if (!CAN.begin(CanBitRate::BR_500k)) {
Serial.println("Failed to initialize built-in CAN controller!");
while (1) delay(1000);
}
Serial.println("Built-in CAN controller initialized at 500kbps");
Serial.println("Waiting for IVT-S Current and Voltage data...");
Serial.println("---------------------------------------------");
}
void loop() {
if (CAN.available()) {
CanMsg const msg = CAN.read();
if (msg.id == IVT_CURRENT_ID && msg.data_length >= 6) {
// Parse current value (bytes 2-5 as little-endian signed int32)
current_ma = (int32_t)(
msg.data[2] |
(msg.data[3] << 8) |
(msg.data[4] << 16) |
(msg.data[5] << 24)
);
lastUpdate = millis();
}
else if (msg.id == IVT_VOLTAGE_ID && msg.data_length >= 6) {
// Parse voltage value (bytes 2-5 as little-endian signed int32)
// Voltage is typically in millivolts (mV)
voltage_mv = (int32_t)(
msg.data[2] |
(msg.data[3] << 8) |
(msg.data[4] << 16) |
(msg.data[5] << 24)
);
lastUpdate = millis();
// Display both current and voltage when voltage is updated
displayReadings();
}
}
// Display readings every second even if no new data
if (millis() - lastUpdate >= 1000) {
displayReadings();
lastUpdate = millis();
}
delay(10);
}
void displayReadings() {
// Convert to more readable units
float current_a = current_ma / 1000.0; // mA to A
float voltage_v = voltage_mv / 1000.0; // mV to V
Serial.print("Current: ");
Serial.print(current_a, 3); // 3 decimal places
Serial.print(" A (");
Serial.print(current_ma);
Serial.print(" mA) | Voltage: ");
Serial.print(voltage_v, 1); // 1 decimal place
Serial.print(" V (");
Serial.print(voltage_mv);
Serial.println(" mV)");
}
As mentioned earlier I am hopeless at writing code so all of this was written by Deep Seek.