3 Commits

Author SHA1 Message Date
hg
13d19d4e15 meterbusclient is working, SND_NKE will be answered 2014-03-09 00:25:48 +01:00
hg
854d2f202a mbc seems to work partly now, finally 2014-03-08 20:57:17 +01:00
hg
b333be0cd9 meterbus integrated but not working 2014-03-08 19:24:27 +01:00
10 changed files with 444 additions and 96 deletions

View File

@ -102,20 +102,22 @@ void Config::setUChar(int pos, unsigned char value) {
void Config::initialize() {
if (! Config::isInitialized()) {
if (! isInitialized()) {
Serial.println(getResource(CONFIG_INIT_KEY));
Config::setFloat(Config::THERMOMETER_ALPHA, 1.0);
Config::setULong(Config::THERMOMETER_PERIOD, 1000);
setFloat(THERMOMETER_ALPHA, 1.0);
setULong(THERMOMETER_PERIOD, 1000);
for (int i = 0; i < 4; i++) {
Config::setFloat(Config::THERMOMETER_CAL[i], 1.0);
setFloat(THERMOMETER_CAL[i], 1.0);
}
Config::setBool(Config::THERMOMETER_DEBUG, true);
Config::setBool(Config::THERMOMETER_INFO, true);
setBool(THERMOMETER_DEBUG, false);
setBool(THERMOMETER_INFO, false);
Config::setUChar(Config::METERBUSCLIENT_ADDRESS, 0);
setUChar(METERBUSCLIENT_ADDRESS, 0);
setBool(METERBUSCLIENT_DEBUG, false);
setBool(METERBUSCLIENT_INFO, false);
Config::setMagic();
setMagic();
}
}

View File

@ -55,6 +55,9 @@ namespace Config {
const int THERMOMETER_DEBUG = 28; // 1
const int THERMOMETER_INFO = 29; // 1
const int METERBUSCLIENT_ADDRESS = 30; // 1
const int METERBUSCLIENT_DEBUG = 31; // 1
const int METERBUSCLIENT_INFO = 32; // 1
bool getBool(int pos);

View File

@ -12,6 +12,78 @@
//String TEXT;
const String TEXT_RESOURCES[] = {
"Text1",
"PeriodMeasure (ms): ",
"Alpha: ",
"Calibration: ",
"Info: ",
"Debug: ",
"COMPILE_TIME_DEBUG: ",
"TimeOuts: ",
"Cycles: ",
"Period (ms): ",
"Alpha: ",
"index: ",
"cal: ",
"t: ",
"ts: ",
", ",
" enable : enable the calibration mode",
" disable : disable the calibration mode",
" show : show parameters for calibration process",
" r : set value of calibration resistor",
" start <0..3>: start calibration on channel",
" stop <0..3>: stop calibration on channel",
" enabled : ",
" r_cal : ",
"setTemperature: i=",
"t=",
"t_smoothed=",
"CONF: ",
"MODE: ",
"Initializing EEPROM",
"State 0",
"Switching to State 1",
"Switching to State 10",
"State 9",
"Timeout: ",
"State 10",
"No, no, we are in calibration high mode, so directly switch to state 20",
"Switching to state 11",
"r_avg on channel ",
"calibration factor: ",
"Calibration stopped",
"Save calibration factor for channel ",
": ",
"HELP List this help for all commands",
"command not found",
"Thermometer configuration operations",
"Show thermometer measurement values",
"Thermometer calibration operations",
"No, no, we are in calibration zero mode, so directly switch to state 20",
"MeterBus Client Configuration",
"Invalid frame",
"No valid frame available",
"Invalid checksum",
"Not for me but for ",
"Unhandled frame",
"s: ",
"l: ",
"c: ",
"a: ",
"ci: ",
"u: ",
" ",
"frames: ",
"my frames: ",
"invalid frames: ",
"invalid checksum: ",
"mbus address: ",
};
const String& getResource(uint8_t key) {
//TEXT = String("T") + key + String(": ");

View File

@ -62,62 +62,23 @@ const uint8_t THERMVALUES_HELP_KEY = 46;
const uint8_t THERMCALIBRATE_HELP_KEY = 47;
const uint8_t CALIBRATION_ZEOR_MODE_HINT_KEY = 48;
const uint8_t MBC_CONFIG_HELP_KEY = 49;
const String TEXT_RESOURCES[] = {
"Text1",
"PeriodMeasure (ms): ",
"Alpha: ",
"Calibration: ",
"Info: ",
"Debug: ",
"COMPILE_TIME_DEBUG: ",
"TimeOuts: ",
"Cycles: ",
"Period (ms): ",
"Alpha: ",
"index: ",
"cal: ",
"t: ",
"ts: ",
", ",
" enable : enable the calibration mode",
" disable : disable the calibration mode",
" show : show parameters for calibration process",
" r : set value of calibration resistor",
" start <0..3>: start calibration on channel",
" stop <0..3>: stop calibration on channel",
" enabled : ",
" r_cal : ",
"setTemperature: i=",
"t=",
"t_smoothed=",
"CONF: ",
"MODE: ",
"Initializing EEPROM",
"State 0",
"Switching to State 1",
"Switching to State 10",
"State 9",
"Timeout: ",
"State 10",
"No, no, we are in calibration high mode, so directly switch to state 20",
"Switching to state 11",
"r_avg on channel ",
"calibration factor: ",
"Calibration stopped",
"Save calibration factor for channel ",
": ",
"HELP List this help for all commands",
"command not found",
"Thermometer configuration operations",
"Show thermometer measurement values",
"Thermometer calibration operations",
"No, no, we are in calibration zero mode, so directly switch to state 20",
"MeterBus Client Configuration",
};
const uint8_t MBC_INVALID_FRAME_KEY = 50;
const uint8_t MBC_NO_VALID_FRAME_KEY = 51;
const uint8_t MBC_INVALID_CHECKSUM_KEY = 52;
const uint8_t MBC_NOT_FOR_ME_KEY = 53;
const uint8_t MBC_UNHANDLED_FRAME_KEY = 54;
const uint8_t MBC_START_DELIMITER_KEY = 55;
const uint8_t MBC_LENGTH_KEY = 56;
const uint8_t MBC_CFIELD_KEY = 57;
const uint8_t MBC_ADDRESS_KEY = 58;
const uint8_t MBC_CIFIELD_KEY = 59;
const uint8_t MBC_USERDATA_KEY = 60;
const uint8_t SPACE_KEY = 61;
const uint8_t MBC_FRAMES_KEY = 62;
const uint8_t MBC_MYFRAMES_KEY = 63;
const uint8_t MBC_INVALID_FRAMES_KEY = 64;
const uint8_t MBC_INVALID_CHECKSUM_CNT_KEY = 65;
const uint8_t MBC_ADDRESS_LONG_KEY = 66;
const String& getResource(uint8_t key);

View File

@ -5,33 +5,29 @@
#include "thermometer.h"
#include "Config.h"
#include "spi.h"
#include "meterBusClient.h"
#define ENABLE_CONFIGURATION_INVALID_CMD 1
static CmdServer cmdServer(&Serial);
#ifdef ENABLE_CONFIGURATION_INVALID_CMD
static ConfigInvalidateCmd configInvalidateCmd;
#endif
static ConfigInvalidateCmd configInvalidateCmd;
static Uptime uptime;
static Thermometer thermometer;
static MeterBusClient meterBusClient;
void setup() {
Serial.begin(9600);
Config::initialize();
spiInit();
cmdServer.begin();
#ifdef ENABLE_CONFIGURATION_INVALID_CMD
configInvalidateCmd.registerYourself(&cmdServer);
#endif
uptime.begin(&cmdServer);
thermometer.begin(&cmdServer);
meterBusClient.begin(&cmdServer, &thermometer);
}
@ -39,4 +35,5 @@ void loop() {
cmdServer.exec();
uptime.exec();
thermometer.exec();
meterBusClient.exec();
}

View File

@ -1,10 +1,11 @@
#include <avr/interrupt.h>
#include"fatal.h"
#include <Arduino.h>
void fatal(uint8_t code) {
// cli();
// do something with the code and somehow show that there is a problem
Serial.print("Fatal: "); Serial.println(code);
while (1);
}

View File

@ -5,20 +5,65 @@
* Author: wn
*/
#include "meterBusClient.h"
MeterBusClient::MeterBusClient() : m_address(0) {
const bool MBC_COMPILE_TIME_DEBUG = false;
String MeterBusClientConfig::exec(String params) {
String res = "done";
int space = params.indexOf(' ');
String p1 = "";
char pb1[128];
if (space != -1) {
params.toCharArray(pb1, 128, space+1);
}
if (params.startsWith("a ") && (space != -1)) {
unsigned int a = atoi(pb1);
m_meterBusClient->setAddress(a);
} else if (params.startsWith("debug ") && (space != -1)) {
bool b = (strcmp(pb1, "on") == 0);
m_meterBusClient->setDebug(b);
} else if (params.startsWith("info ") && (space != -1)) {
bool b = (strcmp(pb1, "on") == 0);
m_meterBusClient->setInfo(b);
} else if (params.startsWith("show")) {
Serial.print(getResource(MBC_FRAMES_KEY)); Serial.print(m_meterBusClient->m_frameCnt); Serial.println();
Serial.print(getResource(MBC_MYFRAMES_KEY)); Serial.print(m_meterBusClient->m_myFrameCnt); Serial.println();
Serial.print(getResource(MBC_INVALID_FRAMES_KEY)); Serial.print(m_meterBusClient->m_invalidFrameCnt); Serial.println();
Serial.print(getResource(MBC_INVALID_CHECKSUM_CNT_KEY)); Serial.print(m_meterBusClient->m_invalidChecksum); Serial.println();
Serial.print(getResource(MBC_ADDRESS_LONG_KEY)); Serial.print(m_meterBusClient->getAddress()); Serial.println();
} else {
res = "subcommand not found";
}
return res;
}
MeterBusClient::MeterBusClient() : m_meterBusClientConfig(this), m_address(0),
m_frameCnt(0), m_myFrameCnt(0), m_invalidFrameCnt(0), m_invalidChecksum(0) {
}
void MeterBusClient::begin(CmdServer *cmdServer) {
void MeterBusClient::begin(CmdServer *cmdServer, Thermometer *thermometer) {
m_meterBusClientConfig.registerYourself(cmdServer);
m_thermometer = thermometer;
Serial3.begin(1200);
setAddress(Config::getUChar(Config::METERBUSCLIENT_ADDRESS));
}
void MeterBusClient::setAddress(unsigned char a) {
@ -30,6 +75,24 @@ unsigned char MeterBusClient::getAddress() {
return m_address;
}
void MeterBusClient::setDebug(bool b) {
Config::setBool(Config::METERBUSCLIENT_DEBUG, b);
m_debug = b;
}
bool MeterBusClient::getDebug() {
return m_debug;
}
void MeterBusClient::setInfo(bool b) {
Config::setBool(Config::METERBUSCLIENT_INFO, b);
m_info = b;
}
bool MeterBusClient::getInfo() {
return m_info;
}
/*
@ -44,7 +107,7 @@ unsigned char MeterBusClient::getAddress() {
*
* Control Frame:
* Start 68h
* Length
* Length = 3
* Length
* Start 68h
* C-Field
@ -74,24 +137,197 @@ unsigned char MeterBusClient::getAddress() {
*/
void MeterBusClient::exec() {
static uint8_t state = 0;
bool done = false;
if (Serial3.available()) {
int chi;
while ((chi = Serial3.read()) != -1) {
char ch = (char) chi;
switch (state) {
case 0:
break;
}
if (done) {
}
}
bool isChecksumValid(MeterBusFrame frame) {
unsigned char ctrlsum = frame.aField + frame.cField + frame.ciField;
for (int i = 0; i < (frame.length - 3); i++) {
ctrlsum += frame.userData[i];
}
return (ctrlsum == frame.checksum);
}
void MeterBusClient::handleFrame() {
m_frameCnt++;
if (! isChecksumValid(m_frame)) {
Serial.println(getResource(MBC_INVALID_CHECKSUM_KEY));
m_invalidChecksum++;
} else if (m_frame.aField != getAddress()) {
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.print(getResource(MBC_NOT_FOR_ME_KEY)); Serial.print((int)m_frame.aField, 16); Serial.println();}
} else {
m_myFrameCnt++;
// handle the frame
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.print(getResource(MBC_START_DELIMITER_KEY)); Serial.println(m_frame.startDelimiter, 16);}
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.print(getResource(MBC_LENGTH_KEY)); Serial.println(m_frame.length, 16);}
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.print(getResource(MBC_CFIELD_KEY)); Serial.println(m_frame.cField, 16);}
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.print(getResource(MBC_ADDRESS_KEY)); Serial.println(m_frame.aField, 16);}
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.print(getResource(MBC_CIFIELD_KEY)); Serial.println(m_frame.ciField, 16);}
if (m_frame.length > 3) {
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.print(getResource(MBC_USERDATA_KEY));}
for (unsigned char i = 0; i < (m_frame.length - 3); i++) {
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.print(m_frame.userData[i], 16);}
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.print(getResource(SPACE_KEY));}
}
if (MBC_COMPILE_TIME_DEBUG && getDebug()) { Serial.println();}
}
if (m_frame.startDelimiter == 0x10) {
if (m_frame.cField == 0x40) {
SND_NKE();
} else if (m_frame.cField == 0x5b) {
REQ_UD2();
} else {
Serial.println(getResource(MBC_UNHANDLED_FRAME_KEY));
}
}
}
}
typedef enum {
STATE_START, STATE_IDLE, STATE_SHORT_FRAME, STATE_LONG_CTRL_FRAME, STATE_HANDLE, STATE_INVALID, STATE_DONE
} e_meterBusClientState;
typedef enum {
SUBSTATE_LENGTH, SUBSTATE_LENGTH_REPEAT, SUBSTATE_START_REPEAT, SUBSTATE_C_FIELD, SUBSTATE_A_FIELD, SUBSTATE_CI_FIELD,
SUBSTATE_USERDATA, SUBSTATE_CHECKSUM, SUBSTATE_STOP
} e_meterBusClientSubState;
void MeterBusClient::exec() {
static e_meterBusClientState state = STATE_IDLE;
static e_meterBusClientSubState subState = SUBSTATE_LENGTH;
static unsigned char userDataCnt = 0;
int chi = Serial3.read();
char ch = (char) chi;
switch (state) {
case STATE_START:
m_frame.startDelimiter = 0;
m_frame.length = 0;
m_frame.cField = 0;
m_frame.aField = 0;
m_frame.ciField = 0;
//memset(m_frame.userData, 0, sizeof(m_frame.userData));
m_frame.valid = false;
state = STATE_IDLE;
break;
case STATE_IDLE:
if (chi != -1) {
if (ch == 0x10) {
m_frame.startDelimiter = 0x10;
state = STATE_SHORT_FRAME;
subState = SUBSTATE_C_FIELD;
} else if (ch == 0x68) {
m_frame.startDelimiter = 0x68;
state = STATE_LONG_CTRL_FRAME;
subState = SUBSTATE_LENGTH;
} else {
state = STATE_INVALID;
}
}
break;
case STATE_SHORT_FRAME:
if (chi != -1) {
if (subState == SUBSTATE_C_FIELD) {
m_frame.cField = ch;
subState = SUBSTATE_A_FIELD;
} else if (subState == SUBSTATE_A_FIELD) {
m_frame.aField = ch;
subState = SUBSTATE_CHECKSUM;
} else if (subState == SUBSTATE_CHECKSUM) {
m_frame.checksum = ch;
subState = SUBSTATE_STOP;
} else if (subState == SUBSTATE_STOP) {
if (ch == 0x16) {
m_frame.valid = true;
state = STATE_HANDLE;
} else {
state = STATE_INVALID;
}
}
}
break;
case STATE_LONG_CTRL_FRAME:
if (chi != -1) {
if (subState == SUBSTATE_LENGTH) {
m_frame.length = ch;
if ((m_frame.length < 3) || (m_frame.length > 252)) {
state = STATE_INVALID;
} else {
subState = SUBSTATE_LENGTH_REPEAT;
}
} else if (subState == SUBSTATE_LENGTH_REPEAT) {
if (ch == m_frame.length) {
subState = SUBSTATE_START_REPEAT;
} else {
state = STATE_INVALID;
}
} else if (subState == SUBSTATE_START_REPEAT) {
if (ch == 0x68) {
subState = SUBSTATE_C_FIELD;
} else {
state = STATE_INVALID;
}
} else if (subState == SUBSTATE_C_FIELD) {
m_frame.cField = ch;
subState = SUBSTATE_A_FIELD;
} else if (subState == SUBSTATE_A_FIELD) {
m_frame.aField = ch;
subState = SUBSTATE_CI_FIELD;
} else if (subState == SUBSTATE_CI_FIELD) {
m_frame.ciField = ch;
if (m_frame.length == 3) {
subState = SUBSTATE_CHECKSUM;
} else {
subState = SUBSTATE_USERDATA;
userDataCnt = 0;
}
} else if (subState == SUBSTATE_USERDATA) {
m_frame.userData[userDataCnt] = ch;
userDataCnt++;
if (userDataCnt >= (m_frame.length - 3)) {
subState = SUBSTATE_CHECKSUM;
}
} else if (subState == SUBSTATE_CHECKSUM) {
m_frame.checksum = ch;
subState = SUBSTATE_STOP;
} else if (subState == SUBSTATE_STOP) {
if (ch == 0x16) {
m_frame.valid = true;
state = STATE_HANDLE;
} else {
state = STATE_INVALID;
}
}
}
break;
case STATE_INVALID:
m_invalidFrameCnt++;
state = STATE_START;
break;
case STATE_HANDLE:
if (m_frame.valid) {
handleFrame();
} else {
Serial.println(getResource(MBC_NO_VALID_FRAME_KEY));
}
state = STATE_DONE;
break;
case STATE_DONE:
// may be another useful message
state = STATE_START;
break;
}
}

View File

@ -9,9 +9,11 @@
#define METERBUSCLIENT_H_
#include "cmd.h"
#include "Config.h"
#include "Resources.h"
#include "Thermometer.h"
class MeterBusClient;
@ -29,18 +31,70 @@ private:
struct MeterBusFrame {
/*
* Short Frame:
* Start 10h
* C-Field
* A-Field
* Check-Sum
* Stop 16h
*
* Long Frame:
* Start 68h
* Length
* Length
* Start 68h
* C-Field
* A-Field
* CI-Field
* User-Data
* Check-Sum
* Stop 16h
*
*/
unsigned char startDelimiter;
unsigned char length;
unsigned char cField;
unsigned char aField;
unsigned char ciField;
unsigned char userData[255];
unsigned char checksum;
bool valid;
};
class MeterBusClient {
public:
MeterBusClient();
void begin(CmdServer *cmdServer);
void begin(CmdServer *cmdServer, Thermometer *thermometer);
void exec();
friend class MeterBusClientConfig;
private:
MeterBusClientConfig m_meterBusClientConfig;
Thermometer *m_thermometer;
unsigned char m_address;
void setAddress(unsigned char address);
unsigned char getAddress();
void handleFrame();
MeterBusFrame m_frame;
unsigned long m_frameCnt;
unsigned long m_myFrameCnt;
unsigned long m_invalidFrameCnt;
unsigned long m_invalidChecksum;
bool m_debug;
bool getDebug();
void setDebug(bool b);
bool m_info;
bool getInfo();
void setInfo(bool b);
void SND_NKE();
void REQ_UD2();
};
#endif /* METERBUSCLIENT_H_ */

23
meterBusClientFrames.cpp Normal file
View File

@ -0,0 +1,23 @@
/*
* meterBusClientFrames.cpp
*
* Created on: 09.03.2014
* Author: wn
*/
#include "meterBusClient.h"
void MeterBusClient::SND_NKE() {
Serial3.write(0xE5);
}
void MeterBusClient::REQ_UD2() {
}

View File

@ -374,7 +374,6 @@ void Thermometer::exec() {
if (currentMillis >= (lastMillis + getPeriodMeasure())) {
lastMillis = currentMillis;
state = 0;
Serial3.println("Tick");
}
break;