EPSolar Tracer 2210A Charge Controller + Blynk = Epic Solar Monitor

I am setting up solar panels on a sailboat with a 3215BN. When I am at dock, I use a dc power supply on the PV input. It is easy this way, no need of a battery charger. Since at dock there is power 24/7, I want to use a lower voltage for float charging to save the battery. Eventually I will use LiFepo4 bank also. So when I get power fron the psu, I need to send from esp8266 or else a new value to the CC for float voltage every time I dock in-out. This is my project, just beginning and not much skills in coding… lots of fun to come !!! I will pick into your code guys !!

1 Like

I set the delay to 1.1 seconds, and still have the same issue of the controller randomly becoming unresponsive for hours at a time, especially during times of high solar output.

I’m wondering if it’s a grounding issue. I’m using this adaptor:

Which doesn’t have any pin for ground. Hmm.

I used to get time outs on my set up, A Tracer3215BN, and the usb converter that came with it, using Solar Station Monitor from EPever…
I noticed it only happened when the inverter was on. I have seperated the cables as much as possible, certainly never touching. I also went for a CAT6a, I needed a 15M run.
I have not experienced the problem since. Guess it could have been electrical noise/interferrence.


I started to use my Arduino in earnest, to read my tracer recently, and also found I had lost data, even with my CAT6 cable! Changed the code as below, It reads the register about four times if it gets a 0 response meaning no register read. This has provided about 99% success. The first delay is to give the tracer a moment to settle down, the second one ensures we don’t stay there forever. As you can see it’s to get the status of the tracer. I guess I could make the delay longer if need be. I’m a novice at this coding, so if there are gaping faults, please let me know.

 //void AddressRegistry_3201() ????????????? Charging Status (Read Only)
 //D3-D2 00=No charge, 01/1=Float, 10/2=Boost, 11/3=Equalisation
 started_waiting_at = millis();  //Get start time
result = Tracer_modbus.readInputRegisters(0x3201, 1);
while (!result == 0) {
 delay(50); // give tracer a moment to settle down
result = Tracer_modbus.readInputRegisters(0x3201, 1);
if (millis() - started_waiting_at > 220 ) { // but, if we have waited 220 mls move on.. se how this goes
  //Serial.println("No response received - timeout!");
  break;// and get out of this while loop, otherwise we could be here for ever.
 if (result == Tracer_modbus.ku8MBSuccess)
ChrgStatus = Tracer_modbus.getResponseBuffer(0x00);
ChrgStatus = ChrgStatus >> 2;// shift right 2 places to get bits D3 D2 into D1 D0
ChrgStatus = ChrgStatus & 3; // and it, bit wise with, 0000000000000011, to get just D1 D0, loose th rest
rs485DataReceived = false;
//Serial.println("Fail readInputRegisters(0x3201, 1) ");//take this out later

hi I’m Karthik from India. and I’m new to this Arduino.
I would like to clear one doubt which is somehow closely related to this.
Is it possible the read the rs485 burst data using Arduino?

Well, after troubleshooting this for ages, I finally solved the problem of losing contact with my Tracer 4210a when the sun got high. To recap, the charge controller would stop responding over modbus whenever it was charging above 400 watts or so (I have 600 watts of panels connected to it). And the solution is…

grounding of course.

Can’t believe I didn’t think of it sooner.

Anyway, grounding the modbus cable coming from the charge controller to one of the GPIO ground pins on the Raspberry Pi solved it. That’s pin 7 or 8 from this diagram:



What is the reason you do not recommend, or discourage the MAX485?

It requires a UART RS485 module. I couldn’t get the MAX485 modules to work and ended up ordering a UART RS485 module which worked right away.

1 Like

Hi wrybread,

Wow, do you have your epever connected directly to a raspberry pi? Thats awesome! I was thinking of a round about way to use esp12 and send mqtt messages to the pi. But I can see that we can route the ethernet wire directly and and use this converted and connect it to the pi’s usb. Can you share the driver and code that you have used?

Hi Jamin,
I’m following your instruction to program the ESP8266 mini, everything went smooth. On the Blynk app, the NodeMCU is online but nothing display on screen .

Would you please help me and let me know what I did wrong or am I missing something?

Hi All, I got some conflicts in compiling the Github .ino file. Someone can help me in finding the way ?

I report the errors:

In file included from C:\Users\RPRO01\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc2\libraries\ArduinoOTA\ArduinoOTA.cpp:13:0:

C:\Users\RPRO01\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc2/tools/sdk/include/user_interface.h:657:174: error: declaration of C function ‘int wifi_send_pkt_freedom(uint8**, int, bool)’ conflicts with

int wifi_register_send_pkt_freedom_cb(freedom_outside_cb_t cb); void wifi_unregister_send_pkt_freedom__cb(void); int wifi_send_pkt_freedom(uint8 **buf, int len, bool sys_seq);


In file included from C:\Users\RPRO01\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc2\libraries\ArduinoOTA\ArduinoOTA.cpp:13:0:

C:\Users\RPRO01\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc2/tools/sdk/include/user_interface.h:537:5: error: previous declaration ‘int wifi_send_pkt_freedom(uint8*, int, bool)’ here

int wifi_send_pkt_freedom(uint8 *buf, int len, bool sys_seq);


exit status 1
Error compiling for board Generic ESP8266 Module.

Many thnaks

I’ve been trying for about a week to get this working. I have the EPEver Triron 4210 Charge Controller and I’m using a Raspberry Pi 3. I’m using pins GPIO14(TX), GPIO15(RX), and ground to connect directly to the controller through Ethernet cable. I can’t seem to get this working no matter what I do. Can you lend a hand? I also noticed that there’s a library named MODBUSMASTER I can’t find nowhere, and the ones on Github don’t seem right.

Hmm. Well you’ll definitely need the modbus library:

Or “pip install pymodbus”

And here’s some barebones code to test with:


from pymodbus.client.sync import ModbusSerialClient as ModbusClient

modbus_timeout = .1 # NOTE! This is default 3 seconds. It waits for the timeout before returning I think. Making this .1 works well. The pyepsolar project uses a 1 second timeout.

client = ModbusClient(method = 'rtu', port = '/dev/ttyUSB0', baudrate = 115200, timeout=1)
result = client.read_input_registers(0x3100,6,unit=1)
solarVoltage = float(result.registers[0] / 100.0)
solarCurrent = float(result.registers[1] / 100.0)
batteryVoltage = float(result.registers[4] / 100.0)
chargeCurrent = float(result.registers[5] / 100.0)

print solarVoltage
print solarCurrent
print batteryVoltage
print chargeCurrent

On a sidenote I found the Tracer controller to be very sensitive to grounding issues. Mine would periodically stop responding. Although, oddly, it would always work with the MT50 remote monitoring box, which I think uses the same protocol. I’d solve it for awhile and it would work well, and then just stop responding for awhile. My system was a bit odd though, I have 900 watts of panels and I’m running a propane/ac fridge off AC sometimes (my Pi kicks the fridge over to AC when my 4 Trojan T105 batteries are fully charged). I don’t know if that was a factor.

Eventually someone gave me a very used but still working Morningstar MPPT60 charge controller so I shifted over to that, which has been pretty rock solid. But oof those things are pricey.

1 Like

Finally got it to display the values onto the python shell… Now I need to push those values to Blynk…How do I do that?


1 Like

Thanks so much. So, to be clear: I can just virtual write the results by inserting the python code right into the Blynk code (I’m assuming blink code = python). Sorry for being so N00b, but I’m just getting into this Raspberry Pi world (always been a C++/Object Pascal fanatic)

import time
import os
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
modbus_timeout = .1
client = ModbusClient(method = ‘rtu’,port = ‘/dev/ttyUSB0’,baudrate = 115200, timeout=1)

result2 - client.read_input_registers(

while 1:
result = client.read_input_registers(0x3100,20,unit=1)
result2 = client.read_input_registers(0x3300,15,unit=1)
solarVoltage = float(result.registers[0] /100.0)
solarCurrent = float(result.registers[1]/100.0)
batteryVoltage = float(result.registers[4] /100.0)
chargeCurrent = float(result.registers[5] /100.0)
chargingMode = float(result.registers[19]/100.0)
maxvolts = float(result2.registers[12]/100.0)

#while (solarVoltage > 0):
print ("Solar Voltage ", solarVoltage)
print ("Solar Current ",solarCurrent)
print ("Battery Voltage ",batteryVoltage)
print ("Charge Current ",chargeCurrent)
print ("Load Power ",chargingMode)
print ("KWatts Today ", maxvolts)

    result = client.read_input_registers(0x311A, 1, unit=1)
    batterySOC = result.registers[0]
    print (" ")
    print ("batterySOC=", batterySOC)


Finally sending values to the virtual ports. Thanks for your help. Now I need to refresh that data every 30 seconds or so, but once Blynk starts, I can’t send that data. Any thoughts?

A post was split to a new topic: ESP8266 (NoceMCU), EPEver Tracer A and MAX485 module