changes to sensor config and project environments

master
Andrew Woodlee 2 weeks ago
parent 93dbe1f3e9
commit df05374e4b

@ -4,31 +4,37 @@ This is the code that will control the ESP32.
## Requirements
We will be using PlatformIO for this project. This will allow us to possibly use its remote test and dev features.
We will be using PlatformIO for this project. This allows us to have greater control and allows for swapping boards if needed.
***You will need to change your upload port in `platformio.ini`.***
## Env variables
You will need to download the Silcon Labs Driver here - https://community.silabs.com/s/article/legacy-os-software-and-driver-packages?language=en_US
Add the env variables to a `.env` file before building it:
```sh
XFORMER_MON_WIFI_SSID=Your-WiFi-SSID
XFORMER_MON_WIFI_PASSWD=Your-WiFi-Password
# Your MQTT server
XFORMER_MON_MQTT_SERVER=xformer.utilitymonitor.io
XFORMER_MON_MQTT_USER=test
XFORMER_MON_MQTT_PASS=secure-mqtt-pass
XFORMER_MON_MQTT_ID=unique-id
XFORMER_MON_MQTT_PORT="8883"
## Setup
# Must be "enabled" if using SSL!
XFORMER_MON_USE_SSL="enabled"
*The Excel sheet has the necessary formulas to calculate the sensor config values. The important ones go in a `include/sensorConfigValues.h`.*
Add the necessary variables to a `config.yml` file before building the project.
*If you have the server certificate at `cert.crt` at build time, this cert will be used instead of fetching it from the server.*
```yaml
wifi:
# Your WiFi SSID
ssid: "Your-WiFi-SSID"
# Your WiFi Password
password: "Your-Secret-WiFi-Password"
mqtt:
# Your MQTT server
server: your.mqtt-broker.tld
# The port the MQTT server is running on
port: 8883
# Your MQTT User
user: test
# Your MQTT Password
password: secure-mqtt-pass
# A unique ID, usually the name of the transformer
id: unique-id
```
## Development
@ -37,7 +43,7 @@ Put .cpp files in `src`, .h files in `include`, and any libraries in `lib`.
## Tests
Put tests in `src/tests`. These are not PlatformIO tests.
Put tests in `src/tests`. **These are not PlatformIO tests.**
Run and upload tests using PlatformIO's VSCode extension. Or upload them using the command `pio run -t upload -e Test[Name]`. Name is the name of the test to run.
@ -59,4 +65,4 @@ build_src_filter =
## Setup
Depending on which sensor is used, the board has to be set up differently.
The PlatformIO environment `prod` is the same as `dev`, but `dev` has serial monitor code.

@ -13,20 +13,4 @@ mqtt:
# Your MQTT Password
password: secure-mqtt-pass
# A unique ID, usually the name of the transformer
id: unique-id
sensor:
config:
# voltage rms gain in hex. See docs/Gains.md for more information
ugain: 0x
# Voltage gain for CTs
lgain: 0x
# Voltage gain for neutral line
ngain: 0x
# power freqency
lfreq: 0x
# PGA Gain for current channels
pgagain: 0x
# Only for the ATM90E36 board
# determines which line to read
# Determines which voltage needs to be set.
line: "A"
id: unique-id

@ -24,7 +24,6 @@ mqttConfig = monitorConfigFile.get("mqtt")
mqttServer = mqttConfig.get("server")
mqttPort = mqttConfig.get("port")
sensorConfig = monitorConfigFile.get("sensor")
if wifiConfig.get("ssid") == None:
print(f"wifi object variable SSID not defined. Define it in the config.yml file at the root of the project.")
@ -41,6 +40,7 @@ if mqttConfig.get("server") == None:
env.Append(CPPDEFINES=[
("TM_WIFI_SSID", wifiConfig.get('ssid')),
("TM_WIFI_PASSWD", wifiConfig.get('password') ),
("TM_MQTT_ID", mqttConfig.get('id')),
("TM_MQTT_PORT", mqttConfig.get('port')),
("TM_MQTT_SVR", mqttConfig.get("server")),
("TM_MQTT_USER", mqttConfig.get("user")),

@ -0,0 +1,12 @@
// ********* Configuration of ATM90E26 ********* //
// L line calibration gain
double lgain = 0x1D39;
// voltage RMS gain
double ugain = 0x6F0B;
// L line current gain
double igainl = 0x7FF4;
// voltage sag threshold
double vsag = 0x0CD5;
// ********************************************* //

@ -10,6 +10,8 @@
#include <idf_additions.h>
#include <energyic_UART.h>
#include <transformerMonitorServerCert.h>
#include <sensorConfigValues.h>
// Turn build flags (Macros) into strings
#define ST(A) #A
@ -17,29 +19,33 @@
// extract the WiFi SSID from its macro
#ifdef TM_WIFI_SSID
char const *ssid = STR(TM_WIFI_SSID);
char const *ssid = STR(TM_WIFI_SSID);
#endif
// extract the WiFi Password from its macro
#ifdef TM_WIFI_PASSWD
char const *wifiPassword = STR(TM_WIFI_PASSWD);
char const *wifiPassword = STR(TM_WIFI_PASSWD);
#endif
// extract the MQTT Port from its macro
#ifdef TM_MQTT_PORT
uint16_t mqttPort = (uint16_t) strtoul(STR(TM_MQTT_PORT), NULL, 10);
uint16_t mqttPort = (uint16_t)strtoul(STR(TM_MQTT_PORT), NULL, 10);
#endif
// extract the MQTT server hostname from its macro
#ifdef TM_MQTT_SVR
char const *mqttServer = STR(TM_MQTT_SVR);
char const *mqttServer = STR(TM_MQTT_SVR);
#endif
// extract the MQTT username from its macro
#ifdef TM_MQTT_USER
char const *mqttUser = STR(TM_MQTT_USER);
char const *mqttUser = STR(TM_MQTT_USER);
#endif
// extract the MQTT password from its macro
#ifdef TM_MQTT_PASSWD
char const *mqttPass = STR(TM_MQTT_PASSWD);
char const *mqttPass = STR(TM_MQTT_PASSWD);
#endif
#ifdef TM_MQTT_ID
char const *client_id = STR(TM_MQTT_ID);
#endif
@ -47,8 +53,8 @@
//********* GPIO PINS ************* //
// pins for UART
#define PIN_SerialATM_RX 19 //RX pin for AdaFruit Huzzah32
#define PIN_SerialATM_TX 13 //TX pin for AdaFruit Huzzah32
#define PIN_SerialATM_RX 19 // RX pin for AdaFruit Huzzah32
#define PIN_SerialATM_TX 13 // TX pin for AdaFruit Huzzah32
// GPIO pins where the DS18B20 sensors are connected
const int oilTempBus = 5; // one in the epoxy resin
@ -65,14 +71,13 @@ void messageReceived(String &topic, String &payload);
WiFiClientSecure wifiClient;
PubSubClient mqttClient;
HardwareSerial ATMSerial(1); //1 = just hardware serial number. ESP32 supports 3 hardware serials. UART 0 usually for flashing.
HardwareSerial ATMSerial(1); // 1 = just hardware serial number. ESP32 supports 3 hardware serials. UART 0 usually for flashing.
ATM90E26_UART eic(&ATMSerial);
// * we are using the transformer's name to provide a unique ID
char* client_id = "al-xformer-592";
struct tempSensors {
struct tempSensors
{
DallasTemperature oil, cabinet;
};
@ -83,26 +88,28 @@ DeviceAddress cabinetTempSensorAddr;
OneWire oilTempBusOneWire(oilTempBus);
OneWire cabinetTempBusOneWire(cabinetTempBus);
// Pass our oneWire reference to Dallas Temperature sensor
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature oilTempSensor(&oilTempBusOneWire);
DallasTemperature cabinetTempSensor(&cabinetTempBusOneWire);
// temp sensor objects
tempSensors monitorTempSensors{oilTempSensor, cabinetTempSensor};
// Data structs for queue
struct tempData {
struct tempData
{
float cabinet, oil;
};
struct powerData {
struct powerData
{
double active, factor;
};
struct xformerMonitorData {
struct xformerMonitorData
{
unsigned short sysStatus, meterStatus;
double lineCurrent, lineVoltage;
double lineCurrent, lineVoltage, freq;
tm *timeInfo;
tempData temps;
powerData power;
@ -116,7 +123,7 @@ QueueHandle_t eicDataQueue;
// End variables for tasks
// Functions for tasks
void readEICData( void * pvParameters );
void readEICData(void *pvParameters);
// End functions for tasks
// Timer variable and function
@ -139,7 +146,8 @@ void setupMQTTClient();
// function to set up and initialize the energy monitor
void setupEnergyMonitor();
struct xformerMonConfigData {
struct xformerMonConfigData
{
char *wifiSsid;
char *wifiPass;
char *mqttName;

@ -140,28 +140,31 @@ unsigned short ATM90E26_UART::GetSysStatus() {
/*
Initialise Energy IC, assume UART has already began in the main code
*/
void ATM90E26_UART::InitEnergyIC() {
void ATM90E26_UART::InitEnergyIC(double ugain, double lgain, double igainl, double vSagTh) {
unsigned short systemstatus;
CommEnergyIC(0, SoftReset, 0x789A); // Perform soft reset
CommEnergyIC(0, FuncEn, 0x0030); // Voltage sag irq=1, report on warnout
// pin=1, energy dir change irq=0
CommEnergyIC(0, SagTh, 0x1F2F); // Voltage sag threshhold
CommEnergyIC(0, SagTh, vSagTh); // Voltage sag threshhold
// Set metering calibration values
CommEnergyIC(0, CalStart, 0x5678); // Metering calibration startup command.
// Register 21 to 2B need to be set
CommEnergyIC(0, PLconstH, 0x0014); // PL Constant MSB
CommEnergyIC(0, PLconstL, 0x3FB7); // PL Constant LSB
CommEnergyIC(0, Lgain, 0x1D39); // Line calibration gain
CommEnergyIC(0, PLconstH, 0x0007); // PL Constant MSB
CommEnergyIC(0, PLconstL, 0x24A1); // PL Constant LSB
CommEnergyIC(0, Lgain, lgain); // Line calibration gain
CommEnergyIC(0, Lphi, 0x0000); // Line calibration angle
CommEnergyIC(0, PStartTh, 0x08BD); // Active Startup Power Threshold
CommEnergyIC(0, PNolTh, 0x0000); // Active No-Load Power Threshold
CommEnergyIC(0, QStartTh, 0x0AEC); // Reactive Startup Power Threshold
CommEnergyIC(0, QNolTh, 0x0000); // Reactive No-Load Power Threshold
CommEnergyIC(0, MMode, 0x9422); // Metering Mode Configuration. All defaults.
// See pg 31 of datasheet.
CommEnergyIC(0, CSOne, 0x4A34); // Write CSOne, as self calculated
// read CS1 and write the value back
double cs1 = CommEnergyIC(1, CSOne, 0x0000);
CommEnergyIC(0, CSOne, cs1); // Write CSOne, as self calculated
Serial.print("Checksum 1:");
Serial.println(
@ -172,13 +175,17 @@ void ATM90E26_UART::InitEnergyIC() {
CommEnergyIC(
0, AdjStart,
0x5678); // Measurement calibration startup command, registers 31-3A
CommEnergyIC(0, Ugain, 0x352F); // Voltage rms gain
CommEnergyIC(0, IgainL, 0x6E49); // L line current gain
CommEnergyIC(0, Ugain, ugain); // Voltage rms gain
CommEnergyIC(0, IgainL, igainl); // L line current gain
CommEnergyIC(0, Uoffset, 0x0000); // Voltage offset
CommEnergyIC(0, IoffsetL, 0x0000); // L line current offset
CommEnergyIC(0, IoffsetL, 0x000); // L line current offset
CommEnergyIC(0, PoffsetL, 0x0000); // L line active power offset
CommEnergyIC(0, QoffsetL, 0x0000); // L line reactive power offset
CommEnergyIC(0, CSTwo, 0xD294); // Write CSTwo, as self calculated
// read CS2 and write the value back:
double cs2 = CommEnergyIC(1, CSTwo, 0x0000);
CommEnergyIC(0, CSTwo, cs2); // Write CSTwo, as self calculated
Serial.print("Checksum 2:");
Serial.println(

@ -92,7 +92,7 @@ public:
double GetPowerFactor();
double GetImportEnergy();
double GetExportEnergy();
void InitEnergyIC();
void InitEnergyIC(double ugain, double lgain, double igainl, double vSagTh);
unsigned short GetSysStatus();
unsigned short GetMeterStatus();
@ -100,6 +100,7 @@ private:
unsigned short CommEnergyIC(unsigned char RW, unsigned char address,
unsigned short val);
Stream *ATM_UART;
double _lgain, _ugain;
};
#endif

@ -19,12 +19,21 @@ extra_scripts = pre:envSetup.py
monitor_speed = 9600
upload_port = COM9
[env:prod]
build_flags = -D PROD ${env.build_flags} -D ATM90E26_EIC
lib_deps =
SPI
knolleary/pubsubclient
bblanchon/ArduinoJson @ ^6
paulstoffregen/OneWire@^2.3.8
milesburton/DallasTemperature@^3.11.0
build_src_filter = +<transformerMonitor.cpp> -<.git/> -<.svn/> -<tests/>
[env:dev]
build_flags = -D DEV ${env.build_flags} -D ATM90E26_EIC
build_flags = -D dev ${env.build_flags} -D ATM90E26_EIC
lib_deps =
SPI
knolleary/pubsubclient
https://github.com/whatnick/ATM90E26_Arduino
bblanchon/ArduinoJson @ ^6
paulstoffregen/OneWire@^2.3.8
milesburton/DallasTemperature@^3.11.0
@ -38,8 +47,6 @@ build_src_filter = -<*> +<store-config.cpp> -<.git/> -<.svn/> -<tests/>
build_flags = -D DEV ${env.build_flags}
lib_deps =
knolleary/pubsubclient
https://github.com/CircuitSetup/ATM90E36
https://github.com/whatnick/ATM90E26_Arduino
bblanchon/ArduinoJson @ ^6.21.3
paulstoffregen/OneWire@^2.3.8
milesburton/DallasTemperature@^3.11.0

@ -10,10 +10,16 @@ unsigned long lastMillis = 0;
// const char* test_client_cert = ""; //to verify the client
void setup()
{
#if defined(DEV)
Serial.begin(9600);
#endif // DEV
delay(1000);
setupEnergyMonitor();
// set LED pins
// setup LED pins
pinMode(PIN_RED, OUTPUT);
pinMode(PIN_GREEN, OUTPUT);
pinMode(PIN_BLUE, OUTPUT);
@ -23,10 +29,25 @@ void setup()
delay(1000);
// create data queue
eicDataQueue = xQueueCreate(60, sizeof(xformerMonitorData));
eicDataQueue = xQueueCreate(6000, sizeof(xformerMonitorData));
if (eicDataQueue == 0)
{
#if defined(DEV)
printf("Failed to create queue= %p\n", eicDataQueue);
#endif // DEV
eicDataQueue = xQueueCreate(600, sizeof(xformerMonitorData));
if (eicDataQueue == 0)
{
// halt execution
while (1) {}
}
}
// configure time
// TODO: make dst and timezone configurable
@ -59,22 +80,32 @@ void setup()
}
// connect connects to the WiFi and restarts it
// TODO: set LED red when not connected, green when connected
void connect()
{
#if defined(DEV)
// connect to the WiFi network
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
#endif // DEV
WiFi.begin(ssid, wifiPassword);
// attempt to connect to Wifi network:
while (WiFi.status() != WL_CONNECTED)
{
setLEDColor(255, 0, 0);
#if defined(DEV)
Serial.print(".");
#endif // DEV
// wait 1 second for re-trying
delay(1000);
}
#if defined(DEV)
Serial.print("Connected to ");
Serial.println(ssid);
@ -85,14 +116,21 @@ void connect()
// we are using the ESP32's MAC address to provide a unique ID
Serial.printf("The client %s connects to the public mqtt broker\n", client_id);
#endif // DEV
if (mqttClient.connect(client_id, mqttUser, mqttPass))
{
setLEDColor(0, 255, 0);
#if defined(DEV)
Serial.println("\nconnected!");
#endif // DEV
}
else
{
#if defined(DEV)
Serial.println("\nnot connected to MQTT!");
#endif // DEV
// set LED color to red
setLEDColor(255, 0, 0);
delay(2000);
@ -138,7 +176,7 @@ void loop()
strftime(timeBuffer, sizeof(timeBuffer), "%FT%TZ", mqttSensorData.timeInfo);
delay(100);
// if sysStatus is not reporting, or if there is no current
if (mqttSensorData.sysStatus == 0xFFFF || mqttSensorData.lineCurrent <= 0.05)
if (mqttSensorData.sysStatus == 0xFFFF || mqttSensorData.lineCurrent < 0.5 || mqttSensorData.lineVoltage <= 90)
{
// Sensor is not working - set LED red
setLEDColor(255, 0, 0);
@ -161,8 +199,11 @@ void loop()
mqttJsonData["time"] = timeBuffer;
mqttJsonData["meterStatus"] = mqttSensorData.meterStatus;
mqttJsonData["sysStatus"] = mqttSensorData.sysStatus;
mqttJsonData["frequency"] = mqttSensorData.freq;
// * Voltage and current
mqttJsonData["voltage"] = mqttSensorData.lineVoltage;
@ -203,9 +244,13 @@ void loop()
void setupMQTTClient()
{
#if defined(DEV)
Serial.print("Setting MQTT server: ");
Serial.println(mqttServer);
#endif // DEV
mqttClient.setClient(wifiClient);
mqttClient.setServer(mqttServer, mqttPort);
@ -221,7 +266,9 @@ void setupEnergyMonitor()
// Serial RX pin
// Serial TX pin
ATMSerial.begin(9600, SERIAL_8N1, PIN_SerialATM_RX, PIN_SerialATM_TX);
eic.InitEnergyIC();
eic.InitEnergyIC(ugain, lgain, igainl, vsag);
delay(1000);
}
@ -241,10 +288,13 @@ void readEICData(void *pvParameters)
for (;;)
{
static int secondsPassed = 0;
// global time variable
time_t now;
// Get the current time and store it in a variable
time(&now);
// set {"time":"2021-05-04T13:13:04Z"}
sensorData.timeInfo = gmtime(&now);
@ -263,27 +313,31 @@ void readEICData(void *pvParameters)
vTaskDelay(10);
// in hex
sensorData.meterStatus = eic.GetMeterStatus();
sensorData.meterStatus = eic.GetMeterStatus();
vTaskDelay(10);
sensorData.sysStatus = eic.GetSysStatus();
vTaskDelay(10);
sensorData.lineVoltage = eic.GetLineVoltage();
vTaskDelay(10);
sensorData.lineCurrent = eic.GetLineCurrent();
sensorData.lineCurrent = eic.GetLineCurrent();
vTaskDelay(10);
sensorData.power.factor = eic.GetPowerFactor();
vTaskDelay(10);
sensorData.power.active = eic.GetActivePower();
vTaskDelay(10);
sensorData.freq = eic.GetFrequency();
vTaskDelay(10);
// send data to queue
xQueueSend(eicDataQueue, &sensorData, portMAX_DELAY);
vTaskDelay(1000);
secondsPassed++;
}

Loading…
Cancel
Save