Skip to content

Arduino, esp32 and esp8266 library for ABB (ex PowerOne) Aurora Inverter, implement a full methods to retrieve data from the Inverter via RS-485

License

Notifications You must be signed in to change notification settings

xreef/ABB_Aurora_Solar_Inverter_Library

Repository files navigation

Support forum Aurora Inverter English
Forum supporto Aurora Inverter italiano

06/04/2022: v1.0.3 Fix package size

ABB Aurora protocol

You can refer the complete documentation on my site

ABB Aurora PV inverter library for Arduino, esp8266 and esp32

I create this library to develop this Web Monitor interface.

Here the base information of RS485 ABB Aurora communication Protocol.

ABB PowerOne Aurora communication protocol Library arduino esp8266 esp32 Main

ABB PowerOne Aurora communication protocol Library arduino esp8266 esp32 Main

The communication between Host and processor works via a Serial Interface RS485 or RS232. Configuration parameters in both cases are:

  • 19200 baud (default value)
  • 1 stop bit
  • no parity

The structure of the answer has also fixed length (6 Bytes + 2 Bytes for Checksum) :

Transmission State is coded as follows:

0 = Everything is OK.

51 = Command is not implemented

52 = Variable does not exist

53 = Variable value is out of range

54 = EEprom not accessible

55 = Not Toggled Service Mode

56 = Can not send the command to internal micro

57 = Command not Executed

58 = The variable is not available, retry

Global State shows the state of the addressed device, the details are specified in the description of the commands.

Arduino UNO and MAX485

You can use an Arduino UNO and a MAX485 IC, if you prefer can buy a module.

You can find IC on AliExpress

You can find module on AliExpress

You can ArduinoUNO on AliExpress

Here the simple connection schema, the resistor must be 120Ω, i use 104Ω.

MAX485 Arduino connection schema

I create a library derived from a project that you can find in the web created by drhack, It’s a fantastic works (thanks to drhack) but I find It quite difficult to use, with specific hardware and not so reusable.

So I try to standardize the library and made It simple (the people that use my library know that “simplify first” It’s my motto.

esp8266 and MAX3485

If you want use an esp8266 (I create a centraline with Wemos D1 mini) you must buy a MAX3485 tha work at the correct voltage.

You can find IC on AliExpress eBay

You can find module on AliExpress eBay

You can find WeMos D1 mini on AliExpress

Here the simple connection schema, the resistor must be 120Ω, i use 104Ω.

MAX3485 and esp8266 connection schema

As you can see It’s quite simple to connect.

Constructor

As usual I try to create It more generic as possible, so If you want use HardwareSerial or SoftwareSerial you are free to choiche.

You must specify an address, that address normally is 2, but you must check It in your inverter menu.

You can create a chain of inverters that communicate via RS485. An address can be chosen from 2 to 63. The address on the inverter is set through the display and the pushbutton panel.

To change address go to SETTINGS --> Insert password (default 0000) --> Address.

This menu allows you to set the serial port addresses of the individual inverters connected to the RS485 line. The addresses that can be assigned are 2 to 63. The UP and DOWN buttons scroll through the numerical scale. ‘AUTO’ selection cannot be used at present.

HardwareSerial

// Aurora(byte inverterAddress, HardwareSerial* serial, byte serialCommunicationControlPin) Aurora inverter = Aurora(2, &Serial, 5);
  • inverterAddress: as described is the inverter address set on device.
  • serial: is the HardwareSerial.
  • serialCommunicationControlPin: is the pin that activate transmission of serial communication.

SoftwareSerial

// Aurora(byte inverterAddress, byte rxPin, byte txPin, byte serialCommunicationControlPin) Aurora inverter = Aurora(2, 10, 11, 5);
  • inverterAddress: as described is the inverter address set on device.
  • rxPin: is the SoftwareSerial RX pin.
  • txPin: is the SoftwareSerial TX pin.
  • serialCommunicationControlPin: is the pin that activate transmission of serial communication.

For software serial you can pass external SoftwareSerial instance.

// Aurora(byte inverterAddress, SoftwareSerial* serial, byte serialCommunicationControlPin) |

Usage

You can refer the complete documentation on my site ABB Aurora PV inverter library for Arduino, esp8266 and esp32

First you must startup the communication with begin command:

inverter.begin();|

Than there are a lot of command that you can use to make query to your Inverter:

        void begin();

        void clearReceiveData();
        DataState readState();
        DataVersion readVersion();
        DataDSP readDSP(byte type, byte global = (byte)1);
        DataTimeDate readTimeDate();
        bool writeTimeDate(unsigned long epochTime);
        DataLastFourAlarms readLastFourAlarms();
        DataJunctionBoxState readJunctionBoxState(byte nj);
        bool readJunctionBoxVal(byte nj, byte par);
        DataSystemPN readSystemPN();
        DataSystemSerialNumber readSystemSerialNumber();
        DataManufacturingWeekYear readManufacturingWeekYear();
        DataFirmwareRelease readFirmwareRelease();
        DataCumulatedEnergy readCumulatedEnergy(byte par);
        bool writeBaudRateSetting(byte baudcode);
        DataConfigStatus readConfig();
        DataTimeCounter readTimeCounter(byte param);

        // Central
        bool readFlagsSwitchCentral();
        bool readCumulatedEnergyCentral(byte var, byte ndays_h, byte ndays_l, byte global);
        bool readFirmwareReleaseCentral(byte var);
        bool readBaudRateSettingCentral(byte baudcode, byte serialline);
        bool readSystemInfoCentral(byte var);
        bool readJunctionBoxMonitoringCentral(byte cf, byte rn, byte njt, byte jal, byte jah);
        bool readSystemPNCentral();
        bool readSystemSerialNumberCentral();

Example code

Here an example of reading via Arduino.

/*
 Test Arduino MAX485 Aurora ABB connection
 by Mischianti Renzo <https://www.mischianti.org>
 
 https://www.mischianti.org/
*/
 
#include "Arduino.h"
#include <Aurora.h>
#include <SoftwareSerial.h>
#include <MemoryFree.h>
 
//SoftwareSerial mySerial(10, 11); // RX, TX
//Aurora inverter = Aurora(2, &amp;Serial1, 5);
Aurora inverter = Aurora(2, 10, 11, 5);
 
void SerialPrintData(byte *data) {
  for (int i = 0; i < 8; i++) {
    Serial.print((int)data[i]);
    Serial.print(F(" "));
  }
  Serial.println(F(" "));
 
}
 
void setup()
{
    Serial.begin(19200);
    inverter.begin();
}
 
// The loop function is called in an endless loop
void loop()
{
    Serial.print(F("freeMemory(1)="));Serial.println(freeMemory());
 
    Aurora::DataCumulatedEnergy cumulatedEnergy = inverter.readCumulatedEnergy((byte)1);
    Serial.println(F("------------------------------------------"));
    Serial.println(F("INVERTER 2"));
    Serial.print(F("          Data ROW = ")); SerialPrintData(inverter.receiveData);
    Serial.print(F("        Read State = ")); Serial.println(cumulatedEnergy.state.readState);
    Serial.print(F("Transmission State = ")); Serial.println(cumulatedEnergy.state.getTransmissionState());
    Serial.print(F("      Global State = ")); Serial.println(cumulatedEnergy.state.getGlobalState());
    Serial.print(F("           Energia = ")); Serial.print(cumulatedEnergy.energy); Serial.println(" Wh");
//    free(&amp;cumulatedEnergy);
    Serial.println(F("------------------------------------------"));
 
 
    Aurora::DataLastFourAlarms lastFour = inverter.readLastFourAlarms();
 
    Serial.println(F("INVERTER 2"));
    Serial.print(F("          Data ROW = "));  SerialPrintData(inverter.receiveData);
    Serial.print(F("        Read State = "));  Serial.println(lastFour.state.readState);
    Serial.print(F("Transmission State = "));  Serial.println(lastFour.state.getTransmissionState());
    Serial.print(F("      Global State = "));  Serial.println(lastFour.state.getGlobalState());
    Serial.print(F("          Alarms 1 = "));  Serial.println(lastFour.getAlarm1State());
    Serial.print(F("          Alarms 2 = "));  Serial.println(lastFour.getAlarm2State());
    Serial.print(F("          Alarms 3 = "));  Serial.println(lastFour.getAlarm3State());
    Serial.print(F("          Alarms 4 = "));  Serial.println(lastFour.getAlarm4State());
//  free(&amp;lastFour);
 
    Serial.println(F("------------------------------------------"));
 
    Aurora::DataVersion version = inverter.readVersion();
    Serial.println("INVERTER 2");
    Serial.print(F("          Data ROW = ")); SerialPrintData(inverter.receiveData);
    Serial.print(F("        Read State = ")); Serial.println(version.state.readState);
    Serial.print(F("Transmission State = ")); Serial.println(version.state.getTransmissionState());
    Serial.print(F("      Global State = ")); Serial.println(version.state.getGlobalState());
    Serial.print(F("           Version = ")); Serial.print(version.getModelName().name); Serial.print(F(" ")); Serial.print(version.getIndoorOutdoorAndType()); Serial.print(F(" ")); Serial.print(version.getGridStandard()); Serial.print(F(" ")); Serial.print(version.getTrafoOrNonTrafo()); Serial.print(F(" ")); Serial.println(version.getWindOrPV());
    Serial.println(F("------------------------------------------"));
//  free(&amp;version);
 
    Aurora::DataConfigStatus configStatus = inverter.readConfig();
 
    Serial.print(F("          Data ROW = ")); SerialPrintData(inverter.receiveData);
    Serial.print(F("        Read State = ")); Serial.println(configStatus.state.readState);
    Serial.print(F("Transmission State = ")); Serial.println(configStatus.state.getTransmissionState());
    Serial.print(F("      Global State = ")); Serial.println(configStatus.state.getGlobalState());
    Serial.print(F("      config       = ")); Serial.println(configStatus.getConfigStatus());
    Serial.println(F("------------------------------------------"));
//  free(&amp;version);
    Serial.print(F("freeMemory(2)="));Serial.println(freeMemory());
 
    Aurora::DataTimeCounter timeCounter = inverter.readTimeCounter(CT_TOTAL_RUN);
 
    Serial.print(F("          Data ROW = ")); SerialPrintData(inverter.receiveData);
    Serial.print(F("        Read State = ")); Serial.println(timeCounter.state.readState);
    Serial.print(F("Transmission State = ")); Serial.println(timeCounter.state.getTransmissionState());
    Serial.print(F("      Global State = ")); Serial.println(timeCounter.state.getGlobalState());
    Serial.print(F("      time in sec  = ")); Serial.println(timeCounter.upTimeInSec);
    Serial.print(F("      time in verb  = ")); Serial.print(timeCounter.getSecondsInDateElements()[0]); Serial.print(F("Y ")); Serial.print(timeCounter.getSecondsInDateElements()[1]); Serial.print(F("D "));Serial.print(timeCounter.getSecondsInDateElements()[2]);Serial.print(F("H "));Serial.print(timeCounter.getSecondsInDateElements()[3]);+Serial.print(F("M "));Serial.print(timeCounter.getSecondsInDateElements()[4]);Serial.println(F("S "));
    Serial.println(F("------------------------------------------"));
//  free(&amp;version);
    Serial.print(F("freeMemory(2)="));Serial.println(freeMemory());
 
    delay(4000);
 
}

As you can see the usage is quite simple.

Here the video of the result call.

Watch the video

Thanks