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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// =====================================================================================================
|