Easun Inverter #8
Replies: 4 comments
-
A late answer but I just asked the producer for powland SMP 5KW inverter, and their email address was easunpower. Communication protocol.powland.English-Auto.Translated.pdf I think the author can implement this quite eacy. PS the paper have the hex you need to send on rs232 to get answer and it is eacy to test. |
Beta Was this translation helpful? Give feedback.
-
this inverters have different protocols, in a future version i will build in the communication, but i need the communication protocol for it |
Beta Was this translation helpful? Give feedback.
-
@sigurdi with your translated protocol pdf, i was able to receive data from my 3.2kW 24V EcgSolax hybrid inverter. Here my arduino code for ESP32 S2 Lolin mini: #define _DEBUG
#ifdef _DEBUG
#define OUT(txt, val) {Serial.print(F(txt)); Serial.print(F(": ")); Serial.print(val);}
#define OUTT(txt, val) {Serial.print(F(txt)); Serial.print(F(": ")); Serial.print(val); Serial.print(F("\t"));}
#define OUTTX(txt, val) {Serial.print(F(txt)); Serial.print(F(": ")); Serial.print(val,HEX); Serial.print(F("\t"));}
#define OUTTB(txt, val) {Serial.print(F(txt)); Serial.print(F(": ")); Serial.print(val,BIN); Serial.print(F("\t"));}
#define OUTN(txt, val) {Serial.print(F(txt)); Serial.print(F(": ")); Serial.println(val);}
#else
#define OUT(txt, val)
#define OUTT(txt, val)
#define OUTTX(txt, val)
#define OUTTB(txt, val)
#define OUTN(txt, val)
#endif
#include <HardwareSerial.h>
const int pinInverter = 11;
// UART Configuration (ESP32 S2 Mini: GPIO37 = TX, GPIO39 = RX)
HardwareSerial InverterSerial(1); // Use UART1
const int TX_PIN = 37;
const int RX_PIN = 39;
const uint32_t BAUDRATE = 2400; // Common inverter baud rate
// Inverter Protocol Settings
const byte INVERTER_ADDRESS = 2; // Default address (change in inverter settings)
const String COMMAND_PREFIX = "^D005"; // For 5-byte commands :cite[7]
byte aCmd[] = {0x51, 0x50, 0x49, 0x47, 0x53, 0xB7, 0xA9, 0x0D, 110}; // QPIGS<CRC16><CR>: Device general status parameters inquiry. last byte is response ength
// Command Definitions (PI30 protocol) :cite[7]:cite[10]
const String QUERY_GENERAL_STATUS = "QPIGS"; // General status
const String QUERY_RATED_INFO = "QPIRI"; // Rated information
const String QUERY_FLAGS = "QFLAG"; // System flags
const String SET_OUTPUT_SOURCE = "POP"; // Control output source (00:utility, 01:solar, 02:SBU)
// Response Buffers
char responseBuffer[256]; // Raw inverter response
int bufferIndex = 0; // Tracks response length
// Parsed Data Structure
struct InverterData {
float gridVoltage;
float gridFrequency;
float outputAcV;
float outputAcHz;
int outputAcVA;
int outputAcW;
int outputAcPercent;
int busV;
float batteryV;
int batteryChargeA;
int batteryCpacity; // State of Charge (%)
float temperature;
int pvA;
float pvV;
float batterySccV;
int batteryDischargeA;
byte state;
};
InverterData currentData;
void setup() {
// Start debug serial (USB)
Serial.begin(115200);
// Start UART with inverter
InverterSerial.begin(BAUDRATE, SERIAL_8N1, RX_PIN, TX_PIN);
Serial.println("Initialized UART on pins 37(TX), 39(RX)");
pinMode(pinInverter,OUTPUT); // turn inverter on with CNY17-1 optocoupler who will pull down the battery voltage on the red cable of the on/off switch
digitalWrite(pinInverter,0);
}
unsigned long iTimeNextRequest = 2000;
void loop()
{
if (millis() > 1000) digitalWrite(pinInverter,1);
if (CheckResponse())
{
printInverterData();
}
if (millis() > iTimeNextRequest)
{
iTimeNextRequest = millis() + 200;
RequestData(QUERY_GENERAL_STATUS);
RequestData(QUERY_GENERAL_STATUS); // for some reason, we must sent twice :-/
}
}
bool RequestData(String command2)
{
if (bufferIndex) // wait for received message to be processed
return false;
byte iResponseLength = aCmd[sizeof(aCmd)-1]; // last byte is response length
InverterSerial.write(aCmd,sizeof(aCmd)-1);
Serial.write(aCmd,sizeof(aCmd)-1);
//InverterSerial.write(0x0A);
memset(responseBuffer, 0, sizeof(responseBuffer)); // Clear buffer
//OUTN(" request data",iResponseLength);
return true;
}
unsigned long iTimeLastRx = 0;
boolean CheckResponse()
{
if (iTimeLastRx)
{
if (millis()-iTimeLastRx > 100)
{
iTimeLastRx = bufferIndex = 0; // skip incomplete message
return false;
}
}
if (!InverterSerial.available())
return false;
iTimeLastRx = millis();
if (!bufferIndex) // read to beginning char '('
{
while (InverterSerial.available())
{
char c = InverterSerial.read();
if (c == '(')
{
Serial.print(c);
responseBuffer[bufferIndex++] = c;
break;
}
}
}
byte iMissing = aCmd[sizeof(aCmd)-1]-1; // last byte is response length, '(' already read
if (InverterSerial.available() < iMissing)
return false;
while (iMissing--)
{
char c = InverterSerial.read();
Serial.print(c);
responseBuffer[bufferIndex++] = c;
}
return parseData2();
}
bool parseData2()
{
// Sample response: (000.0 00.0 230.1 49.9 0000 0000 000 388 26.00 000 098 0049 0000 000.0 00.00 00000 00010000 00 00 00000 010⸮a
InverterData tempData;
int32_t iState = -1;
sscanf(responseBuffer, "(%f %f %f %f %d %d %d %d %f %d %d %d %d %f %f %d %u",
&tempData.gridVoltage,
&tempData.gridFrequency,
&tempData.outputAcV,
&tempData.outputAcHz,
&tempData.outputAcVA,
&tempData.outputAcW,
&tempData.outputAcPercent,
&tempData.busV,
&tempData.batteryV,
&tempData.batteryChargeA,
&tempData.batteryCpacity, // State of Charge (%)
&tempData.temperature,
&tempData.pvA,
&tempData.pvV,
&tempData.batterySccV,
&tempData.batteryDischargeA,
&iState
);
OUTT("- iState",iState)
if (iState == -1)
{
Serial.println("parsing failed");
bufferIndex = 0; // reset to receive new response
return false;
}
memcpy(¤tData,&tempData,sizeof(currentData));
currentData.state = 0;
int iBit=1;
while (iState)
{
currentData.state |= (iState%2) * iBit;
iBit *= 2;
iState /= 10;
}
OUTN(" -> ",currentData.state)
bufferIndex = 0; // reset to receive new response
return true;
}
void printInverterData() {
Serial.println("\n--- Inverter Data ---");
OUTN("gridVoltage", currentData.gridVoltage)
OUTN("gridFrequency", currentData.gridFrequency)
OUTN("outputAcV", currentData.outputAcV)
OUTN("outputAcHz", currentData.outputAcHz)
OUTN("outputAcVA", currentData.outputAcVA)
OUTN("outputAcW", currentData.outputAcW)
OUTN("outputAcPercent", currentData.outputAcPercent)
OUTN("busV", currentData.busV)
OUTN("batteryV", currentData.batteryV)
OUTN("batteryChargeA", currentData.batteryChargeA)
OUTN("batteryCpacity", currentData.batteryCpacity)
OUTN("temperature", currentData.temperature)
OUTN("pvA", currentData.pvA)
OUTN("pvV", currentData.pvV)
OUTN("batterySccV", currentData.batterySccV)
OUTN("batteryDischargeA", currentData.batteryDischargeA)
OUTTB("state", currentData.state)
Serial.println();
} |
Beta Was this translation helpful? Give feedback.
-
Just tested that my code also works with a EASun 48V 6200W hybrid inverter. For connecting the Lolin S2 mini, i took the small and cheap RS232 MAX3232 module: |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello.
I would like to use the application on this inverter
https://www.easunpower.com/products/EASUN-POWER-Hybrid-Solar-Inverter-5500W-90A-MPPT-Charger-220V-48V-5.5KW-450Vdc-Grid-Tied-Touch-Screen-Inverter-with -CT-Sensor
Do you think it is compatible?
What should I set to type inverter?
Beta Was this translation helpful? Give feedback.
All reactions