Added NV Storage for ESP32
Changed "USB" to "DebugPort" Tidy up of blue wire data frames and passing about by reference instead of just the data buffer. Added AppInventor application
This commit is contained in:
parent
5d112d7e64
commit
1325ae6038
BIN
AppInventor/BluetoothHeater.aia
Normal file
BIN
AppInventor/BluetoothHeater.aia
Normal file
Binary file not shown.
4
Arduino/SenderTrial2/.vscode/settings.json
vendored
4
Arduino/SenderTrial2/.vscode/settings.json
vendored
|
@ -9,6 +9,8 @@
|
|||
"xhash": "cpp",
|
||||
"xstring": "cpp",
|
||||
"xtree": "cpp",
|
||||
"algorithm": "cpp"
|
||||
"algorithm": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"xutility": "cpp"
|
||||
}
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
class CProtocol;
|
||||
|
||||
void Bluetooth_Init();
|
||||
void Bluetooth_Report(const char* pHdr, const unsigned char Data[24]);
|
||||
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame);
|
||||
void Bluetooth_Check();
|
||||
|
||||
void Bluetooth_Interpret(String line);
|
||||
extern void Command_Interpret(String line); // decodes received command lines, implemented in main .ino file!
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#include "Bluetooth.h"
|
||||
#include "TxManage.h"
|
||||
#include "pins.h"
|
||||
#include "Protocol.h"
|
||||
#include "debugport.h"
|
||||
|
||||
#if defined(ESP32)
|
||||
#ifdef ESP32
|
||||
|
||||
const int LED = 2;
|
||||
|
||||
// ESP32
|
||||
|
||||
void Bluetooth_Interpret();
|
||||
|
||||
String BluetoothRxLine;
|
||||
|
||||
#ifndef ESP32_USE_BLE_RLJ
|
||||
|
@ -25,8 +25,10 @@ BluetoothSerial SerialBT;
|
|||
|
||||
void Bluetooth_Init()
|
||||
{
|
||||
pinMode(LED, OUTPUT);
|
||||
|
||||
if(!SerialBT.begin("ESPHEATER")) {
|
||||
Serial.println("An error occurred initialising Bluetooth");
|
||||
DebugPort.println("An error occurred initialising Bluetooth");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +38,7 @@ void Bluetooth_Check()
|
|||
char rxVal = SerialBT.read();
|
||||
if(isControl(rxVal)) { // "End of Line"
|
||||
BluetoothRxLine += '\0';
|
||||
Bluetooth_Interpret(BluetoothRxLine);
|
||||
Command_Interpret(BluetoothRxLine);
|
||||
BluetoothRxLine = "";
|
||||
}
|
||||
else {
|
||||
|
@ -45,11 +47,22 @@ void Bluetooth_Check()
|
|||
}
|
||||
}
|
||||
|
||||
void Bluetooth_Report(const char* pHdr, const unsigned char Data[24])
|
||||
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame)
|
||||
{
|
||||
if(SerialBT.hasClient()) {
|
||||
SerialBT.print(pHdr);
|
||||
SerialBT.write(Data, 24);
|
||||
|
||||
if(Frame.verifyCRC()) {
|
||||
digitalWrite(LED, !digitalRead(LED)); // toggle LED
|
||||
SerialBT.print(pHdr);
|
||||
SerialBT.write(Frame.Data, 24);
|
||||
}
|
||||
else {
|
||||
DebugPort.print("Bluetooth data not sent, CRC error ");
|
||||
DebugPort.println(pHdr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
digitalWrite(LED, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +119,7 @@ class MyCallbacks : public BLECharacteristicCallbacks {
|
|||
while(rxValue.length() > 0) {
|
||||
char rxVal = rxValue[0];
|
||||
if(isControl(rxVal)) { // "End of Line"
|
||||
Bluetooth_Interpret(BluetoothRxLine);
|
||||
Command_Interpret(BluetoothRxLine);
|
||||
BluetoothRxLine = "";
|
||||
}
|
||||
else {
|
||||
|
@ -148,18 +161,20 @@ void Bluetooth_Init()
|
|||
pService->start();
|
||||
// start advertising
|
||||
pServer->getAdvertising()->start();
|
||||
Serial.println("Awaiting a client to notify...");
|
||||
DebugPort.println("Awaiting a client to notify...");
|
||||
}
|
||||
|
||||
void Bluetooth_Report(const char* pHdr, const unsigned char Data[24])
|
||||
void Bluetooth_Report(const char* pHdr, const CProtocol& Frame)
|
||||
{
|
||||
if(deviceConnected) {
|
||||
// BLE can only squirt 20 bytes per packet.
|
||||
// build the entire message then divide and conquer
|
||||
std::string txData = pHdr;
|
||||
txData.append((char*)Data, 24);
|
||||
if(Frame.verifyCRC()) {
|
||||
// BLE can only squirt 20 bytes per packet.
|
||||
// build the entire message then divide and conquer
|
||||
std::string txData = pHdr;
|
||||
txData.append((char*)Frame.Data, 24);
|
||||
|
||||
BLE_Send(txData);
|
||||
BLE_Send(txData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +184,7 @@ void Bluetooth_Check()
|
|||
if (!deviceConnected && oldDeviceConnected) {
|
||||
delay(500); // give the bluetooth stack the chance to get things ready
|
||||
pServer->startAdvertising(); // restart advertising
|
||||
Serial.println("start advertising");
|
||||
DebugPort.println("start advertising");
|
||||
oldDeviceConnected = deviceConnected;
|
||||
}
|
||||
// connecting
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
#include "Bluetooth.h"
|
||||
#include "TxManage.h"
|
||||
#include "pins.h"
|
||||
#include "Protocol.h"
|
||||
#include "debugport.h"
|
||||
|
||||
#if defined (ESP32)
|
||||
// Bluetooth access via HC-05 Module, using a UART
|
||||
|
||||
#ifndef ESP32
|
||||
// NOTE: ESP32 uses an entirely different mechanism, please refer to BluetoothESP32.cpp/.h
|
||||
#else
|
||||
|
||||
#if defined(__arm__)
|
||||
#ifdef __arm__
|
||||
// for Arduino Due
|
||||
static UARTClass& Bluetooth(Serial2);
|
||||
#else
|
||||
// for Mega
|
||||
static HardwareSerial& Bluetooth(Serial2); // TODO: make proper ESP32 BT client
|
||||
static HardwareSerial& Bluetooth(Serial2); // TODO: make proper ESP32 BT client
|
||||
#endif
|
||||
|
||||
bool Bluetooth_Command(const char* cmd);
|
||||
void Bluetooth_Interpret();
|
||||
bool Bluetooth_ATCommand(const char* cmd);
|
||||
|
||||
String BluetoothRxData;
|
||||
|
||||
|
@ -27,8 +28,7 @@ bool bHC05Available = false;
|
|||
|
||||
void Bluetooth_Init()
|
||||
{
|
||||
#ifndef __ESP32__
|
||||
|
||||
|
||||
// search for BlueTooth adapter, trying the common baud rates, then less common
|
||||
// as the device cannot be guaranteed to power up with the key pin high
|
||||
// we are at the mercy of the baud rate stored in the module.
|
||||
|
@ -36,53 +36,53 @@ void Bluetooth_Init()
|
|||
digitalWrite(KeyPin, HIGH);
|
||||
delay(500);
|
||||
|
||||
USB.println("\r\n\r\nAttempting to detect HC-05 Bluetooth module...");
|
||||
DebugPort.println("\r\n\r\nAttempting to detect HC-05 Bluetooth module...");
|
||||
|
||||
int BTidx = 0;
|
||||
int maxTries = sizeof(BTRates)/sizeof(int);
|
||||
for(BTidx = 0; BTidx < maxTries; BTidx++) {
|
||||
USB.print(" @ ");
|
||||
USB.print(BTRates[BTidx]);
|
||||
USB.print(" baud... ");
|
||||
DebugPort.print(" @ ");
|
||||
DebugPort.print(BTRates[BTidx]);
|
||||
DebugPort.print(" baud... ");
|
||||
Bluetooth.begin(BTRates[BTidx]); // open serial port at a certain baud rate
|
||||
Bluetooth.print("\r\n");
|
||||
Bluetooth.setTimeout(50);
|
||||
|
||||
if(Bluetooth_Command("AT\r\n")) {
|
||||
USB.println(" OK.");
|
||||
if(Bluetooth_ATCommand("AT\r\n")) {
|
||||
DebugPort.println(" OK.");
|
||||
break;
|
||||
}
|
||||
// failed, try another baud rate
|
||||
USB.println("");
|
||||
DebugPort.println("");
|
||||
Bluetooth.flush();
|
||||
}
|
||||
|
||||
USB.println("");
|
||||
DebugPort.println("");
|
||||
if(BTidx == maxTries) {
|
||||
USB.println("FAILED to detect HC-05 Bluetooth module :-(");
|
||||
DebugPort.println("FAILED to detect HC-05 Bluetooth module :-(");
|
||||
}
|
||||
else {
|
||||
if(BTRates[BTidx] == 115200) {
|
||||
USB.println("HC-05 found and already set to 115200 baud, skipping Init.");
|
||||
DebugPort.println("HC-05 found and already set to 115200 baud, skipping Init.");
|
||||
bHC05Available = true;
|
||||
}
|
||||
else {
|
||||
do {
|
||||
USB.println("HC-05 found");
|
||||
DebugPort.println("HC-05 found");
|
||||
|
||||
USB.print(" Setting Name to \"DieselHeater\"... ");
|
||||
if(!Bluetooth_Command("AT+NAME=\"DieselHeater\"\r\n")) {
|
||||
USB.println("FAILED");
|
||||
DebugPort.print(" Setting Name to \"DieselHeater\"... ");
|
||||
if(!Bluetooth_ATCommand("AT+NAME=\"DieselHeater\"\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
break;
|
||||
}
|
||||
USB.println("OK");
|
||||
DebugPort.println("OK");
|
||||
|
||||
USB.print(" Setting baud rate to 115200N81...");
|
||||
if(!Bluetooth_Command("AT+UART=115200,1,0\r\n")) {
|
||||
USB.println("FAILED");
|
||||
DebugPort.print(" Setting baud rate to 115200N81...");
|
||||
if(!Bluetooth_ATCommand("AT+UART=115200,1,0\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
break;
|
||||
};
|
||||
USB.println("OK");
|
||||
DebugPort.println("OK");
|
||||
|
||||
Bluetooth.begin(115200);
|
||||
bHC05Available = true;
|
||||
|
@ -98,8 +98,7 @@ void Bluetooth_Init()
|
|||
if(!bHC05Available)
|
||||
Bluetooth.end(); // close serial port if no module found
|
||||
|
||||
USB.println("");
|
||||
#endif
|
||||
DebugPort.println("");
|
||||
}
|
||||
|
||||
void Bluetooth_Check()
|
||||
|
@ -110,7 +109,7 @@ void Bluetooth_Check()
|
|||
char rxVal = Bluetooth.read();
|
||||
if(isControl(rxVal)) { // "End of Line"
|
||||
BluetoothRxData += '\0';
|
||||
Bluetooth_Interpret(BluetoothRxData);
|
||||
Command_Interpret(BluetoothRxData);
|
||||
BluetoothRxData = "";
|
||||
}
|
||||
else {
|
||||
|
@ -121,16 +120,22 @@ void Bluetooth_Check()
|
|||
}
|
||||
|
||||
|
||||
void Bluetooth_Report(const char* pHdr, const unsigned char Data[24])
|
||||
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame)
|
||||
{
|
||||
if(bHC05Available) {
|
||||
Bluetooth.print(pHdr);
|
||||
Bluetooth.write(Data, 24);
|
||||
if(Frame.verifyCRC()) {
|
||||
Bluetooth.print(pHdr);
|
||||
Bluetooth.write(Frame.Data, 24);
|
||||
}
|
||||
else {
|
||||
DebugPort.print("Bluetooth data not sent, CRC error ");
|
||||
DebugPort.println(pHdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// local function, typically to perform Hayes commands with HC-05
|
||||
bool Bluetooth_Command(const char* cmd)
|
||||
bool Bluetooth_ATCommand(const char* cmd)
|
||||
{
|
||||
if(bHC05Available) {
|
||||
Bluetooth.print(cmd);
|
||||
|
@ -148,36 +153,3 @@ bool Bluetooth_Command(const char* cmd)
|
|||
#endif
|
||||
|
||||
|
||||
void Bluetooth_Interpret(String line)
|
||||
{
|
||||
if(line.startsWith("[CMD]") ) {
|
||||
USB.write("BT command Rx'd: ");
|
||||
// incoming command from BT app!
|
||||
line.remove(0, 5); // strip away "[CMD]" header
|
||||
if(line.startsWith("ON") ) {
|
||||
USB.write("ON\n");
|
||||
TxManage.RequestOn();
|
||||
}
|
||||
else if(line.startsWith("OFF")) {
|
||||
USB.write("OFF\n");
|
||||
TxManage.RequestOff();
|
||||
}
|
||||
else if(line.startsWith("Pmin")) {
|
||||
line.remove(0, 4);
|
||||
USB.write("Pmin\n");
|
||||
}
|
||||
else if(line.startsWith("Pmax")) {
|
||||
line.remove(0, 4);
|
||||
USB.write("Pmax\n");
|
||||
}
|
||||
else if(line.startsWith("Fmin")) {
|
||||
line.remove(0, 4);
|
||||
USB.write("Fmin\n");
|
||||
}
|
||||
else if(line.startsWith("Fmax")) {
|
||||
line.remove(0, 4);
|
||||
USB.write("Fmax\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
118
Arduino/SenderTrial2/NVStorage.cpp
Normal file
118
Arduino/SenderTrial2/NVStorage.cpp
Normal file
|
@ -0,0 +1,118 @@
|
|||
#include "Arduino.h"
|
||||
#include "NVStorage.h"
|
||||
|
||||
|
||||
CHeaterStorage::CHeaterStorage()
|
||||
{
|
||||
calValues.Pmin = 14;
|
||||
calValues.Pmax = 40;
|
||||
calValues.Fmin = 1500;
|
||||
calValues.Fmax = 4500;
|
||||
calValues.ThermostatMode = 1;
|
||||
calValues.setTemperature = 22;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getPmin()
|
||||
{
|
||||
return calValues.Pmin;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getPmax()
|
||||
{
|
||||
return calValues.Pmax;
|
||||
}
|
||||
|
||||
unsigned short
|
||||
CHeaterStorage::getFmin()
|
||||
{
|
||||
return calValues.Fmin;
|
||||
}
|
||||
|
||||
unsigned short
|
||||
CHeaterStorage::getFmax()
|
||||
{
|
||||
return calValues.Fmax;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getTemperature()
|
||||
{
|
||||
return calValues.setTemperature;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getThermostatMode()
|
||||
{
|
||||
return calValues.ThermostatMode;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setPmin(unsigned char val)
|
||||
{
|
||||
calValues.Pmin = val;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setPmax(unsigned char val)
|
||||
{
|
||||
calValues.Pmax = val;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setFmin(unsigned short val)
|
||||
{
|
||||
calValues.Fmin = val;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setFmax(unsigned short val)
|
||||
{
|
||||
calValues.Fmax = val;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setTemperature(unsigned char val)
|
||||
{
|
||||
calValues.setTemperature = val;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setThermostatMode(unsigned char val)
|
||||
{
|
||||
calValues.ThermostatMode = val;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// ESP32
|
||||
//
|
||||
#ifdef ESP32
|
||||
|
||||
CESP32HeaterStorage::CESP32HeaterStorage()
|
||||
{
|
||||
}
|
||||
|
||||
CESP32HeaterStorage::~CESP32HeaterStorage()
|
||||
{
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
void
|
||||
CESP32HeaterStorage::init()
|
||||
{
|
||||
preferences.begin("dieselheater", false);
|
||||
}
|
||||
|
||||
void CESP32HeaterStorage::load()
|
||||
{
|
||||
preferences.getBytes("calValues", &calValues, sizeof(sNVStore));
|
||||
}
|
||||
|
||||
void CESP32HeaterStorage::save()
|
||||
{
|
||||
preferences.putBytes("calValues", &calValues, sizeof(sNVStore));
|
||||
}
|
||||
|
||||
#endif // ESP32
|
69
Arduino/SenderTrial2/NVStorage.h
Normal file
69
Arduino/SenderTrial2/NVStorage.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
|
||||
struct sNVStore {
|
||||
unsigned char Pmin;
|
||||
unsigned char Pmax;
|
||||
unsigned short Fmin;
|
||||
unsigned short Fmax;
|
||||
unsigned char ThermostatMode;
|
||||
unsigned char setTemperature;
|
||||
};
|
||||
|
||||
class CNVStorage {
|
||||
public:
|
||||
CNVStorage() {};
|
||||
virtual ~CNVStorage() {};
|
||||
virtual void init() = 0;
|
||||
virtual void load() = 0;
|
||||
virtual void save() = 0;
|
||||
};
|
||||
|
||||
|
||||
class CHeaterStorage : public CNVStorage {
|
||||
protected:
|
||||
sNVStore calValues;
|
||||
public:
|
||||
CHeaterStorage();
|
||||
virtual ~CHeaterStorage() {};
|
||||
|
||||
// TODO: These are only here to allow building without fully
|
||||
// fleshing out NV storage for Due, Mega etc
|
||||
// these should be removed once complete (pure virtual)
|
||||
void init() {};
|
||||
void load() {};
|
||||
void save() {};
|
||||
|
||||
|
||||
unsigned char getPmin();
|
||||
unsigned char getPmax();
|
||||
unsigned short getFmin();
|
||||
unsigned short getFmax();
|
||||
unsigned char getTemperature();
|
||||
unsigned char getThermostatMode();
|
||||
|
||||
void setPmin(unsigned char val);
|
||||
void setPmax(unsigned char val);
|
||||
void setFmin(unsigned short val);
|
||||
void setFmax(unsigned short val);
|
||||
void setTemperature(unsigned char val);
|
||||
void setThermostatMode(unsigned char val);
|
||||
};
|
||||
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include <Preferences.h>
|
||||
|
||||
class CESP32HeaterStorage : public CHeaterStorage {
|
||||
Preferences preferences;
|
||||
public:
|
||||
CESP32HeaterStorage();
|
||||
virtual ~CESP32HeaterStorage();
|
||||
void init();
|
||||
void load();
|
||||
void save();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
extern CHeaterStorage* pNVStorage;
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
#include <Arduino.h>
|
||||
#include "Protocol.h"
|
||||
|
||||
#include "debugport.h"
|
||||
|
||||
unsigned short
|
||||
CProtocol::CalcCRC(int len)
|
||||
CProtocol::CalcCRC(int len) const
|
||||
{
|
||||
// calculate a CRC-16/MODBUS checksum using the first 22 bytes of the data array
|
||||
unsigned short wCRCWord = 0xFFFF;
|
||||
|
||||
int wLength = len;
|
||||
unsigned char* pData = Data;
|
||||
const unsigned char* pData = Data;
|
||||
while (wLength--)
|
||||
{
|
||||
unsigned char nTemp = *pData++ ^ wCRCWord;
|
||||
|
@ -34,20 +35,29 @@ CProtocol::setCRC(unsigned short CRC)
|
|||
|
||||
|
||||
unsigned short
|
||||
CProtocol::getCRC()
|
||||
CProtocol::getCRC() const
|
||||
{
|
||||
unsigned short CRC;
|
||||
CRC = Data[22]; // MSB of CRC in Data[22]
|
||||
CRC <<= 8;
|
||||
CRC |= Data[23]; // LSB of CRC in Data[23]
|
||||
return CRC;
|
||||
}
|
||||
|
||||
// return true for CRC match
|
||||
bool
|
||||
CProtocol::verifyCRC()
|
||||
CProtocol::verifyCRC() const
|
||||
{
|
||||
unsigned short CRC = CalcCRC(22); // calculate CRC based on first 22 bytes
|
||||
return (getCRC() == CRC); // does it match the stored values?
|
||||
unsigned short FrameCRC = getCRC();
|
||||
bool bOK = (FrameCRC == CRC);
|
||||
if(!bOK) {
|
||||
DebugPort.print("verifyCRC FAILED: calc:");
|
||||
DebugPort.print(CRC, HEX);
|
||||
DebugPort.print(" data:");
|
||||
DebugPort.println(FrameCRC, HEX);
|
||||
}
|
||||
return bOK; // does it match the stored values?
|
||||
}
|
||||
|
||||
CProtocol&
|
||||
|
@ -57,21 +67,6 @@ CProtocol::operator=(const CProtocol& rhs)
|
|||
return *this;
|
||||
}
|
||||
|
||||
int
|
||||
CProtocol::getCommand()
|
||||
{
|
||||
return Controller.Command;
|
||||
}
|
||||
|
||||
void
|
||||
CProtocol::setCommand(int cmd)
|
||||
{
|
||||
Controller.Command = cmd;
|
||||
}
|
||||
|
||||
/*unsigned char getCommand();
|
||||
void setCommand(int mode);*/
|
||||
|
||||
|
||||
void
|
||||
CProtocol::setFan_Min(short Speed)
|
||||
|
|
|
@ -98,16 +98,24 @@ public:
|
|||
public:
|
||||
CProtocol() { Init(0); };
|
||||
CProtocol(int TxMode) { Init(TxMode); };
|
||||
|
||||
void Init(int Txmode);
|
||||
// CRC handlers
|
||||
unsigned short CalcCRC(int len); // calculate and set the CRC upon len bytes
|
||||
void setCRC(); // calculate and set the CRC in the buffer
|
||||
unsigned short CalcCRC(int len) const; // calculate the CRC upon len bytes
|
||||
void setCRC(); // calculate and set the CRC in the buffer
|
||||
void setCRC(unsigned short CRC); // set the CRC in the buffer
|
||||
unsigned short getCRC(); // extract CRC value from buffer
|
||||
bool verifyCRC(); // return true for CRC match
|
||||
// command
|
||||
int getCommand();
|
||||
void setCommand(int mode);
|
||||
unsigned short getCRC() const; // extract CRC value from buffer
|
||||
bool verifyCRC() const; // return true for CRC match
|
||||
|
||||
void setActiveMode() { Controller.Byte0 = 0x76; }; // this allows heater to save tuning params to EEPROM
|
||||
void setPassiveMode() { Controller.Byte0 = 0x78; }; // this prevents heater saving tuning params to EEPROM
|
||||
// command helpers
|
||||
void resetCommand() { setRawCommand(0x00); };
|
||||
void onCommand() { setRawCommand(0xA0); };
|
||||
void offCommand() { setRawCommand(0x05); };
|
||||
// raw command
|
||||
int getRawCommand() { return Controller.Command; };
|
||||
void setRawCommand(int mode) { Controller.Command = mode; };
|
||||
// Run state
|
||||
unsigned char getRunState() { return Heater.RunState; };
|
||||
void setRunState(unsigned char state) { Heater.RunState = state; };
|
||||
|
@ -144,10 +152,13 @@ public:
|
|||
unsigned char getTemperature_Desired() { return Controller.DesiredTemperature; };
|
||||
unsigned char getTemperature_Min() { return Controller.MinTemperature; };
|
||||
unsigned char getTemperature_Max() { return Controller.MaxTemperature; };
|
||||
void setThermostatMode(unsigned on) { Controller.OperatingMode = on ? 0x32 : 0xCD; };
|
||||
// glow plug
|
||||
short getGlowPlug_Current(); // glow plug current
|
||||
short getGlowPlug_Voltage(); // glow plug voltage
|
||||
void setGlowPlug_Current(short ampsx100); // glow plug current
|
||||
void setGlowPlug_Voltage(short voltsx10); // glow plug voltage
|
||||
// heat exchanger
|
||||
short getTemperature_HeatExchg(); // temperature of heat exchanger
|
||||
void setTemperature_HeatExchg(short degC); // temperature of heat exchanger
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Chinese Heater Half Duplex Serial Data Sending Tool
|
||||
|
||||
Connects to the blue wire of a Chinese heater, which is the half duplex serial link.
|
||||
Sends and receives data from serial port 1.
|
||||
Sends and receives data from hardware serial port 1.
|
||||
|
||||
Terminology: Tx is to the heater unit, Rx is from the heater unit.
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
|||
This software can connect to the blue wire in a normal OEM system, detecting the
|
||||
OEM controller and allowing extraction of the data or injecting on/off commands.
|
||||
|
||||
If Pin 21 is grounded on the Due, this simple stream will be reported over USB and
|
||||
If Pin 21 is grounded on the Due, this simple stream will be reported over Serial and
|
||||
no control from the Arduino will be allowed.
|
||||
This allows sniffing of the blue wire in a normal system.
|
||||
|
||||
|
@ -20,11 +20,11 @@
|
|||
If it has been > 100ms since the last blue wire activity this indicates a new frame
|
||||
sequence is starting from the OEM controller.
|
||||
Synchronise as such then count off the next 24 bytes storing them in the Controller's
|
||||
data array. These bytes are then reported over USB to the PC in ASCII.
|
||||
data array. These bytes are then reported over Serial to the PC in ASCII.
|
||||
|
||||
It is then expected the heater will respond with it's 24 bytes.
|
||||
Capture those bytes and store them in the Heater1 data array.
|
||||
Once again these bytes are then reported over USB to the PC in ASCII.
|
||||
Once again these bytes are then reported over Serial to the PC in ASCII.
|
||||
|
||||
If no activity is sensed in a second, it is assumed no controller is attached and we
|
||||
have full control over the heater.
|
||||
|
@ -65,22 +65,26 @@
|
|||
#include "Protocol.h"
|
||||
#include "TxManage.h"
|
||||
#include "pins.h"
|
||||
#include "NVStorage.h"
|
||||
#include "debugport.h"
|
||||
|
||||
#define BLUETOOTH
|
||||
|
||||
#define DEBUG_BTRX
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
#include "Bluetooth.h"
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
// for Arduino Due
|
||||
// Required for Arduino Due, UARTclass is derived from HardwareSerial
|
||||
static UARTClass& BlueWire(Serial1);
|
||||
#else
|
||||
// for ESP32, Mega
|
||||
// HardwareSerial is it for these boards
|
||||
static HardwareSerial& BlueWire(Serial1);
|
||||
#endif
|
||||
|
||||
void SerialReport(const char* hdr, const unsigned char* pData, const char* ftr);
|
||||
void DebugReportFrame(const char* hdr, const CProtocol& Frame, const char* ftr);
|
||||
|
||||
class CommStates {
|
||||
public:
|
||||
|
@ -109,74 +113,94 @@ private:
|
|||
|
||||
|
||||
CommStates CommState;
|
||||
CTxManage TxManage(TxEnbPin, Serial1);
|
||||
CProtocol OEMController; // most recent data packet received from OEM controller found on blue wire
|
||||
CProtocol Heater1; // data packet received from heater in response to OEM controller packet
|
||||
CProtocol Heater2; // data packet received from heater in response to our packet
|
||||
CProtocol BTCParams(CProtocol::CtrlMode); // holds our local parameters, used in case of no OEM controller
|
||||
CTxManage TxManage(TxEnbPin, BlueWire);
|
||||
CProtocol OEMControllerFrame; // data packet received from heater in response to OEM controller packet
|
||||
CProtocol HeaterFrame1; // data packet received from heater in response to OEM controller packet
|
||||
CProtocol HeaterFrame2; // data packet received from heater in response to our packet
|
||||
CProtocol DefaultBTCParams(CProtocol::CtrlMode); // defines the default parameters, used in case of no OEM controller
|
||||
long lastRxTime; // used to observe inter character delays
|
||||
|
||||
// setup Non Volatile storage
|
||||
// this is very much hardware dependent, we can use the ESP32's FLASH
|
||||
#ifdef ESP32
|
||||
CESP32HeaterStorage NVStorage;
|
||||
#else
|
||||
CHeaterStorage NVStorage; // dummy, for now
|
||||
#endif
|
||||
CHeaterStorage* pNVStorage = NULL;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
// initialize listening serial port
|
||||
// initialize serial port to interact with the "blue wire"
|
||||
// 25000 baud, Tx and Rx channels of Chinese heater comms interface:
|
||||
// Tx/Rx data to/from heater, special baud rate for Chinese heater controllers
|
||||
// Tx/Rx data to/from heater,
|
||||
// Note special baud rate for Chinese heater controllers
|
||||
pinMode(ListenOnlyPin, INPUT_PULLUP);
|
||||
pinMode(KeyPin, OUTPUT);
|
||||
// pinMode(Tx2Pin, OUTPUT);
|
||||
digitalWrite(KeyPin, LOW);
|
||||
// digitalWrite(Tx2Pin, HIGH);
|
||||
|
||||
#if defined(__arm__) || defined(__AVR__)
|
||||
BlueWire.begin(25000);
|
||||
pinMode(Rx1Pin, INPUT_PULLUP); // required for MUX to work properly
|
||||
#else if defined(__ESP32__)
|
||||
#elif ESP32
|
||||
// ESP32
|
||||
BlueWire.begin(25000, SERIAL_8N1, Rx1Pin, Tx1Pin);
|
||||
BlueWire.begin(25000, SERIAL_8N1, Rx1Pin, Tx1Pin); // need to explicitly specify pins for pin multiplexer!
|
||||
pinMode(Rx1Pin, INPUT_PULLUP); // required for MUX to work properly
|
||||
#endif
|
||||
|
||||
// initialise serial monitor on serial port 0
|
||||
USB.begin(115200);
|
||||
// this is the usual USB connection to a PC
|
||||
DebugPort.begin(115200);
|
||||
|
||||
// prepare for first long delay detection
|
||||
lastRxTime = millis();
|
||||
|
||||
TxManage.begin(); // ensure Tx enable pin setup
|
||||
TxManage.begin(); // ensure Tx enable pin is setup
|
||||
|
||||
// define defaults should heater controller be missing
|
||||
BTCParams.setTemperature_Desired(23);
|
||||
BTCParams.setTemperature_Actual(22);
|
||||
BTCParams.Controller.OperatingVoltage = 120;
|
||||
BTCParams.setPump_Min(16);
|
||||
BTCParams.setPump_Max(55);
|
||||
BTCParams.setFan_Min(1680);
|
||||
BTCParams.setFan_Max(4500);
|
||||
DefaultBTCParams.setTemperature_Desired(23);
|
||||
DefaultBTCParams.setTemperature_Actual(22);
|
||||
DefaultBTCParams.Controller.OperatingVoltage = 120;
|
||||
DefaultBTCParams.setPump_Min(16);
|
||||
DefaultBTCParams.setPump_Max(55);
|
||||
DefaultBTCParams.setFan_Min(1680);
|
||||
DefaultBTCParams.setFan_Max(4500);
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
Bluetooth_Init();
|
||||
#endif
|
||||
|
||||
// create pointer to CHeaterStorage
|
||||
// via the magic of polymorphism we can use this to access whatever
|
||||
// storage is required for a specifc platform in a uniform way
|
||||
pNVStorage = &NVStorage;
|
||||
pNVStorage->init();
|
||||
pNVStorage->load();
|
||||
}
|
||||
|
||||
// main functional loop is based about a state machine approach, waiting for data
|
||||
// to appear upon the blue wire, and marshalling into an appropriate receive buffer
|
||||
// according to the state.
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
unsigned long timenow = millis();
|
||||
|
||||
// check for test commands received from PC Over USB
|
||||
if(USB.available()) {
|
||||
char rxval = USB.read();
|
||||
if(DebugPort.available()) {
|
||||
char rxval = DebugPort.read();
|
||||
if(rxval == '+') {
|
||||
TxManage.RequestOn();
|
||||
TxManage.queueOnRequest();
|
||||
}
|
||||
if(rxval == '-') {
|
||||
TxManage.RequestOff();
|
||||
TxManage.queueOffRequest();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
// check for Bluetooth activity
|
||||
Bluetooth_Check();
|
||||
Bluetooth_Check(); // check for Bluetooth activity
|
||||
#endif
|
||||
|
||||
// Handle time interval where we send data to the blue wire
|
||||
|
@ -194,27 +218,28 @@ void loop()
|
|||
// check for no rx traffic => no OEM controller
|
||||
if(CommState.is(CommStates::Idle) && (RxTimeElapsed >= 970)) {
|
||||
// have not seen any receive data for a second.
|
||||
// OEM controller probably not connected.
|
||||
// Skip to BTC_Tx, sending our own settings.
|
||||
// OEM controller is probably not connected.
|
||||
// Skip state machine immediately to BTC_Tx, sending our own settings.
|
||||
CommState.set(CommStates::BTC_Tx);
|
||||
bool bOurParams = true;
|
||||
TxManage.Start(BTCParams, timenow, bOurParams);
|
||||
bool isBTCmaster = true;
|
||||
TxManage.PrepareFrame(DefaultBTCParams, isBTCmaster); // use our parameters, and mix in NV storage values
|
||||
TxManage.Start(timenow);
|
||||
#ifdef BLUETOOTH
|
||||
Bluetooth_Report("[BTC]", BTCParams.Data); // BTC => Bluetooth Controller :-)
|
||||
Bluetooth_SendFrame("[BTC]", TxManage.getFrame()); // BTC => Bluetooth Controller :-)
|
||||
#endif
|
||||
}
|
||||
|
||||
// precautionary action if all 24 bytes were not received whilst expecting them
|
||||
if(RxTimeElapsed > 50) {
|
||||
if( CommState.is(CommStates::ControllerRx) ||
|
||||
CommState.is(CommStates::HeaterRx1) ||
|
||||
CommState.is(CommStates::HeaterRx1) ||
|
||||
CommState.is(CommStates::HeaterRx2) ) {
|
||||
|
||||
CommState.set(CommStates::Idle);
|
||||
}
|
||||
}
|
||||
|
||||
// read from port 1, the "blue wire" (to/from heater), store according to CommState
|
||||
// read data from Serial port 1, the "blue wire" (to/from heater), store according to CommState
|
||||
if (BlueWire.available()) {
|
||||
|
||||
lastRxTime = timenow;
|
||||
|
@ -227,19 +252,19 @@ void loop()
|
|||
int inByte = BlueWire.read(); // read hex byte
|
||||
|
||||
if( CommState.is(CommStates::ControllerRx) ) {
|
||||
if(CommState.saveData(OEMController.Data, inByte) ) {
|
||||
if(CommState.saveData(OEMControllerFrame.Data, inByte) ) {
|
||||
CommState.set(CommStates::ControllerReport);
|
||||
}
|
||||
}
|
||||
|
||||
else if( CommState.is(CommStates::HeaterRx1) ) {
|
||||
if( CommState.saveData(Heater1.Data, inByte) ) {
|
||||
if( CommState.saveData(HeaterFrame1.Data, inByte) ) {
|
||||
CommState.set(CommStates::HeaterReport1);
|
||||
}
|
||||
}
|
||||
|
||||
else if( CommState.is(CommStates::HeaterRx2) ) {
|
||||
if( CommState.saveData(Heater2.Data, inByte) ) {
|
||||
if( CommState.saveData(HeaterFrame2.Data, inByte) ) {
|
||||
CommState.set(CommStates::HeaterReport2);
|
||||
}
|
||||
}
|
||||
|
@ -250,35 +275,38 @@ void loop()
|
|||
if( CommState.is(CommStates::ControllerReport) ) {
|
||||
// filled controller frame, report
|
||||
#ifdef BLUETOOTH
|
||||
Bluetooth_Report("[OEM]", OEMController.Data);
|
||||
// echo received OEM controller frame over Bluetooth, using [OEM] header
|
||||
Bluetooth_SendFrame("[OEM]", OEMControllerFrame);
|
||||
#endif
|
||||
SerialReport("Ctrl ", OEMController.Data, " ");
|
||||
DebugReportFrame("OEM ", OEMControllerFrame, " ");
|
||||
CommState.set(CommStates::HeaterRx1);
|
||||
}
|
||||
|
||||
else if(CommState.is(CommStates::HeaterReport1) ) {
|
||||
// received heater frame (after controller message), report
|
||||
SerialReport("Htr1 ", Heater1.Data, "\r\n");
|
||||
DebugReportFrame("Htr1 ", HeaterFrame1, "\r\n");
|
||||
#ifdef BLUETOOTH
|
||||
Bluetooth_Report("[HTR]", Heater1.Data);
|
||||
// echo heater reponse data to Bluetooth client
|
||||
Bluetooth_SendFrame("[HTR]", HeaterFrame1);
|
||||
#endif
|
||||
|
||||
if(digitalRead(ListenOnlyPin)) {
|
||||
bool bOurParams = false;
|
||||
TxManage.Start(OEMController, timenow, bOurParams);
|
||||
bool isBTCmaster = false;
|
||||
TxManage.PrepareFrame(OEMControllerFrame, isBTCmaster); // parrot OEM parameters, but block NV modes
|
||||
TxManage.Start(timenow);
|
||||
CommState.set(CommStates::BTC_Tx);
|
||||
}
|
||||
else {
|
||||
CommState.set(CommStates::Idle); // "Listen Only" input held low, don't send out Tx
|
||||
CommState.set(CommStates::Idle); // "Listen Only" input is held low, don't send out Tx
|
||||
}
|
||||
}
|
||||
|
||||
else if( CommState.is(CommStates::HeaterReport2) ) {
|
||||
// received heater frame (after our control message), report
|
||||
SerialReport("Htr2 ", Heater2.Data, "\r\n");
|
||||
DebugReportFrame("Htr2 ", HeaterFrame2, "\r\n");
|
||||
// if(!digitalRead(ListenOnlyPin)) {
|
||||
#ifdef BLUETOOTH
|
||||
Bluetooth_Report("[HTR]", Heater2.Data); // pin not grounded, suppress duplicate to BT
|
||||
Bluetooth_SendFrame("[HTR]", HeaterFrame2); // pin not grounded, suppress duplicate to BT
|
||||
#endif
|
||||
// }
|
||||
CommState.set(CommStates::Idle);
|
||||
|
@ -286,14 +314,87 @@ void loop()
|
|||
|
||||
} // loop
|
||||
|
||||
void SerialReport(const char* hdr, const unsigned char* pData, const char* ftr)
|
||||
void DebugReportFrame(const char* hdr, const CProtocol& Frame, const char* ftr)
|
||||
{
|
||||
USB.print(hdr); // header
|
||||
DebugPort.print(hdr); // header
|
||||
for(int i=0; i<24; i++) {
|
||||
char str[16];
|
||||
sprintf(str, "%02X ", pData[i]); // build 2 dig hex values
|
||||
USB.print(str); // and print
|
||||
sprintf(str, "%02X ", Frame.Data[i]); // build 2 dig hex values
|
||||
DebugPort.print(str); // and print
|
||||
}
|
||||
DebugPort.print(ftr); // footer
|
||||
}
|
||||
|
||||
void Command_Interpret(String line)
|
||||
{
|
||||
unsigned char cVal;
|
||||
unsigned short sVal;
|
||||
|
||||
#ifdef DEBUG_BTRX
|
||||
DebugPort.println(line);
|
||||
DebugPort.println();
|
||||
#endif
|
||||
|
||||
if(line.startsWith("[CMD]") ) {
|
||||
DebugPort.write("BT command Rx'd: ");
|
||||
// incoming command from BT app!
|
||||
line.remove(0, 5); // strip away "[CMD]" header
|
||||
if(line.startsWith("ON") ) {
|
||||
DebugPort.write("ON\n");
|
||||
TxManage.queueOnRequest();
|
||||
}
|
||||
else if(line.startsWith("OFF")) {
|
||||
DebugPort.write("OFF\n");
|
||||
TxManage.queueOffRequest();
|
||||
}
|
||||
else if(line.startsWith("Pmin")) {
|
||||
line.remove(0, 4);
|
||||
DebugPort.write("Pmin=");
|
||||
cVal = (line.toFloat() * 10) + 0.5;
|
||||
DebugPort.println(cVal);
|
||||
pNVStorage->setPmin(cVal);
|
||||
}
|
||||
else if(line.startsWith("Pmax")) {
|
||||
line.remove(0, 4);
|
||||
DebugPort.write("Pmax=");
|
||||
cVal = (line.toFloat() * 10) + 0.5;
|
||||
DebugPort.println(cVal);
|
||||
pNVStorage->setPmax(cVal);
|
||||
}
|
||||
else if(line.startsWith("Fmin")) {
|
||||
line.remove(0, 4);
|
||||
DebugPort.print("Fmin=");
|
||||
sVal = line.toInt();
|
||||
DebugPort.println(sVal);
|
||||
pNVStorage->setFmin(sVal);
|
||||
}
|
||||
else if(line.startsWith("Fmax")) {
|
||||
line.remove(0, 4);
|
||||
DebugPort.print("Fmax=");
|
||||
sVal = line.toInt();
|
||||
DebugPort.println(sVal);
|
||||
pNVStorage->setFmax(sVal);
|
||||
}
|
||||
else if(line.startsWith("save")) {
|
||||
line.remove(0, 4);
|
||||
DebugPort.write("save\n");
|
||||
pNVStorage->save();
|
||||
}
|
||||
else if(line.startsWith("degC")) {
|
||||
line.remove(0, 4);
|
||||
DebugPort.write("degC=");
|
||||
cVal = line.toInt();
|
||||
DebugPort.println(cVal);
|
||||
pNVStorage->setTemperature(cVal);
|
||||
}
|
||||
else if(line.startsWith("Mode")) {
|
||||
line.remove(0, 4);
|
||||
DebugPort.write("Mode=");
|
||||
cVal = !pNVStorage->getThermostatMode();
|
||||
pNVStorage->setThermostatMode(cVal);
|
||||
DebugPort.println(cVal);
|
||||
}
|
||||
|
||||
}
|
||||
USB.print(ftr); // footer
|
||||
}
|
||||
|
||||
|
|
|
@ -1,51 +1,90 @@
|
|||
#include "TxManage.h"
|
||||
#include "NVStorage.h"
|
||||
|
||||
extern void SerialReport(const char* hdr, const unsigned char* pData, const char* ftr);
|
||||
extern void DebugReportFrame(const char* hdr, const CProtocol&, const char* ftr);
|
||||
|
||||
CTxManage::CTxManage(int TxEnbPin, HardwareSerial& serial) :
|
||||
m_Serial(serial),
|
||||
m_Frame(CProtocol::CtrlMode)
|
||||
CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) :
|
||||
m_BlueWireSerial(serial),
|
||||
m_TxFrame(CProtocol::CtrlMode)
|
||||
{
|
||||
m_bOnReq = false;
|
||||
m_bOffReq = false;
|
||||
m_bTxPending = false;
|
||||
m_nStartTime = 0;
|
||||
m_nTxEnbPin = TxEnbPin;
|
||||
m_nTxGatePin = TxGatePin;
|
||||
}
|
||||
|
||||
void CTxManage::begin()
|
||||
{
|
||||
pinMode(m_nTxEnbPin, OUTPUT);
|
||||
digitalWrite(m_nTxEnbPin, LOW);
|
||||
pinMode(m_nTxGatePin, OUTPUT);
|
||||
digitalWrite(m_nTxGatePin, LOW);
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::RequestOn()
|
||||
CTxManage::queueOnRequest()
|
||||
{
|
||||
m_bOnReq = true;
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::RequestOff()
|
||||
CTxManage::queueOffRequest()
|
||||
{
|
||||
m_bOffReq = true;
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::Start(const CProtocol& ref, unsigned long timenow, bool self)
|
||||
void
|
||||
CTxManage::PrepareFrame(const CProtocol& basisFrame, bool isBTCmaster)
|
||||
{
|
||||
m_Frame = ref;
|
||||
// copy supplied frame, typically this will be the values an OEM controller delivered
|
||||
// which means we parrot that data by default.
|
||||
// When parroting, we must especially avoid ping ponging "set temperature"!
|
||||
// Otherwise we are supplied with the default params for standalone mode, which we
|
||||
// then instil the NV parameters
|
||||
m_TxFrame = basisFrame;
|
||||
|
||||
// ALWAYS install on/off commands if required
|
||||
m_TxFrame.resetCommand(); // no command upon blue wire initially, unless a request is pending
|
||||
if(m_bOnReq) {
|
||||
m_bOnReq = false;
|
||||
m_TxFrame.onCommand();
|
||||
}
|
||||
if(m_bOffReq) {
|
||||
m_bOffReq = false;
|
||||
m_TxFrame.offCommand();
|
||||
}
|
||||
|
||||
// 0x78 prevents the controller showing bum information when we parrot the OEM controller
|
||||
// heater is happy either way, the OEM controller has set the max/min stuff already
|
||||
m_Frame.Data[0] = self ? 0x76 : 0x78;
|
||||
if(isBTCmaster) {
|
||||
m_TxFrame.setActiveMode(); // this allows heater to svae the tuning params to EEPROM
|
||||
m_TxFrame.setFan_Min(pNVStorage->getFmin());
|
||||
m_TxFrame.setFan_Max(pNVStorage->getFmax());
|
||||
m_TxFrame.setPump_Min(pNVStorage->getPmin());
|
||||
m_TxFrame.setPump_Max(pNVStorage->getPmax());
|
||||
m_TxFrame.setThermostatMode(pNVStorage->getThermostatMode());
|
||||
m_TxFrame.setTemperature_Desired(pNVStorage->getTemperature());
|
||||
}
|
||||
else {
|
||||
m_TxFrame.setPassiveMode(); // this prevents the tuning parameters being saved by heater
|
||||
}
|
||||
|
||||
if(timenow == 0)
|
||||
// ensure CRC valid
|
||||
m_TxFrame.setCRC();
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::Start(unsigned long timenow)
|
||||
{
|
||||
if(timenow == 0) // avoid a black hole if millis() wraps
|
||||
timenow++;
|
||||
|
||||
m_nStartTime = timenow;
|
||||
m_bTxPending = true;
|
||||
}
|
||||
|
||||
// generate a Tx Gate, then send the TxFrame to the Blue wire
|
||||
// Note the serial data is ISR driven, we need to hold off
|
||||
// for a while to let teh buffewred dat clear before closing the Tx Gate.
|
||||
bool
|
||||
CTxManage::CheckTx(unsigned long timenow)
|
||||
{
|
||||
|
@ -55,51 +94,20 @@ CTxManage::CheckTx(unsigned long timenow)
|
|||
|
||||
if(diff > m_nStartDelay) {
|
||||
// begin front porch of Tx gating pulse
|
||||
digitalWrite(m_nTxEnbPin, HIGH);
|
||||
digitalWrite(m_nTxGatePin, HIGH);
|
||||
}
|
||||
if(m_bTxPending && (diff > (m_nStartDelay + m_nFrontPorch))) {
|
||||
// begin serial transmission
|
||||
m_bTxPending = false;
|
||||
_send();
|
||||
m_BlueWireSerial.write(m_TxFrame.Data, 24); // write native binary values
|
||||
DebugReportFrame("BTC ", m_TxFrame, " "); // report frame to debug port
|
||||
}
|
||||
if(diff > (m_nStartDelay + m_nFrameTime)) {
|
||||
// conclude Tx gating
|
||||
m_nStartTime = 0;
|
||||
digitalWrite(m_nTxEnbPin, LOW);
|
||||
digitalWrite(m_nTxGatePin, LOW);
|
||||
}
|
||||
}
|
||||
return m_nStartTime == 0;
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::_send()
|
||||
{
|
||||
// install on/off commands if required
|
||||
if(m_bOnReq) {
|
||||
m_bOnReq = false;
|
||||
m_Frame.Controller.Command = 0xa0;
|
||||
}
|
||||
else if(m_bOffReq) {
|
||||
m_bOffReq = false;
|
||||
m_Frame.Controller.Command = 0x05;
|
||||
}
|
||||
else {
|
||||
m_Frame.Controller.Command = 0x00;
|
||||
}
|
||||
|
||||
// ensure CRC valid
|
||||
m_Frame.setCRC();
|
||||
|
||||
// send to heater - using binary
|
||||
for(int i=0; i<24; i++) {
|
||||
m_Serial.write(m_Frame.Data[i]); // write native binary values
|
||||
}
|
||||
|
||||
Report();
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::Report()
|
||||
{
|
||||
SerialReport("Self ", m_Frame.Data, " ");
|
||||
}
|
||||
|
|
|
@ -8,24 +8,24 @@ class CTxManage
|
|||
const int m_nFrontPorch = 2;
|
||||
|
||||
public:
|
||||
CTxManage(int TxEnbPin, HardwareSerial& serial);
|
||||
void RequestOn();
|
||||
void RequestOff();
|
||||
void Start(const CProtocol& ref, unsigned long timenow, bool self);
|
||||
CTxManage(int TxGatePin, HardwareSerial& serial);
|
||||
void queueOnRequest();
|
||||
void queueOffRequest();
|
||||
void PrepareFrame(const CProtocol& Frame, bool isBTCmaster);
|
||||
void Start(unsigned long timenow);
|
||||
bool CheckTx(unsigned long timenow);
|
||||
void Report();
|
||||
void begin();
|
||||
const CProtocol& getFrame() const { return m_TxFrame; };
|
||||
|
||||
private:
|
||||
CProtocol m_Frame;
|
||||
CProtocol m_TxFrame;
|
||||
bool m_bOnReq;
|
||||
bool m_bOffReq;
|
||||
bool m_bTxPending;
|
||||
int m_nTxEnbPin;
|
||||
int m_nTxGatePin;
|
||||
unsigned long m_nStartTime;
|
||||
HardwareSerial& m_Serial;
|
||||
HardwareSerial& m_BlueWireSerial;
|
||||
|
||||
void _send();
|
||||
};
|
||||
|
||||
extern CTxManage TxManage;
|
||||
|
|
8
Arduino/SenderTrial2/debugport.h
Normal file
8
Arduino/SenderTrial2/debugport.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
|
||||
#if defined(__arm__)
|
||||
// Typically Arduino Due
|
||||
static UARTClass& DebugPort(Serial);
|
||||
#else
|
||||
static HardwareSerial& DebugPort(Serial); // reference Serial as DebugPort
|
||||
#endif
|
|
@ -1,8 +1,4 @@
|
|||
#if defined(__ESP32__)
|
||||
const int TxEnbPin = 22;
|
||||
#else
|
||||
const int TxEnbPin = 20;
|
||||
#endif
|
||||
const int ListenOnlyPin = 21;
|
||||
const int KeyPin = 15;
|
||||
const int Tx1Pin = 18;
|
||||
|
@ -10,10 +6,3 @@ const int Rx1Pin = 19;
|
|||
const int Tx2Pin = 16;
|
||||
const int Rx2Pin = 17;
|
||||
|
||||
#if defined(__arm__)
|
||||
// for Arduino Due
|
||||
static UARTClass& USB(Serial); // TODO: make proper ESP32 BT client
|
||||
#else
|
||||
// for ESP32, Mega
|
||||
static HardwareSerial& USB(Serial); // TODO: make proper ESP32 BT client
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue