MeterBusPowerMaster/meterBusMaster.cpp

276 lines
6.1 KiB
C++
Raw Normal View History

2014-01-17 22:00:39 +01:00
#include <Arduino.h>
#include <stdio.h>
#include <WString.h>
#include <Print.h>
#include <HardwareSerial.h>
#include "meterBusMaster.h"
// #include "config.h"
#include "fatal.h"
uint8_t charToNibble(char i) {
uint8_t r = 99;
if ((i >= '0') && (i <= '9')) {
r = i - '0';
} else if ((i >= 'a') && (i <= 'f')) {
r = i - 'a' + 10;
} else if ((i >= 'A') && (i <= 'F')) {
r = i - 'A' + 10;
}
return r;
}
uint16_t stringToUInt8(String i, uint8_t index) {
uint16_t r = 999;
char b0 = i[index];
uint8_t c0 = charToNibble(b0);
char b1 = i[index + 1];
uint8_t c1 = charToNibble(b1);
if ((c0 <= 15) && (c1 <= 15)) {
r = (c0 << 4) | c1;
}
return r;
}
// =====================================================================================================
2014-02-02 16:39:08 +01:00
String CalibrationSupport::exec(String params) {
2014-02-03 23:04:57 +01:00
String res = "failed";
MeterBusMaster *mbm = (MeterBusMaster*)m_meterBusMaster;
if (params.equalsIgnoreCase("sample") && enable) {
mbm->sample();
res = "done";
} else if (params.equalsIgnoreCase("hold") && enable) {
mbm->hold();
res = "done";
} else if (params.equalsIgnoreCase("enable") && ! enable) {
enable = true;
mbm->m_calibration = true;
res = "enabled";
} else if (params.equalsIgnoreCase("disable") && enable) {
enable = false;
mbm->m_calibration = false;
res = "disabled";
}
return res;
2014-02-02 16:39:08 +01:00
}
2014-01-18 15:51:27 +01:00
String MeasureCurrent::exec(String params) {
int currentInVal = analogRead(CURRENT_IN);
2014-01-19 00:37:40 +01:00
int current = ((double)currentInVal * U_UNIT) / R_SHUNT;
2014-01-18 15:51:27 +01:00
2014-01-19 00:37:40 +01:00
return String() + current + String("mA");
2014-01-18 15:51:27 +01:00
}
2014-01-17 22:00:39 +01:00
String SendOctets::exec(String params) {
bool err = false;;
uint16_t sendBufLen = 0;
uint8_t *sendBuffer = m_meterBusMaster->getSendBuffer();
if (sendBuffer == 0) {
err = true;
} else {
uint16_t n;
for (uint16_t j = 0; j < params.length(); j+=3) {
n = stringToUInt8(params, j);
if (n == 999) {
err = true;
break;
}
if (sendBufLen >= SEND_BUFFER_SIZE)
fatal(FATAL_BUFFER_OVERFLOW + 2);
*(sendBuffer+sendBufLen) = n;
sendBufLen++;
}
}
if (err) {
return "error";
} else {
m_meterBusMaster->sendBufferReady(sendBufLen, this);
return "success";
}
}
void SendOctets::sendResponse(uint8_t *responseBuffer, uint16_t responseBufferLength) {
Print *out = m_stream;
out->print("SO RESP: ");
uint16_t i = 0;
while (true) {
if (responseBuffer[i] <= 0x0f) {
out->print("0");
}
out->print(responseBuffer[i], HEX);
out->print(" ");
i++;
if (i == responseBufferLength) {
break;
}
}
out->println("");
}
void SendOctets::sendError(uint8_t code) {
switch (code) {
case 1:
m_stream->println("SO RESP: no resp.");
break;
}
}
2014-02-02 16:39:08 +01:00
2014-01-17 22:00:39 +01:00
// =====================================================================================================
2014-01-18 15:51:27 +01:00
MeterBusMaster::MeterBusMaster() : m_sendOctets(this), m_measureCurrent(this),
2014-02-02 16:39:08 +01:00
m_calibrationSupport(this),
2014-01-17 22:00:39 +01:00
m_cmdReadyToSend(false), m_cmdReadyFromRecv(false), m_expectResponse(false),
2014-02-03 23:04:57 +01:00
m_sendBufLen(0), m_recvBufLen(0), m_retransmitCount(0), m_responseCallback(0),
m_sampling(true), m_calibration(false) {
2014-01-17 22:00:39 +01:00
pinMode(RX_EN_PIN, OUTPUT);
digitalWrite(RX_EN_PIN, RX_DISABLE);
Serial1.begin(2400, SERIAL_8E1);
}
2014-01-18 15:51:27 +01:00
void MeterBusMaster::begin(CmdServer *cmdServer) {
m_sendOctets.registerYourself(cmdServer);
2014-02-03 23:04:57 +01:00
m_measureCurrent.registerYourself(cmdServer);
2014-02-02 16:39:08 +01:00
m_calibrationSupport.registerYourself(cmdServer);
2014-01-18 15:51:27 +01:00
}
2014-01-17 22:00:39 +01:00
uint8_t *MeterBusMaster::getSendBuffer() {
return m_expectResponse ? 0 : m_sendBuffer;
}
void MeterBusMaster::sendBufferReady(uint16_t sendBufLen, ResponseCallback *responseCallback) {
m_cmdReadyToSend = true;
m_retransmitCount = 0;
m_sendBufLen = sendBufLen;
m_responseCallback = responseCallback;
}
void MeterBusMaster::prepareResponse(bool err, uint8_t in) {
static int16_t expectedChars = -1;
static uint8_t state = 0;
if (err) {
if (m_responseCallback != 0) {
m_responseCallback->sendError(1);
}
expectedChars = 0;
state = 0;
m_expectResponse = false;
m_responseCallback = 0;
} else {
switch (state) {
case 0:
m_recvBufLen = 0;
if (in == 0xe5) {
state = 2;
expectedChars = 0;
} else if (in == 0x10) {
state = 2;
expectedChars = 4;
} else if (in == 0x68) {
state = 1;
expectedChars = -1;
}
break;
case 1:
expectedChars = (int16_t)in;
expectedChars += 4;
state = 2;
break;
case 2:
expectedChars--;
break;
}
if (m_recvBufLen >= RECEIVE_BUFFER_SIZE)
fatal(FATAL_BUFFER_OVERFLOW + 1);
m_recvBuffer[m_recvBufLen] = in;
m_recvBufLen++;
if (expectedChars == 0) {
if (m_responseCallback != 0) {
m_responseCallback->sendResponse(m_recvBuffer, m_recvBufLen);
}
m_expectResponse = false;
state = 0;
m_responseCallback = 0;
}
}
}
void MeterBusMaster::sample() {
if (! m_sampling) {
m_sampling = true;
digitalWrite(RX_EN_PIN, RX_DISABLE);
}
}
void MeterBusMaster::hold() {
if (m_sampling) {
m_sampling = false;
digitalWrite(RX_EN_PIN, RX_ENABLE);
}
}
void MeterBusMaster::exec() {
2014-02-03 23:04:57 +01:00
if (! m_calibration) {
static unsigned long cmdSendTime = 0;
if (m_cmdReadyToSend) {
sample();
Serial1.write(m_sendBuffer, m_sendBufLen);
Serial1.flush();
hold();
m_cmdReadyToSend = false;
m_expectResponse = true;
cmdSendTime = millis();
}
2014-01-17 22:00:39 +01:00
2014-02-03 23:04:57 +01:00
if (! m_expectResponse) {
sample();
}
2014-01-17 22:00:39 +01:00
2014-02-03 23:04:57 +01:00
// timeout
if (m_expectResponse && ((millis() - cmdSendTime) > RESPONSE_TIMEOUT)) {
m_retransmitCount++;
if (m_retransmitCount > 2) {
m_expectResponse = false;
prepareResponse(true, 0);
} else {
m_cmdReadyToSend = true;
}
2014-01-17 22:00:39 +01:00
}
2014-02-03 23:04:57 +01:00
int serialInChar = Serial1.read();
2015-05-29 10:16:51 +02:00
if (serialInChar != -1) {
Serial.print("Recv: "); Serial.println(serialInChar, 16);
}
2014-02-03 23:04:57 +01:00
if ((serialInChar != -1) && m_expectResponse) {
prepareResponse(false, (uint8_t)serialInChar);
}
2014-01-17 22:00:39 +01:00
}
}
// =====================================================================================================