Skip to content

Commit

Permalink
send all data in one request, read CT ratio from meter
Browse files Browse the repository at this point in the history
  • Loading branch information
LeoDJ committed Jun 14, 2021
1 parent eedcb01 commit 1b7eae8
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 65 deletions.
1 change: 1 addition & 0 deletions software/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.vscode/settings.json

README
%AppData%
Expand Down
5 changes: 2 additions & 3 deletions software/src/globals.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
#pragma once
#include <stdint.h>

#include "secrets.h"
#include "secrets.h" // don't forget to create secrets.h based on the .sample file

#define DEBUG Serial1

#define UPDATE_INTERVAL 5000 // ms

#define CT_RATIO (40/5) // calculated current transformer ratio (e.g. 40:5 -> 8)
#define MODUBS_SERIAL Serial3
#define MODBUS_BAUD 38400
#define MODBUS_ADDR 1


// put InfluxDB credentials into secrets.h

#define SPI2_MOSI PB15
#define SPI2_MISO PB14
Expand Down
75 changes: 36 additions & 39 deletions software/src/janitza.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,16 @@ const char *phaseTagStr[] = {






#define REG_SERIAL 911
#define REG_CT_PRIM 600
#define REG_CT_SEC 601


#define EMPTY {0, 1, false, INT, P_ALL, NULL}
#define LONG_SPACER EMPTY


// TODO: fix addresses (currently not needed)
// array is aligned with line numbers for easier referencing
registerDefinition_t registerDefinition[] = {
//addr multipl CTratio type phase name
{ 200, 10, false, INT, P_L1, "U_LN" },
Expand Down Expand Up @@ -142,30 +142,30 @@ registerDefinition_t registerDefinition[] = {
{ 1, 10, false, INT, P_L3, "U_LN_Harm11" },
{ 1, 10, false, INT, P_L3, "U_LN_Harm13" },
{ 1, 10, false, INT, P_L3, "U_LN_Harm15" },
{ 1, 1, false, INT, P_L1, "I_Harm1" },
{ 1, 1, false, INT, P_L1, "I_Harm3" },
{ 1, 1, false, INT, P_L1, "I_Harm5" },
{ 1, 1, false, INT, P_L1, "I_Harm7" },
{ 1, 1, false, INT, P_L1, "I_Harm9" },
{ 1, 1, false, INT, P_L1, "I_Harm11" },
{ 1, 1, false, INT, P_L1, "I_Harm13" },
{ 1, 1, false, INT, P_L1, "I_Harm15" },
{ 1, 1, false, INT, P_L2, "I_Harm1" },
{ 1, 1, false, INT, P_L2, "I_Harm3" },
{ 1, 1, false, INT, P_L2, "I_Harm5" },
{ 1, 1, false, INT, P_L2, "I_Harm7" },
{ 1, 1, false, INT, P_L2, "I_Harm9" },
{ 1, 1, false, INT, P_L2, "I_Harm11" },
{ 1, 1, false, INT, P_L2, "I_Harm13" },
{ 1, 1, false, INT, P_L2, "I_Harm15" },
{ 1, 1, false, INT, P_L3, "I_Harm1" },
{ 1, 1, false, INT, P_L3, "I_Harm3" },
{ 1, 1, false, INT, P_L3, "I_Harm5" },
{ 1, 1, false, INT, P_L3, "I_Harm7" },
{ 1, 1, false, INT, P_L3, "I_Harm9" },
{ 1, 1, false, INT, P_L3, "I_Harm11" },
{ 1, 1, false, INT, P_L3, "I_Harm13" },
{ 1, 1, false, INT, P_L3, "I_Harm15" },
{ 1, 1, true, INT, P_L1, "I_Harm1" },
{ 1, 1, true, INT, P_L1, "I_Harm3" },
{ 1, 1, true, INT, P_L1, "I_Harm5" },
{ 1, 1, true, INT, P_L1, "I_Harm7" },
{ 1, 1, true, INT, P_L1, "I_Harm9" },
{ 1, 1, true, INT, P_L1, "I_Harm11" },
{ 1, 1, true, INT, P_L1, "I_Harm13" },
{ 1, 1, true, INT, P_L1, "I_Harm15" },
{ 1, 1, true, INT, P_L2, "I_Harm1" },
{ 1, 1, true, INT, P_L2, "I_Harm3" },
{ 1, 1, true, INT, P_L2, "I_Harm5" },
{ 1, 1, true, INT, P_L2, "I_Harm7" },
{ 1, 1, true, INT, P_L2, "I_Harm9" },
{ 1, 1, true, INT, P_L2, "I_Harm11" },
{ 1, 1, true, INT, P_L2, "I_Harm13" },
{ 1, 1, true, INT, P_L2, "I_Harm15" },
{ 1, 1, true, INT, P_L3, "I_Harm1" },
{ 1, 1, true, INT, P_L3, "I_Harm3" },
{ 1, 1, true, INT, P_L3, "I_Harm5" },
{ 1, 1, true, INT, P_L3, "I_Harm7" },
{ 1, 1, true, INT, P_L3, "I_Harm9" },
{ 1, 1, true, INT, P_L3, "I_Harm11" },
{ 1, 1, true, INT, P_L3, "I_Harm13" },
{ 1, 1, true, INT, P_L3, "I_Harm15" },
{ 1, 10, false, INT, P_L1, "THD_U" },
{ 1, 10, false, INT, P_L2, "THD_U" },
{ 1, 10, false, INT, P_L3, "THD_U" },
Expand All @@ -176,9 +176,9 @@ registerDefinition_t registerDefinition[] = {
{ 1, 100, false, INT, P_ALL, "CosPhi" },
{ 1, 1, false, INT, P_ALL, "Rotation" },
{ 1, 1, false, INT, P_ALL, "I_N" },
{ 1, 1, false, INT, P_ALL, "P" },
{ 1, 1, false, INT, P_ALL, "Q" },
{ 1, 1, false, INT, P_ALL, "S" },
{ 1, 1, true, INT, P_ALL, "P" },
{ 1, 1, true, INT, P_ALL, "Q" },
{ 1, 1, true, INT, P_ALL, "S" },
EMPTY, // { 0, 1, true, INT, P_L1, "I_Mean" },
EMPTY, // { 0, 1, true, INT, P_L2, "I_Mean" },
EMPTY, // { 0, 1, true, INT, P_L3, "I_Mean" },
Expand Down Expand Up @@ -313,19 +313,16 @@ registerDefinition_t registerDefinition[] = {
EMPTY,
EMPTY,
EMPTY,
{ 1, 1, false, LONG, P_ALL, "Wp" }, // Wh
{ 1, 1, true, LONG, P_ALL, "Wp" }, // Wh
LONG_SPACER,
{ 1, 1, false, LONG, P_ALL, "Wq" },
{ 1, 1, true, LONG, P_ALL, "Wq" },
LONG_SPACER,
EMPTY,
EMPTY,
{ 1, 1, false, LONG, P_ALL, "Wp_Import" }, // Wh
{ 1, 1, true, LONG, P_ALL, "Wp_Import" }, // Wh
LONG_SPACER,
{ 1, 1, false, LONG, P_ALL, "Wp_Supply" }, // Wh
{ 1, 1, true, LONG, P_ALL, "Wp_Supply" }, // Wh
LONG_SPACER,
};
#define REG_DEF_NUM (sizeof(registerDefinition) / sizeof(registerDefinition[0]))
#define REG_DEF_START_ADDR 200


#define REG_SERIAL 911
#define REG_DEF_START_ADDR 200
71 changes: 48 additions & 23 deletions software/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,29 @@
#include "eth.h"



ModbusMaster mb;
uint32_t _serialNumber;
uint16_t _ctRatio = 1;
EthernetClient client;


void handleHttpResponse() {
// print response from HTTP request
if (client.available()) {
int len = client.available();
uint8_t buf[256];
if (len > 256) {
len = 256;
uint8_t buf[512];
if (len > 512) {
len = 512;
}
client.read(buf, len);

DEBUG.write(buf, len);
if (strncmp((const char *)buf, "HTTP/1.1 204", 12) == 0) {
DEBUG.println("InfluxDB request successful.");
}
else {
DEBUG.println("InfluxDB request failed!");
DEBUG.write(buf, len);
}
}
}

Expand Down Expand Up @@ -51,12 +58,22 @@ void sendInfluxRequest(char *lineProtocolCommand) {
uint32_t readSerialNumber() {
uint8_t ret = mb.readHoldingRegisters(REG_SERIAL, 2);
if (ret != mb.ku8MBSuccess) {
DEBUG.printf("Error reading from ModBus. Status = %02X\n", ret);
DEBUG.printf("Error reading from ModBus in readSerialNumber. Status = %02X\n", ret);
return 0;
}
return mb.getResponseBuffer(0) << 16 | mb.getResponseBuffer(1);
}

uint16_t readCtRatio() {
uint8_t ret = mb.readHoldingRegisters(REG_CT_PRIM, 2);
if (ret != mb.ku8MBSuccess) {
DEBUG.printf("Error reading from ModBus in readCtRatio. Status = %02X\n", ret);
return 0;
}
// calculate CT ratio, only integers supported currently
return mb.getResponseBuffer(0) / mb.getResponseBuffer(1);
}

registerDefinition_t *getRegDef(uint16_t address) {
// currently the definition is still continuous, so we don't actually have to search through it
if (address >= REG_DEF_START_ADDR && address <= REG_DEF_START_ADDR + REG_DEF_NUM) {
Expand All @@ -67,7 +84,7 @@ registerDefinition_t *getRegDef(uint16_t address) {
}
}

#define MB_CHUNK_SIZE 64
#define MB_CHUNK_SIZE 32

bool modbusReadBulk(int16_t *destBuf, uint16_t startAddr, uint16_t count) {
int iterations = (count + (MB_CHUNK_SIZE - 1)) / MB_CHUNK_SIZE; // division, but rounded up
Expand All @@ -78,40 +95,40 @@ bool modbusReadBulk(int16_t *destBuf, uint16_t startAddr, uint16_t count) {
mbCount = count % MB_CHUNK_SIZE;
}

DEBUG.printf("Reading Modbus Addr: %d, Count: %d\n", mbStart, mbCount);
DEBUG.printf("Reading Modbus %d/%d (Addr: %d, Count: %d) \r", i+1, iterations, mbStart, mbCount);

uint8_t ret = mb.readHoldingRegisters(mbStart, mbCount);

if (ret != mb.ku8MBSuccess) {
DEBUG.printf("Error reading from ModBus. Status = %02X\n", ret);
DEBUG.printf("\nError reading from ModBus. Status = %02X\n", ret);
return false;
}

for (int j = 0; j < mbCount; j++) {
destBuf[i * MB_CHUNK_SIZE + j] = mb.getResponseBuffer(j);
}
}
DEBUG.printf("\n");
return true;

}

int16_t modbusBuf[REG_DEF_NUM];
char influxQueryBuf[512*10];

void readMeter() {
// readMeterChunk(200, 64);
bool success = modbusReadBulk(modbusBuf, 200, 226);

if (!success) {
DEBUG.printf("Error reading bulk from ModBus\n");
return;
}

char influxQueryBuf[512];
int influxQueryLen = 0;

for (int phase = 0; phase < P_TAG_NUM; phase++) {
const char* phaseStr = phaseTagStr[phase];

int influxQueryLen = 0;
influxQueryLen += sprintf(influxQueryBuf + influxQueryLen, "%s", INFLUX_MEASUREMENT); // measurement name
influxQueryLen += sprintf(influxQueryBuf + influxQueryLen, ",serial=%d,phase=%s ", _serialNumber, phaseStr); // print tags here

Expand All @@ -134,21 +151,18 @@ void readMeter() {

// apply current transformer ratio if needed
if (regDef->applyCtRatio) {
val *= (float)CT_RATIO;
val *= (float)_ctRatio;
}

influxQueryLen += sprintf(influxQueryBuf + influxQueryLen, "%s=%g,", regDef->influxStr, val);
}
}

influxQueryBuf[influxQueryLen - 1] = 0; // clear trailing comma

DEBUG.write(influxQueryBuf);
DEBUG.println();

sendInfluxRequest(influxQueryBuf);
handleHttpResponse();
influxQueryBuf[influxQueryLen - 1] = '\n'; // replace trailing comma with newline
}
// DEBUG.write(influxQueryBuf);
DEBUG.print("Sending InfluxDB Request... ");
sendInfluxRequest(influxQueryBuf);

}

Expand All @@ -159,9 +173,19 @@ void setup() {
MODUBS_SERIAL.begin(MODBUS_BAUD);
mb.begin(MODBUS_ADDR, MODUBS_SERIAL);

_serialNumber = readSerialNumber();
DEBUG.printf("Serial: %d\n", _serialNumber);
// readMeter();
while (_serialNumber == 0) {
_serialNumber = readSerialNumber();
if (_serialNumber != 0) {
DEBUG.printf("Serial: %d\n", _serialNumber);
}
else {
DEBUG.printf("Error: Could not read serial number, make sure the meter is connected and address and baud rate are correct. Retrying in 5s...\n");
delay(5000);
}
}

_ctRatio = readCtRatio();
DEBUG.printf("CT Ratio: %d\n", _ctRatio);

initEthernet();
connectEthernet();
Expand All @@ -177,4 +201,5 @@ void loop() {
readMeter();
}

handleHttpResponse();
}

0 comments on commit 1b7eae8

Please sign in to comment.