ABB Aurora web inverter monitor (WIM): set time and manage battery UPS – 5

Spread the love

You must consider a lot of factor when you try to create a generic device, time and power can be very important and not so simple to manage.

ABB PowerOne Aurora Web Inverter Centraline Set time and manage battery UPS
ABB PowerOne Aurora Web Inverter Centraline Set time and manage battery UPS

Datetime

A problem that must be managed is how to retrieve date and how to manage It.

There a lot of choiche you can apply, some use UTC time and convert It in locale WEB app, some store initial timestamp in the local device and so on.

In my centraline I’d like to store directly initial local time for logging, and I don’t add RTC device.

So I’m going to get time from NTP server (Network Time Protocol) than I’m going to apply specified DST (Daily Saving Time).

WiFiUDP ntpUDP;
// By default 'pool.ntp.org' is used with 60 seconds update interval and
// no offset
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 0*60*60, 60*60*1000);
[...]
	timeClient.begin();
[...]
	timeClient.update();
[...]
	if (timeClient.forceUpdate()){
		unsigned long epoch = timeClient.getEpochTime();
		DEBUG_PRINTLN(epoch);
		DEBUG_PRINTLN(F("NTP Time retrieved."));
		adjustTime(epoch);
		fixedTime = true;
	}

I don’t implement all DST configurations, so if you need to add your Timezone with DST manage ask to me and I add It to esp8266 and WEB part.

You can find all information of Arduino Timezone manage in my article “Network Time Protocol (NTP), Timezone and Daylight saving time (DST) with esp8266, esp32 or Arduino“.

ABB Aurora Timezone configuration

To partially manage the time I add GTM but if you select DST It’s going to override GTM.

time_t getLocalTime(void){
	Timezone tz = getTimezoneData(codeDST);

	return tz.toLocal(now());
}
Timezone getTimezoneData(const String code){
//	DEBUG_PRINT("CODE DST RETRIEVED: ");
//	DEBUG_PRINTLN(code);
	if (code==F("AETZ")){
		// Australia Eastern Time Zone (Sydney, Melbourne)
		TimeChangeRule aEDT = {"AEDT", First, Sun, Oct, 2, 660};    // UTC + 11 hours
		TimeChangeRule aEST = {"AEST", First, Sun, Apr, 3, 600};    // UTC + 10 hours
		Timezone tzTmp = Timezone(aEDT, aEST);
		return tzTmp;
	}else if (code==F("CET")){
//		DEBUG_PRINTLN(F("CET FIND"));
		// Central European Time (Frankfurt, Paris)
		TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};     // Central European Summer Time
		TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};       // Central European Standard Time
		Timezone tzTmp = Timezone(CEST, CET);
		return tzTmp;
	}else if(code==F("MSK")){
		// Moscow Standard Time (MSK, does not observe DST)
		TimeChangeRule msk = {"MSK", Last, Sun, Mar, 1, 180};
		Timezone tzTmp = Timezone(msk);
		return tzTmp;
	}else if(code==F("UK")){
		// United Kingdom (London, Belfast)
		TimeChangeRule BST = {"BST", Last, Sun, Mar, 1, 60};        // British Summer Time
		TimeChangeRule GMT = {"GMT", Last, Sun, Oct, 2, 0};         // Standard Time
		Timezone tzTmp = Timezone(BST, GMT);
		return tzTmp;
	}else if(code==F("USCTZ")){
		// US Central Time Zone (Chicago, Houston)
		TimeChangeRule usCDT = {"CDT", Second, Sun, Mar, 2, -300};
		TimeChangeRule usCST = {"CST", First, Sun, Nov, 2, -360};
		Timezone tzTmp = Timezone(usCDT, usCST);
		return tzTmp;
	}else if(code==F("USMTZ")){
		// US Mountain Time Zone (Denver, Salt Lake City)
		TimeChangeRule usMDT = {"MDT", Second, Sun, Mar, 2, -360};
		TimeChangeRule usMST = {"MST", First, Sun, Nov, 2, -420};
		Timezone tzTmp = Timezone(usMDT, usMST);
		return tzTmp;
	}else if(code==F("ARIZONA")){
		// Arizona is US Mountain Time Zone but does not use DST
		TimeChangeRule usMST = {"MST", First, Sun, Nov, 2, -420};
		Timezone tzTmp = Timezone(usMST);
		return tzTmp;
	}else if(code==F("USPTZ")){
		// US Pacific Time Zone (Las Vegas, Los Angeles)
		TimeChangeRule usPDT = {"PDT", Second, Sun, Mar, 2, -420};
		TimeChangeRule usPST = {"PST", First, Sun, Nov, 2, -480};
		Timezone tzTmp = Timezone(usPDT, usPST);
		return tzTmp;
	}else if(code==F("UTC")){
		// UTC
		TimeChangeRule utcRule = {"UTC", Last, Sun, Mar, 1, 0};     // UTC
		Timezone tzTmp = Timezone(utcRule);
		return tzTmp;
	}else{
		// UTC
//		DEBUG_PRINT("TIME_OFFSET ");
		int to = timeOffset/60;
//		DEBUG_PRINTLN(to);
		TimeChangeRule utcRule = {"GTM", Last, Sun, Mar, 1, to};     // UTC
		Timezone tzTmp = Timezone(utcRule);
		return tzTmp;

	}


}

Another step that I want to manage is to grab Datetime from Inverter.

Inverter have an internal RTC (Real Time Clock), and I manage a call to get this data, as you can see on the article ABB Aurora PV communication protocol via MAX485/MAX3485

The code is quite simple:

Aurora inverter = Aurora(2, &Serial, 5);
[...]
inverter.begin();
[...]
Aurora::DataTimeDate timeDate = inverter.readTimeDate();
Timezone tz = getTimezoneData(codeDST);
tm tempTime = timeDate.getDateTime();
time_t currentUTCTime = tz.toUTC(mktime(&tempTime));
adjustTime(currentUTCTime);

Learn more about how to recover data from Aurora inverter on the article “ABB Aurora PV inverter library for Arduino, esp8266 and esp32

Power source

I crete this centraline in substitution of the old one. The power supply of previous centraline is grab from Inverter directly so when there isn’t sun there isn’t power, this is quite good for previous centraline that use an MQTT protocol to send data directly to a central site, but I’d like to create an “autonomous” centraline without external site or other, so I use my old idea of UPS created with simple material, you can see It in this article Emergency power bank homemade, so It’s work for hours without power supply.

To reduce dimension I use a shield created for D1 Wemos, very compact:

Wemos D1 battery shield

You can find It here on AliExpress

The last version of this shield with a little solder directly put analog value of battery in the A0 pin with a voltage divider, so you can directly test the charge value, but It’s probably that you find the older version, and than you must use a voltage divider to put analog value on pin, more information in this article “Voltage divider: calculator and application“.

For the battery I use a 10kΩ and 20kΩ resistor.

float getBatteryVoltage(){
	//************ Measuring Battery Voltage ***********
	float sample1 = 0;

	for (int i = 0; i < 100; i++) {
		sample1 = sample1 + analogRead(A0); //read the voltage from the divider circuit
		delay(2);
	}
	sample1 = sample1 / 100;
	DEBUG_PRINT(F("AnalogRead..."));
	DEBUG_PRINTLN(sample1);
	float batVolt = (sample1 * 3.3 * (BAT_RES_VALUE_VCC + BAT_RES_VALUE_GND) / BAT_RES_VALUE_GND) / 1023;
	return batVolt;
}

I also rework a design of battery holder to standardize the solution.

Battery holder with voltage divider

So I use dupont to divided value and XH2.54 2p 2.54mm to connect on shield.

You can buy dupont box here AliExpress

You can buy XH2.54 pins box here AliExpress XH2.54 2.54mm AliExpress PH2.0 2.0mm


Now you can expose the charging value and create a chart.

Battery charging value chart

Thanks

  1. ABB Aurora Web Inverter Monitor (WIM): project introduction
  2. ABB Aurora Web Inverter Monitor (WIM): wiring Arduino to RS-485
  3. ABB Aurora Web Inverter Monitor (WIM): storage devices
  4. ABB Aurora Web Inverter Monitor (WIM): debug and notification
  5. ABB Aurora Web Inverter Monitor (WIM): set time and UPS
  6. ABB Aurora Web Inverter Monitor (WIM): WIFI configuration and REST Server
  7. ABB Aurora Web Inverter Monitor (WIM): WebSocket and Web Server
  8. ABB Aurora Web Inverter Monitor (WIM): Wiring and PCB soldering
  9. ABB Aurora Web Inverter Monitor (WIM): upload the sketch and front end
  10. ABB Aurora web inverter Monitor (WIM): 3D printed case to complete project
  11. ABB Aurora web inverter monitor (WIM): repair E013 error

GitHub repository with all code BE and FE transpiled


Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *