Use Arduino to Communicate With Tracer MT5 Charge Controller

15,901

23

21

I bought an MPPT TRACER 3215RN Solar Charge Controller, made by EP Solar (I've also seen SainSonic mentioned as the manufacturer, but it's the same product). I wanted to use my computer to monitor the PV panel and battery instead of buying the manufacturer's MT-5 Remote Meter, (a) because I wanted to log the data on my computer, and (b) why spend $36 when you don't need to.

I hunted around on the Internet and found a straightforward way of doing this with an Arduino Uno. I hope it works for you.

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Prepare Ethernet Cable

Get an Ethernet cable. It makes your head spin when you start looking into connector standards (technically the Tracer uses 8P8C), but so long as it has 8 wires it should be ok.

Cut the connector off one end.

Plug the end with the connector still on it into the Tracer.

On the end you just cut, use a multimeter to determine which wires are which:

- 4 of them will be ground

- 2 of them will be approx +12V

- 2 of them will be approx +3.3V

Trim off three of the ground wires and the two 12V wires, so you're left with one ground wire and the two 3.3V wires.

I then soldered breadboard wires to the three used wires to make it easy to hook up to the Arduino.

Step 2: Install This Arduino Sketch

This Arduino sketch (and most of the info in this posting) is from https://github.com/xxv/tracer However they used a serial baud rate of 57600, I had to drop it to 9600 to work on my Arduino/computer combination.

I had some trouble copying and pasting the sketch below because of unsupported characters, so if you get any errors with the sketch get the original from the github site.

/*
* An interface to the Tracer solar regulator. * Communicating in a way similar to the MT-5 display */

#include

SoftwareSerial myserial(10, 11); // RX, TX

uint8_t start[] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xEB, 0x90, 0xEB, 0x90, 0xEB, 0x90 }; uint8_t id = 0x16; uint8_t cmd[] = { 0xA0, 0x00, 0xB1, 0xA7, 0x7F };

uint8_t buff[128];

void setup() { Serial.begin(9600);

myserial.begin(9600); }

float to_float(uint8_t* buffer, int offset){ unsigned short full = buffer[offset+1] << 8 | buff[offset];

return full / 100.0; }

void loop() { Serial.println("Reading from Tracer");

myserial.write(start, sizeof(start)); myserial.write(id); myserial.write(cmd, sizeof(cmd));

int read = 0;

for (int i = 0; i < 255; i++){ if (myserial.available()) { buff[read] = myserial.read(); read++; } }

Serial.print("Read "); Serial.print(read); Serial.println(" bytes");

for (int i = 0; i < read; i++){ Serial.print(buff[i], HEX); Serial.print(" "); }

Serial.println();

float battery = to_float(buff, 9); float pv = to_float(buff, 11); //13-14 reserved float load_current = to_float(buff, 15); float over_discharge = to_float(buff, 17); float battery_max = to_float(buff, 19); // 21 load on/off // 22 overload yes/no // 23 load short yes/no // 24 reserved // 25 battery overload // 26 over discharge yes/no uint8_t full = buff[27]; uint8_t charging = buff[28]; int8_t battery_temp = buff[29] - 30; float charge_current = to_float(buff, 30);

Serial.print("Load is "); Serial.println(buff[21] ? "on" : "off");

Serial.print("Load current: "); Serial.println(load_current);

Serial.print("Battery level: "); Serial.print(battery); Serial.print("/"); Serial.println(battery_max);

Serial.print("Battery full: "); Serial.println(full ? "yes " : "no" );

Serial.print("Battery temperature: "); Serial.println(battery_temp);

Serial.print("PV voltage: "); Serial.println(pv);

Serial.print("Charging: "); Serial.println(charging ? "yes" : "no" );

Serial.print("Charge current: "); Serial.println(charge_current);

delay(1000); }

Step 3: Connect Wires to Arduino

Connect the ground wire to Arduino ground.

One of the 3.3V wires connects to Arduino pin 10, and the other 3.3V wire connects to Arduino pin 11. There's probably a way of telling which goes which from the colors (comments welcome!), but there's only 2 wires so just swap them if it doesn't work first time.

Watch the results in the serial window (terminal emulator) on your computer.

Good luck!

Home Technology Contest

Participated in the
Home Technology Contest

2 People Made This Project!

Recommendations

  • Made with Math Contest

    Made with Math Contest
  • Multi-Discipline Contest

    Multi-Discipline Contest
  • Robotics Contest

    Robotics Contest

21 Discussions

None
MattiasP5

2 years ago

is it posibly to use arduino nano for this project? im realy new to arduino, but what i understand uno and nano have same atmega, so could i still use pin 10 and 11 for tx and rx?

None
macner

2 years ago

Hi BF72,

I am trying to get the data on following mppt charger and i have no idea about communication with it via Arduino. I have asked the comm. protocol to the manufacturer however no answers at all. I am open to any suggestion.

http://www.cnbou.com/10a-mppt-solar-charge-controller/

It has windows based software which you can follow the info, but it only shows up the last status. We would like to save and upload to PV data to the thingspeak.

http://inverterfactory.com/file/2016-8%20MPPT%20solar%20chagre%20controller%20PC%20Program.zip

Thanks in advance.

None
PaulVdB

2 years ago

I made it, but it doesn't work. :(

I use controller Tracer 2210 -> works fine
I use Arduino Mega, serial 2 (17=RX, 16=TX)
I use the exact same sketch from here above.

After I sent the initialisation strings, I do get a response from the controller that I can see on my osciloscope. I've put a "schmitt trigger" in front of the RX pin so that I get nice 5V pulses on pin 17.
On my serial, I see nothing but ZERO's (except the temperature which is -30)

Baud rates are both set to 9600
I tried 15 and 14 as RX and TX, but the same result.
When I try another baud rate , I don't get nothing back from the charger.
I tried without the schmitt trigger : same result (pulses are only 3V)

What did I do wrong ?

2 replies
None
PaulVdBPaulVdB

Reply 2 years ago

Use this code for Arduino MEGA :

/*
An interface to the Tracer solar regulator.
Communicating in a way similar to the MT-5 display
for ARDUINO MEGA
*/
// DO NOT include <SoftwareSerial.h> !!
// connect RX from MT5 to pin 14 of Arduino MEGA
// connect TX from MT5 to pin 15 of Arduino MEGA
// Arduino MEGA has 3 Serials. Serial3 is standard 14/15 !!

uint8_t start[] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
0xEB, 0x90, 0xEB, 0x90, 0xEB, 0x90
};
uint8_t id = 0x16;
uint8_t cmd[] = { 0xA0, 0x00, 0xB1, 0xA7, 0x7F };
uint8_t buff[128];

void setup() {
Serial.begin(9600);
Serial3.begin(9600); // >>>>>>>>>>>>>>>>> Notice the 3 !
}

float to_float(uint8_t* buffer, int offset) {
unsigned short full = buffer[offset + 1] << 8 | buff[offset];
return full / 500.0;
}

void loop()
{
Serial.println("-------------------------------------");
Serial.println("Reading from Tracer");

Serial3.write(start, sizeof(start));
Serial3.write(id);
Serial3.write(cmd, sizeof(cmd));

int read = 0;

for (int i = 0; i < 255; i++) {
if (Serial3.available()) {
buff[read] = Serial3.read();
read++;
}
}

Serial.print("Read ");
Serial.print(read);
Serial.println(" bytes");

for (int i = 0; i < read; i++) {
Serial.print(buff[i], HEX);
Serial.print(" ");
}

Serial.println();

float battery = to_float(buff, 9);
float pv = to_float(buff, 11);
//13-14 reserved
float load_current = to_float(buff, 15);
float over_discharge = to_float(buff, 17);
float battery_max = to_float(buff, 19);
// 21 load on/off
// 22 overload yes/no
// 23 load short yes/no
// 24 reserved
// 25 battery overload
// 26 over discharge yes/no
uint8_t full = buff[27];
uint8_t charging = buff[28];
int8_t battery_temp = buff[29] - 30;
float charge_current = to_float(buff, 30);

Serial.print("Load is ");
Serial.println(buff[21] ? "on" : "off");

Serial.print("Load current: ");
Serial.println(load_current);

Serial.print("Battery level: ");
Serial.print(battery);
Serial.print("/");
Serial.println(battery_max);

Serial.print("Battery full: ");
Serial.println(full ? "yes " : "no" );

Serial.print("Battery temperature: ");
Serial.println(battery_temp);

Serial.print("PV voltage: ");
Serial.println(pv);

Serial.print("Charging: ");
Serial.println(charging ? "yes" : "no" );

Serial.print("Charge current: ");
Serial.println(charge_current);
Serial.println();

delay(2000);
}

None
PaulVdBPaulVdB

Reply 2 years ago

"exact same sketch" but of course changed SoftwareSerial myserial to (17,16) ! :)

None
PaulVdB

2 years ago

Use this code for Arduino MEGA :

/*
An interface to the Tracer solar regulator.
Communicating in a way similar to the MT-5 display
for ARDUINO MEGA
*/
// DO NOT include <SoftwareSerial.h> !!
// connect RX from MT5 to pin 14 of Arduino MEGA
// connect TX from MT5 to pin 15 of Arduino MEGA
// Arduino MEGA has 3 Serials. Serial3 is standard 14/15 !!

uint8_t start[] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
0xEB, 0x90, 0xEB, 0x90, 0xEB, 0x90
};
uint8_t id = 0x16;
uint8_t cmd[] = { 0xA0, 0x00, 0xB1, 0xA7, 0x7F };
uint8_t buff[128];

void setup() {
Serial.begin(9600);
Serial3.begin(9600); // >>>>>>>>>>>>>>>>> Notice the 3 !
}

float to_float(uint8_t* buffer, int offset) {
unsigned short full = buffer[offset + 1] << 8 | buff[offset];
return full / 500.0;
}

void loop()
{
Serial.println("-------------------------------------");
Serial.println("Reading from Tracer");

Serial3.write(start, sizeof(start));
Serial3.write(id);
Serial3.write(cmd, sizeof(cmd));

int read = 0;

for (int i = 0; i < 255; i++) {
if (Serial3.available()) {
buff[read] = Serial3.read();
read++;
}
}

Serial.print("Read ");
Serial.print(read);
Serial.println(" bytes");

for (int i = 0; i < read; i++) {
Serial.print(buff[i], HEX);
Serial.print(" ");
}

Serial.println();

float battery = to_float(buff, 9);
float pv = to_float(buff, 11);
//13-14 reserved
float load_current = to_float(buff, 15);
float over_discharge = to_float(buff, 17);
float battery_max = to_float(buff, 19);
// 21 load on/off
// 22 overload yes/no
// 23 load short yes/no
// 24 reserved
// 25 battery overload
// 26 over discharge yes/no
uint8_t full = buff[27];
uint8_t charging = buff[28];
int8_t battery_temp = buff[29] - 30;
float charge_current = to_float(buff, 30);

Serial.print("Load is ");
Serial.println(buff[21] ? "on" : "off");

Serial.print("Load current: ");
Serial.println(load_current);

Serial.print("Battery level: ");
Serial.print(battery);
Serial.print("/");
Serial.println(battery_max);

Serial.print("Battery full: ");
Serial.println(full ? "yes " : "no" );

Serial.print("Battery temperature: ");
Serial.println(battery_temp);

Serial.print("PV voltage: ");
Serial.println(pv);

Serial.print("Charging: ");
Serial.println(charging ? "yes" : "no" );

Serial.print("Charge current: ");
Serial.println(charge_current);
Serial.println();

delay(2000);
}

None
LubošZ

3 years ago

Could you do Instructions for tracer BN series? It uses an RS-485 interface.

Description of communication protocol is http://www.solar-elektro.cz/data/dokumenty/1733_modbus_protocol.pdf

4 replies
None
larssorensenLubošZ

Reply 3 years ago

That would be great!

Lubsz, have you managed to get it to work?

None
LubošZlarssorensen

Reply 3 years ago

Working... epsolar BN series. I have 4215BN.

https://github.com/kasbert/epsolar-tracer

None
wrybread

2 years ago

I'm trying to read the data from a Tracer 4210a, which I gather is a BN series, which uses modbus. So far no luck, including with the Windows program "Solar Station Monitor" from EPEVER. It works just fine with the MT50 remote monitoring box though.

I'm using the USB cable from here:

https://www.amazon.com/Battery-Temperature-Sensor-...

Has anyone figured out how to read data from these controllers?

None
AmakA1

3 years ago

How it work with Windows10 iot + raspberry pi !!?

None
johncatherine

3 years ago

I followed your steps and it worked. TY!

On my Ethernet cable, I used brown as ground and stripe-blue went to arduino pin 10 (RX), and solid green went to arduino pin 11 (TX).

None
RohanH

4 years ago

Hi,

I aslo have the sme setup and tried to use your code to get the readings.

When I view the information in the serial window it only shows a lot of special characters over and over, did I miss a step or is there another setting I need to changeto get the right information?

I swapped the 2 wires on pin 10 and 11 aswell and no change..

Regards

1 reply
None
BF72RohanH

Reply 4 years ago

Sometimes getting weird characters is due to the wrong baud rate being set. You might want to check that everything is set to 9600, ie. ensure in the sketch it says Serial.begin(9600) and myserial.begin(9600).

Hope this helps.

None
BF72krzysztof.zurad.5

Reply 4 years ago on Introduction

I tried using one of the +12V wires from the Tracer to power the Arduino and Ethernet board, but it didn't work. The Ethernet board needs a lot of power (they get really hot, which is normal) and there wasn't sufficient power from the Tracer. I needed to plug the Arduino into a dedicated power supply.