EPever/EPsolar Controllers & Blynk

I’ve been with BT about 8 years, never had an issue with them. Tried Virgin briefly, never again…
That said, BT’s telephone exchange is less than half a mile away and their new fibre box is at the end of my drive. So I’ve always had a good connection and reasonable speeds, even though it’s an FTTC connection. I plan to upgrade to FTTP when its available the end of this year. This is about average for me…


Why do you not like them, bad experience?

I was with BT for years and always figured that they’d provide the best service,. even if they werent the cheapest.
After a few issues with internet speeds being worse then usual I had some very frustrating conversations with support people who were clearly in Asian call centres and didn’t speak very good English, didn’t know their arse from their elbow, and didn’t care a toss about resolving my issues.
At that point I swapped to Sky and haven’t had any issues since, and their support is great.

We have fibre to the box down the street and copper from there into the house and I’m getting this sort of speed, which is fine for me…

image

When I worked in IT we were always having battles with BT/Openreach and they never kept to their promises of installation dates and never paid the compensation that should have been due for their failures. One of my friends was a marketing director for Openreach and even she thinks that they’re rubbish!

Pete.

1 Like

As you can see, things are heading in the right direction.
Massive thank you to @PeteKnight for sending me this custom PCB, makes things so much easier and neater.

It’s sat on top of four 18650 cells supplying it with power, so at the moment it’s portable. At the moment its connected to my smallest controller, a 10A Xtra.

As you can see in the screen shot, the load button doesn’t work. Load is off and I’m still receiving data. I can turn it on and off on the controller but not via Blynk. Its not essential for me to be able to turn it on and off, but it would be nice to have the ability, hope I can figure it out.

From memory, I think that the controller has to be in a certain configuration (manual load control I think) to allow the load to be turned on and off via a software command.
This is a snippet of code that I used to use to control the load via software…

  node1.writeSingleCoil(0x0001, 1);
  result = node1.writeSingleCoil(0x0002, state);  

  if (result == node1.ku8MBSuccess)
  {
    node1.getResponseBuffer(0x00);
    Serial1.println("Success.");
  }

The 'state` variable needs to be 1 for on and 0 for off.

Pete.

1 Like

Absolute genius, thank you. Its now working perfectly via the button in the Blynk app…

1 Like

Almost got this sorted, but need a way to change this using segmented switch?

// Modbus slave ID 1,2,3,4 etc
  node.begin(1, Serial);

:thinking:
148323302_339520697249975_1370137909176462672_n

Things are really starting to come together now. Check out this YouTube vid…


Huge thank you to Steve for his help, could not have got this far without him .

Things are moving along, still not perfect yet but I’m getting there. Designed my own PCB that works directly off the controllers RS485 port, no external power required.


Unfortunately it only works on the larger controllers with >200mAh RS485 ports. If I want to use it on the smaller <100mAh controllers I supply the Wemos D1 Pro with power via USB.

Receiving the data via terminal gives me a way to double check the data in each controllers “tab”.

I’ve reached that crucial point where it all appears to be working as it should. I’m sure it can be refined and made to work better, but for the moment, I shall wallow in the fact it works.
I couldn’t have done it without Pete’s help so a huge thank you to him.

This is my largest Blynk project and used about 30,000 Blynk Energy so if you don’t have your own Blynk Server you’ll have to spend a few pennies on energy.

CODE:

 #include <ArduinoOTA.h>
 #include <ESP8266WiFi.h>
 #include <BlynkSimpleEsp8266.h> //Blynk support

 #include <ModbusMaster.h>      //https://github.com/4-20ma/ModbusMaster/

 #include "esp_credentials.h" // include WIFI credentials and Blynk auth token credentials

 // Attach virtual terminal to Virtual Pin V1
 WidgetTerminal terminal(V1);
 
 #define MAX485_DE       D1 // On custom PCB these connections are hard-wired as follows...
 #define MAX485_RE       D2 // DE--> D1 (GPIO5) and RE--> D2 (GPIO4)

 int next_controller = 1;   // Pointer to indicate which controller (node) will be read next (1, 2 or 3)

 // These are the internal registers for the various pieces of data...
 // 3100 Registers ....
 #define PANEL_VOLTS     0x00 // Address 3100
 #define PANEL_AMPS      0x01 // Address 3101
 #define PANEL_POWER_L   0x02 // Address 3102
 #define PANEL_POWER_H   0x03 // Address 3103
 #define BATT_VOLTS      0x04 // Address 3104
 #define BATT_AMPS       0x05 // Address 3105
 #define BATT_POWER_L    0x06 // Address 3106
 #define BATT_POWER_H    0x07 // Address 3107

 // 310C Registers...
 #define LOAD_VOLTS      0x00 // Address 310C
 #define LOAD_AMPS       0x01 // Address 310D
 #define LOAD_POWER_L    0x02 // Address 310E
 #define LOAD_POWER_H    0x03 // Address 310F

 // 3110 Registers...
 #define BATT_TEMP       0x00 // Address 3110
 #define CONTROL_TEMP    0x01 // Address 3111

 // 311A Registers...
 #define BATT_SOC        0x00 // Address 311

uint8_t result;

  ModbusMaster node; // Define ModbusMaster object...

  BlynkTimer timer; // initiate the timer object...


void setup()
{
  Blynk.begin(AUTH, WIFI_SSID, WIFI_PASS);
  
  ArduinoOTA.onError([](ota_error_t error) { ESP.restart(); });
  ArduinoOTA.setHostname("EPEver_Monitor");
  ArduinoOTA.begin();  

  terminal.clear();
  terminal.println("EPEver Monitor Initialised");
  terminal.print("IP Address = ");  
  terminal.println(WiFi.localIP());   
  terminal.println();    

  Serial.begin(115200); // Must be 115200 for EPEver devices

  pinMode(MAX485_RE, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode
  digitalWrite(MAX485_RE, 0);
  digitalWrite(MAX485_DE, 0);


  // Define the callbacks for the nodes. 
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);

  timer.setInterval(10000, read_controllers_in_sequence);
}

void read_controllers_in_sequence()
{
  // This function is called by the timer to read the next controller in the sequence 1, 2 then 3 and back to 1 again...
  node.begin(next_controller, Serial);
  readMODBUS();    

  Blynk.virtualWrite(100, WiFi.RSSI());

  next_controller = next_controller+1;
  if (next_controller > 3)
  {
    next_controller = 1;
  }
}

// The code for reading controllers ...
void readMODBUS()
{
  terminal.print("RESULTS FOR CONTROLLER ");
  terminal.println(next_controller);
  
  uint8_t result;
  
  // Read 6 registers starting at 0x3100)
  node.clearResponseBuffer();
  result = node.readInputRegisters(0x3100, 8);

  if (result == node.ku8MBSuccess)
  {
    float pV = node.getResponseBuffer(PANEL_VOLTS)/100.0f;
    float pI = node.getResponseBuffer(PANEL_AMPS)/100.0f;
    float pP = (node.getResponseBuffer(PANEL_POWER_L) |
                    (node.getResponseBuffer(PANEL_POWER_H) << 8))/100.0f;

    float bV = node.getResponseBuffer(BATT_VOLTS)/100.0f;
    float bI = node.getResponseBuffer(BATT_AMPS)/100.0f;

    float bP = (node.getResponseBuffer(BATT_POWER_L) |
                    (node.getResponseBuffer(BATT_POWER_H) << 8))/100.0f;

    terminal.println();
    terminal.print("VPanel: ");
    terminal.println(pV);
    terminal.print("IPanel: ");
    terminal.println(pI);
    terminal.print("PPanel: ");
    terminal.println(pP);
    terminal.println();
    terminal.print("VBatt: ");
    terminal.println(bV);
    terminal.print("IBatt: ");
    terminal.println(bI);
    terminal.print("PBatt: ");
    terminal.println(bP);
    terminal.println();

    Blynk.virtualWrite((next_controller * 20), pV);       // Virtual pins 20, 40, 60 etc
    Blynk.virtualWrite((next_controller * 20)+1, pI);     // Virtual pins 21, 41, 61 etc
    Blynk.virtualWrite((next_controller * 20)+2, pP);     // Virtual pins 22, 42, 62 etc   
    Blynk.virtualWrite((next_controller * 20)+3, bV);     // Virtual pins 23, 43, 63 etc
    Blynk.virtualWrite((next_controller * 20)+4, bI);     // Virtual pins 24, 44, 64 etc   
    Blynk.virtualWrite((next_controller * 20)+5, bP);     // Virtual pins 25, 45, 65 etc   

  }
  else
  {
      
    terminal.print("Mis-read Node ");
    terminal.print(next_controller);
    terminal.print(", Read of register 0x3100 failed! - Error Code = ");
    terminal.println(result, HEX);
    terminal.println();
  }


  // Read 6 registers starting at 0x310C)
  node.clearResponseBuffer();
  result = node.readInputRegisters(0x310c, 4);

  if (result == node.ku8MBSuccess)
  {
    float lV = node.getResponseBuffer(LOAD_VOLTS)/100.0f;
    float lI = node.getResponseBuffer(LOAD_AMPS)/100.0f;
    float lP = (node.getResponseBuffer(LOAD_POWER_L) |
                    (node.getResponseBuffer(LOAD_POWER_H) << 8))/100.0f;

   
    terminal.print("VLoad: ");
    terminal.println(lV);
    terminal.print("ILoad: ");
    terminal.println(lI);
    terminal.print("PLoad: ");
    terminal.println(lP);   
    terminal.println(); 
    
    Blynk.virtualWrite((next_controller * 20)+6, lV);     // Virtual pins 26, 46, 66 etc
    Blynk.virtualWrite((next_controller * 20)+7, lI);     // Virtual pins 27, 47, 67 etc
    Blynk.virtualWrite((next_controller * 20)+8, lP);     // Virtual pins 28, 48, 68 etc 
    
  }
  else
  {
     
    terminal.print("Mis-read Node ");
    terminal.print(next_controller);
    terminal.print(", Read of register 0x310C failed! - Error Code = ");
    terminal.println(result, HEX);
    terminal.println();
  }

  // Read 2 registers starting at 0x3110)
  node.clearResponseBuffer();
  result = node.readInputRegisters(0x3110, 2);

  if (result == node.ku8MBSuccess)
  {
    float bT = node.getResponseBuffer(BATT_TEMP)/100.0f;
    float cT = node.getResponseBuffer(CONTROL_TEMP)/100.0f;

    terminal.print("BTemp: ");
    terminal.println(bT);
    terminal.print("CTemp: ");    
    terminal.println(cT);

    Blynk.virtualWrite((next_controller * 20)+9, bT);     // Virtual pins 29, 49, 69 etc   
    Blynk.virtualWrite((next_controller * 30)+0, cT);     // Virtual pins 30, 50, 70 etc   
  }
   else
  {
     
    terminal.print("Mis-read Node ");
    terminal.print(next_controller);
    terminal.print(", Read of register 0x3111 failed! - Error Code = ");
    terminal.println(result, HEX);
    terminal.println();
  }


  // Read 1 register starting at 0x311A)
  node.clearResponseBuffer();
  result = node.readInputRegisters(0x311A, 1);

  if (result == node.ku8MBSuccess)
  {
    float bSOC = node.getResponseBuffer(BATT_SOC)/1.0f;

    terminal.print("SOC  : ");
    terminal.println(bSOC);         
    terminal.println();

    Blynk.virtualWrite((next_controller * 30)+1, bSOC);   // Virtual pins 31, 51, 71 etc

  }
   else
  {             
     
    terminal.print("Mis-read Node ");
    terminal.print(next_controller);
    terminal.print(", Read of register 0x311A failed! - Error Code = ");
    terminal.println(result, HEX);
    terminal.println();
  }
}
  
// Callback to on/off button state changes from the Blynk app for Controller 1
BLYNK_WRITE(V103)
{
  uint8_t newState = (uint8_t)param.asInt();
  
  terminal.print("Setting Controller 1 load state output coil to value: ");
  terminal.println(newState);

  node.begin(1, Serial);  // Select Controller 1
  result = node.writeSingleCoil(0x0002, newState);   // Turn the load on or off

  if (result == node.ku8MBSuccess)
  {
    terminal.println("Controller 1 load switched successfully");
    terminal.println(); 
  }
  else
  {
    terminal.println("Controller 1 load switching failed");
    terminal.println();     
  }
}

// Callback to on/off button state changes from the Blynk app for Controller 2
BLYNK_WRITE(V113)
{
  uint8_t newState = (uint8_t)param.asInt();
  
  terminal.print("Setting Controller 2 load state output coil to value: ");
  terminal.println(newState);

  node.begin(2, Serial);  // Select Controller 2
  result = node.writeSingleCoil(0x0002, newState);   // Turn the load on or off

  if (result == node.ku8MBSuccess)
  {
    terminal.println("Controller 2 load switched successfully");
    terminal.println(); 
  }
  else
  {
    terminal.println("Controller 2 load switching failed");
    terminal.println();    
  }
}

// Callback to on/off button state changes from the Blynk app for Controller 3
BLYNK_WRITE(V123)
{
  uint8_t newState = (uint8_t)param.asInt();
  
  terminal.print("Setting Controller 3 load state output coil to value: ");
  terminal.println(newState);

  node.begin(3, Serial);  // Select Controller 3
  result = node.writeSingleCoil(0x0002, newState);   // Turn the load on or off

  if (result == node.ku8MBSuccess)
  {
    terminal.println("Controller 3 load switched successfully");
    terminal.println(); 
  }
  else
  {
    terminal.println("Controller 3 load switching failed");
    terminal.println();     
  }
}

void loop()
{
  ArduinoOTA.handle();
  timer.run();
  Blynk.run();
  if(WiFi.status() != WL_CONNECTED)
  {
 } 
}
void preTransmission()
{
  digitalWrite(MAX485_RE, 1);
  digitalWrite(MAX485_DE, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_RE, 0);
  digitalWrite(MAX485_DE, 0);
}
3 Likes

May I have the complete code?
Like settings.h

I’m new to blynk