Merge branch 'ESP32Bluetooth' into 'master'
Esp32 bluetooth See merge request mrjones.id.au/bluetoothheater!2
This commit is contained in:
commit
8fd8a314dd
BIN
AppInventor/BluetoothHeater.aia
Normal file
BIN
AppInventor/BluetoothHeater.aia
Normal file
Binary file not shown.
|
@ -3,6 +3,8 @@
|
||||||
{
|
{
|
||||||
"name": "Win32",
|
"name": "Win32",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
|
"C:\\Program Files (x86)\\Arduino\\tools\\**",
|
||||||
|
"C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\**",
|
||||||
"C:\\Users\\ray\\AppData\\Local\\Arduino15\\packages\\esp32\\tools\\**",
|
"C:\\Users\\ray\\AppData\\Local\\Arduino15\\packages\\esp32\\tools\\**",
|
||||||
"C:\\Users\\ray\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\1.0.0\\**",
|
"C:\\Users\\ray\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\1.0.0\\**",
|
||||||
"C:\\Users\\ray\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\**",
|
"C:\\Users\\ray\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\**",
|
||||||
|
|
12
Arduino/SenderTrial2/.vscode/settings.json
vendored
12
Arduino/SenderTrial2/.vscode/settings.json
vendored
|
@ -2,5 +2,15 @@
|
||||||
"sketch": "SenderTrial2.ino",
|
"sketch": "SenderTrial2.ino",
|
||||||
"port": "COM4",
|
"port": "COM4",
|
||||||
"board": "arduino:sam:arduino_due_x_dbg",
|
"board": "arduino:sam:arduino_due_x_dbg",
|
||||||
"output": "c:\\Users\\ray\\AppData\\Local\\Arduino\\"
|
"output": "c:\\Users\\ray\\AppData\\Local\\Arduino\\",
|
||||||
|
"files.associations": {
|
||||||
|
"list": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"xhash": "cpp",
|
||||||
|
"xstring": "cpp",
|
||||||
|
"xtree": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"xutility": "cpp"
|
||||||
|
}
|
||||||
}
|
}
|
12
Arduino/SenderTrial2/Bluetooth.h
Normal file
12
Arduino/SenderTrial2/Bluetooth.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
class CProtocol;
|
||||||
|
|
||||||
|
void Bluetooth_Init();
|
||||||
|
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame);
|
||||||
|
void Bluetooth_Check();
|
||||||
|
|
||||||
|
extern void Command_Interpret(String line); // decodes received command lines, implemented in main .ino file!
|
||||||
|
|
||||||
|
|
||||||
|
|
218
Arduino/SenderTrial2/BluetoothESP32.cpp
Normal file
218
Arduino/SenderTrial2/BluetoothESP32.cpp
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
#include "Bluetooth.h"
|
||||||
|
#include "pins.h"
|
||||||
|
#include "Protocol.h"
|
||||||
|
#include "debugport.h"
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
|
||||||
|
const int LED = 2;
|
||||||
|
|
||||||
|
// ESP32
|
||||||
|
|
||||||
|
String BluetoothRxLine;
|
||||||
|
|
||||||
|
#ifndef ESP32_USE_BLE_RLJ
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// CLASSIC BLUETOOTH
|
||||||
|
// |
|
||||||
|
// V
|
||||||
|
|
||||||
|
|
||||||
|
#include "BluetoothSerial.h"
|
||||||
|
|
||||||
|
BluetoothSerial SerialBT;
|
||||||
|
|
||||||
|
void Bluetooth_Init()
|
||||||
|
{
|
||||||
|
pinMode(LED, OUTPUT);
|
||||||
|
|
||||||
|
if(!SerialBT.begin("ESPHEATER")) {
|
||||||
|
DebugPort.println("An error occurred initialising Bluetooth");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bluetooth_Check()
|
||||||
|
{
|
||||||
|
if(SerialBT.available()) {
|
||||||
|
char rxVal = SerialBT.read();
|
||||||
|
if(isControl(rxVal)) { // "End of Line"
|
||||||
|
BluetoothRxLine += '\0';
|
||||||
|
Command_Interpret(BluetoothRxLine);
|
||||||
|
BluetoothRxLine = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BluetoothRxLine += rxVal; // append new char to our Rx buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame)
|
||||||
|
{
|
||||||
|
if(SerialBT.hasClient()) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ^
|
||||||
|
// |
|
||||||
|
// CLASSIC BLUETOOTH
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#else // ESP32_USE_BLE_RLJ
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// BLE
|
||||||
|
// |
|
||||||
|
// V
|
||||||
|
|
||||||
|
|
||||||
|
#include <BLEDevice.h>
|
||||||
|
#include <BLEServer.h>
|
||||||
|
#include <BLEUtils.h>
|
||||||
|
#include <BLE2902.h>
|
||||||
|
|
||||||
|
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
|
||||||
|
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||||
|
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||||
|
|
||||||
|
void BLE_Send(std::string Data);
|
||||||
|
|
||||||
|
BLEServer *pServer = NULL;
|
||||||
|
BLECharacteristic* pTxCharacteristic = NULL;
|
||||||
|
volatile bool deviceConnected = false;
|
||||||
|
bool oldDeviceConnected = false;
|
||||||
|
|
||||||
|
class MyServerCallbacks : public BLEServerCallbacks {
|
||||||
|
|
||||||
|
void onConnect(BLEServer* pServer) {
|
||||||
|
deviceConnected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnect(BLEServer* pServer) {
|
||||||
|
deviceConnected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MyCallbacks : public BLECharacteristicCallbacks {
|
||||||
|
|
||||||
|
// this callback is called when the ESP WRITE characteristic has been written to by a client
|
||||||
|
// We need to *read* the new information!
|
||||||
|
void onWrite(BLECharacteristic* pCharacteristic) {
|
||||||
|
|
||||||
|
std::string rxValue = pCharacteristic->getValue();
|
||||||
|
|
||||||
|
while(rxValue.length() > 0) {
|
||||||
|
char rxVal = rxValue[0];
|
||||||
|
if(isControl(rxVal)) { // "End of Line"
|
||||||
|
Command_Interpret(BluetoothRxLine);
|
||||||
|
BluetoothRxLine = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BluetoothRxLine += rxVal; // append new char to our Rx buffer
|
||||||
|
}
|
||||||
|
rxValue.erase(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void Bluetooth_Init()
|
||||||
|
{
|
||||||
|
// create the BLE device
|
||||||
|
BLEDevice::init("DieselHeater");
|
||||||
|
|
||||||
|
// create the BLE server
|
||||||
|
pServer = BLEDevice::createServer();
|
||||||
|
pServer->setCallbacks(new MyServerCallbacks);
|
||||||
|
|
||||||
|
// create the BLE service
|
||||||
|
BLEService *pService = pServer->createService(SERVICE_UUID);
|
||||||
|
|
||||||
|
// create a BLE characteristic
|
||||||
|
pTxCharacteristic = pService->createCharacteristic(
|
||||||
|
CHARACTERISTIC_UUID_TX,
|
||||||
|
BLECharacteristic::PROPERTY_NOTIFY
|
||||||
|
);
|
||||||
|
pTxCharacteristic->addDescriptor(new BLE2902());
|
||||||
|
|
||||||
|
|
||||||
|
BLECharacteristic* pRxCharacteristic = pService->createCharacteristic(
|
||||||
|
CHARACTERISTIC_UUID_RX,
|
||||||
|
BLECharacteristic::PROPERTY_WRITE
|
||||||
|
);
|
||||||
|
pRxCharacteristic->setCallbacks(new MyCallbacks/*()*/);
|
||||||
|
|
||||||
|
// start the service
|
||||||
|
pService->start();
|
||||||
|
// start advertising
|
||||||
|
pServer->getAdvertising()->start();
|
||||||
|
DebugPort.println("Awaiting a client to notify...");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bluetooth_Report(const char* pHdr, const CProtocol& Frame)
|
||||||
|
{
|
||||||
|
if(deviceConnected) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bluetooth_Check()
|
||||||
|
{
|
||||||
|
// disconnecting
|
||||||
|
if (!deviceConnected && oldDeviceConnected) {
|
||||||
|
delay(500); // give the bluetooth stack the chance to get things ready
|
||||||
|
pServer->startAdvertising(); // restart advertising
|
||||||
|
DebugPort.println("start advertising");
|
||||||
|
oldDeviceConnected = deviceConnected;
|
||||||
|
}
|
||||||
|
// connecting
|
||||||
|
if (deviceConnected && !oldDeviceConnected) {
|
||||||
|
// do stuff here on connecting
|
||||||
|
oldDeviceConnected = deviceConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// break down supplied string into 20 byte chunks (or less)
|
||||||
|
// BLE can only handle 20 bytes per packet!
|
||||||
|
void BLE_Send(std::string Data)
|
||||||
|
{
|
||||||
|
while(!Data.empty()) {
|
||||||
|
std::string substr = Data.substr(0, 20);
|
||||||
|
int len = substr.length();
|
||||||
|
pTxCharacteristic->setValue((uint8_t*)Data.data(), len);
|
||||||
|
pTxCharacteristic->notify();
|
||||||
|
Data.erase(0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ^
|
||||||
|
// |
|
||||||
|
// BLE
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // ESP32_USE_BLE_RLJ
|
||||||
|
|
||||||
|
#endif // __ESP32__
|
155
Arduino/SenderTrial2/BluetoothHC05.cpp
Normal file
155
Arduino/SenderTrial2/BluetoothHC05.cpp
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
#include "Bluetooth.h"
|
||||||
|
#include "pins.h"
|
||||||
|
#include "Protocol.h"
|
||||||
|
#include "debugport.h"
|
||||||
|
|
||||||
|
// Bluetooth access via HC-05 Module, using a UART
|
||||||
|
|
||||||
|
#ifndef ESP32
|
||||||
|
// NOTE: ESP32 uses an entirely different mechanism, please refer to BluetoothESP32.cpp/.h
|
||||||
|
|
||||||
|
#ifdef __arm__
|
||||||
|
// for Arduino Due
|
||||||
|
static UARTClass& Bluetooth(Serial2);
|
||||||
|
#else
|
||||||
|
// for Mega
|
||||||
|
static HardwareSerial& Bluetooth(Serial2); // TODO: make proper ESP32 BT client
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Bluetooth_ATCommand(const char* cmd);
|
||||||
|
|
||||||
|
String BluetoothRxData;
|
||||||
|
|
||||||
|
const int BTRates[] = {
|
||||||
|
9600, 38400, 115200, 19200, 57600, 2400, 4800
|
||||||
|
};
|
||||||
|
|
||||||
|
bool bHC05Available = false;
|
||||||
|
|
||||||
|
void Bluetooth_Init()
|
||||||
|
{
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
Bluetooth.begin(9600);
|
||||||
|
digitalWrite(KeyPin, HIGH);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
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++) {
|
||||||
|
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_ATCommand("AT\r\n")) {
|
||||||
|
DebugPort.println(" OK.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// failed, try another baud rate
|
||||||
|
DebugPort.println("");
|
||||||
|
Bluetooth.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugPort.println("");
|
||||||
|
if(BTidx == maxTries) {
|
||||||
|
DebugPort.println("FAILED to detect HC-05 Bluetooth module :-(");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(BTRates[BTidx] == 115200) {
|
||||||
|
DebugPort.println("HC-05 found and already set to 115200 baud, skipping Init.");
|
||||||
|
bHC05Available = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
do {
|
||||||
|
DebugPort.println("HC-05 found");
|
||||||
|
|
||||||
|
DebugPort.print(" Setting Name to \"DieselHeater\"... ");
|
||||||
|
if(!Bluetooth_ATCommand("AT+NAME=\"DieselHeater\"\r\n")) {
|
||||||
|
DebugPort.println("FAILED");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DebugPort.println("OK");
|
||||||
|
|
||||||
|
DebugPort.print(" Setting baud rate to 115200N81...");
|
||||||
|
if(!Bluetooth_ATCommand("AT+UART=115200,1,0\r\n")) {
|
||||||
|
DebugPort.println("FAILED");
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
DebugPort.println("OK");
|
||||||
|
|
||||||
|
Bluetooth.begin(115200);
|
||||||
|
bHC05Available = true;
|
||||||
|
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
digitalWrite(KeyPin, LOW); // leave HC-05 command mode
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
if(!bHC05Available)
|
||||||
|
Bluetooth.end(); // close serial port if no module found
|
||||||
|
|
||||||
|
DebugPort.println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bluetooth_Check()
|
||||||
|
{
|
||||||
|
// check for data coming back over Bluetooth
|
||||||
|
if(bHC05Available) {
|
||||||
|
if(Bluetooth.available()) {
|
||||||
|
char rxVal = Bluetooth.read();
|
||||||
|
if(isControl(rxVal)) { // "End of Line"
|
||||||
|
BluetoothRxData += '\0';
|
||||||
|
Command_Interpret(BluetoothRxData);
|
||||||
|
BluetoothRxData = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BluetoothRxData += rxVal; // append new char to our Rx buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame)
|
||||||
|
{
|
||||||
|
if(bHC05Available) {
|
||||||
|
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_ATCommand(const char* cmd)
|
||||||
|
{
|
||||||
|
if(bHC05Available) {
|
||||||
|
Bluetooth.print(cmd);
|
||||||
|
char RxBuffer[16];
|
||||||
|
memset(RxBuffer, 0, 16);
|
||||||
|
int read = Bluetooth.readBytesUntil('\n', RxBuffer, 16); // \n is not included in returned string!
|
||||||
|
if((read == 3) && (0 == strcmp(RxBuffer, "OK\r")) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
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 <Arduino.h>
|
||||||
#include "Protocol.h"
|
#include "Protocol.h"
|
||||||
|
#include "debugport.h"
|
||||||
|
|
||||||
unsigned short
|
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
|
// calculate a CRC-16/MODBUS checksum using the first 22 bytes of the data array
|
||||||
unsigned short wCRCWord = 0xFFFF;
|
unsigned short wCRCWord = 0xFFFF;
|
||||||
|
|
||||||
int wLength = len;
|
int wLength = len;
|
||||||
unsigned char* pData = Data;
|
const unsigned char* pData = Data;
|
||||||
while (wLength--)
|
while (wLength--)
|
||||||
{
|
{
|
||||||
unsigned char nTemp = *pData++ ^ wCRCWord;
|
unsigned char nTemp = *pData++ ^ wCRCWord;
|
||||||
|
@ -34,20 +35,29 @@ CProtocol::setCRC(unsigned short CRC)
|
||||||
|
|
||||||
|
|
||||||
unsigned short
|
unsigned short
|
||||||
CProtocol::getCRC()
|
CProtocol::getCRC() const
|
||||||
{
|
{
|
||||||
unsigned short CRC;
|
unsigned short CRC;
|
||||||
CRC = Data[22]; // MSB of CRC in Data[22]
|
CRC = Data[22]; // MSB of CRC in Data[22]
|
||||||
CRC <<= 8;
|
CRC <<= 8;
|
||||||
CRC |= Data[23]; // LSB of CRC in Data[23]
|
CRC |= Data[23]; // LSB of CRC in Data[23]
|
||||||
|
return CRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true for CRC match
|
// return true for CRC match
|
||||||
bool
|
bool
|
||||||
CProtocol::verifyCRC()
|
CProtocol::verifyCRC() const
|
||||||
{
|
{
|
||||||
unsigned short CRC = CalcCRC(22); // calculate CRC based on first 22 bytes
|
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&
|
CProtocol&
|
||||||
|
@ -57,21 +67,6 @@ CProtocol::operator=(const CProtocol& rhs)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
CProtocol::getCommand()
|
|
||||||
{
|
|
||||||
return Controller.Command;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CProtocol::setCommand(int cmd)
|
|
||||||
{
|
|
||||||
Controller.Command = cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*unsigned char getCommand();
|
|
||||||
void setCommand(int mode);*/
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CProtocol::setFan_Min(short Speed)
|
CProtocol::setFan_Min(short Speed)
|
||||||
|
|
|
@ -98,16 +98,24 @@ public:
|
||||||
public:
|
public:
|
||||||
CProtocol() { Init(0); };
|
CProtocol() { Init(0); };
|
||||||
CProtocol(int TxMode) { Init(TxMode); };
|
CProtocol(int TxMode) { Init(TxMode); };
|
||||||
|
|
||||||
void Init(int Txmode);
|
void Init(int Txmode);
|
||||||
// CRC handlers
|
// CRC handlers
|
||||||
unsigned short CalcCRC(int len); // calculate and set the CRC upon len bytes
|
unsigned short CalcCRC(int len) const; // calculate the CRC upon len bytes
|
||||||
void setCRC(); // calculate and set the CRC in the buffer
|
void setCRC(); // calculate and set the CRC in the buffer
|
||||||
void setCRC(unsigned short CRC); // 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
|
unsigned short getCRC() const; // extract CRC value from buffer
|
||||||
bool verifyCRC(); // return true for CRC match
|
bool verifyCRC() const; // return true for CRC match
|
||||||
// command
|
|
||||||
int getCommand();
|
void setActiveMode() { Controller.Byte0 = 0x76; }; // this allows heater to save tuning params to EEPROM
|
||||||
void setCommand(int mode);
|
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
|
// Run state
|
||||||
unsigned char getRunState() { return Heater.RunState; };
|
unsigned char getRunState() { return Heater.RunState; };
|
||||||
void setRunState(unsigned char state) { Heater.RunState = state; };
|
void setRunState(unsigned char state) { Heater.RunState = state; };
|
||||||
|
@ -144,10 +152,13 @@ public:
|
||||||
unsigned char getTemperature_Desired() { return Controller.DesiredTemperature; };
|
unsigned char getTemperature_Desired() { return Controller.DesiredTemperature; };
|
||||||
unsigned char getTemperature_Min() { return Controller.MinTemperature; };
|
unsigned char getTemperature_Min() { return Controller.MinTemperature; };
|
||||||
unsigned char getTemperature_Max() { return Controller.MaxTemperature; };
|
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_Current(); // glow plug current
|
||||||
short getGlowPlug_Voltage(); // glow plug voltage
|
short getGlowPlug_Voltage(); // glow plug voltage
|
||||||
void setGlowPlug_Current(short ampsx100); // glow plug current
|
void setGlowPlug_Current(short ampsx100); // glow plug current
|
||||||
void setGlowPlug_Voltage(short voltsx10); // glow plug voltage
|
void setGlowPlug_Voltage(short voltsx10); // glow plug voltage
|
||||||
|
// heat exchanger
|
||||||
short getTemperature_HeatExchg(); // temperature of heat exchanger
|
short getTemperature_HeatExchg(); // temperature of heat exchanger
|
||||||
void setTemperature_HeatExchg(short degC); // 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
|
Chinese Heater Half Duplex Serial Data Sending Tool
|
||||||
|
|
||||||
Connects to the blue wire of a Chinese heater, which is the half duplex serial link.
|
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.
|
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
|
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.
|
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.
|
no control from the Arduino will be allowed.
|
||||||
This allows sniffing of the blue wire in a normal system.
|
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
|
If it has been > 100ms since the last blue wire activity this indicates a new frame
|
||||||
sequence is starting from the OEM controller.
|
sequence is starting from the OEM controller.
|
||||||
Synchronise as such then count off the next 24 bytes storing them in the Controller's
|
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.
|
It is then expected the heater will respond with it's 24 bytes.
|
||||||
Capture those bytes and store them in the Heater1 data array.
|
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
|
If no activity is sensed in a second, it is assumed no controller is attached and we
|
||||||
have full control over the heater.
|
have full control over the heater.
|
||||||
|
@ -64,18 +64,33 @@
|
||||||
|
|
||||||
#include "Protocol.h"
|
#include "Protocol.h"
|
||||||
#include "TxManage.h"
|
#include "TxManage.h"
|
||||||
|
#include "pins.h"
|
||||||
|
#include "NVStorage.h"
|
||||||
|
#include "debugport.h"
|
||||||
|
|
||||||
void SerialReport(const char* hdr, const unsigned char* pData, const char* ftr);
|
#define BLUETOOTH
|
||||||
void BluetoothDetect();
|
#define DEBUG_BTRX
|
||||||
bool BlueToothCommand(const char* cmd);
|
|
||||||
void BlueToothReport(const char* pHdr, const unsigned char Data[24]);
|
#ifdef BLUETOOTH
|
||||||
void BluetoothInterpret();
|
#include "Bluetooth.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__arm__)
|
||||||
|
// 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 DebugReportFrame(const char* hdr, const CProtocol& Frame, const char* ftr);
|
||||||
|
|
||||||
class CommStates {
|
class CommStates {
|
||||||
public:
|
public:
|
||||||
// comms states
|
// comms states
|
||||||
enum eCS {
|
enum eCS {
|
||||||
Idle, ControllerRx, ControllerReport, HeaterRx1, HeaterReport1, SelfTx, HeaterRx2, HeaterReport2
|
Idle, ControllerRx, ControllerReport, HeaterRx1, HeaterReport1, BTC_Tx, HeaterRx2, HeaterReport2
|
||||||
};
|
};
|
||||||
CommStates() {
|
CommStates() {
|
||||||
set(Idle);
|
set(Idle);
|
||||||
|
@ -96,123 +111,100 @@ private:
|
||||||
int m_Count;
|
int m_Count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__arm__)
|
|
||||||
// for Arduino Due
|
|
||||||
UARTClass& USB(Serial);
|
|
||||||
UARTClass& BlueWire(Serial1);
|
|
||||||
UARTClass& BlueTooth(Serial2);
|
|
||||||
#else
|
|
||||||
// for ESP32, Mega
|
|
||||||
HardwareSerial& USB(Serial);
|
|
||||||
HardwareSerial& BlueWire(Serial1);
|
|
||||||
#if defined(__ESP32__)
|
|
||||||
// ESP32
|
|
||||||
HardwareSerial& BlueTooth(Serial2); // TODO: make proper ESP32 BT client
|
|
||||||
#else
|
|
||||||
// Mega
|
|
||||||
HardwareSerial& BlueTooth(Serial2);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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;
|
|
||||||
const int Rx1Pin = 19;
|
|
||||||
const int Tx2Pin = 16;
|
|
||||||
const int Rx2Pin = 17;
|
|
||||||
|
|
||||||
const int BTRates[] = {
|
|
||||||
9600, 38400, 115200, 19200, 57600, 2400, 4800
|
|
||||||
};
|
|
||||||
|
|
||||||
CommStates CommState;
|
CommStates CommState;
|
||||||
CTxManage TxManage(TxEnbPin, Serial1);
|
CTxManage TxManage(TxEnbPin, BlueWire);
|
||||||
CProtocol Controller; // most recent data packet received from OEM controller found on blue wire
|
CProtocol OEMControllerFrame; // data packet received from heater in response to OEM controller packet
|
||||||
CProtocol Heater1; // 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 Heater2; // data packet received from heater in response to our packet
|
CProtocol HeaterFrame2; // data packet received from heater in response to our packet
|
||||||
CProtocol SelfParams(CProtocol::CtrlMode); // holds our local parameters, used in case of no OEM controller
|
CProtocol DefaultBTCParams(CProtocol::CtrlMode); // defines the default parameters, used in case of no OEM controller
|
||||||
long lastRxTime; // used to observe inter character delays
|
long lastRxTime; // used to observe inter character delays
|
||||||
bool bBlueToothAvailable = false;
|
|
||||||
String BluetoothRxData;
|
|
||||||
|
|
||||||
|
// 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()
|
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:
|
// 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(ListenOnlyPin, INPUT_PULLUP);
|
||||||
pinMode(KeyPin, OUTPUT);
|
pinMode(KeyPin, OUTPUT);
|
||||||
// pinMode(Tx2Pin, OUTPUT);
|
|
||||||
digitalWrite(KeyPin, LOW);
|
digitalWrite(KeyPin, LOW);
|
||||||
// digitalWrite(Tx2Pin, HIGH);
|
|
||||||
|
|
||||||
#if defined(__arm__) || defined(__AVR__)
|
#if defined(__arm__) || defined(__AVR__)
|
||||||
BlueWire.begin(25000);
|
BlueWire.begin(25000);
|
||||||
pinMode(19, INPUT_PULLUP); // required for MUX to work properly
|
pinMode(Rx1Pin, INPUT_PULLUP); // required for MUX to work properly
|
||||||
#else if defined(__ESP32__)
|
#elif ESP32
|
||||||
// ESP32
|
// ESP32
|
||||||
#define RXD2 16
|
BlueWire.begin(25000, SERIAL_8N1, Rx1Pin, Tx1Pin); // need to explicitly specify pins for pin multiplexer!
|
||||||
#define TXD2 17
|
pinMode(Rx1Pin, INPUT_PULLUP); // required for MUX to work properly
|
||||||
BlueWire.begin(25000, SERIAL_8N1, Rx1Pin, Tx1Pin);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// initialise serial monitor on serial port 0
|
// 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
|
// prepare for first long delay detection
|
||||||
lastRxTime = millis();
|
lastRxTime = millis();
|
||||||
|
|
||||||
TxManage.begin(); // ensure Tx enable pin setup
|
TxManage.begin(); // ensure Tx enable pin is setup
|
||||||
|
|
||||||
// define defaults should heater controller be missing
|
// define defaults should heater controller be missing
|
||||||
SelfParams.setTemperature_Desired(23);
|
DefaultBTCParams.setTemperature_Desired(23);
|
||||||
SelfParams.setTemperature_Actual(22);
|
DefaultBTCParams.setTemperature_Actual(22);
|
||||||
SelfParams.Controller.OperatingVoltage = 120;
|
DefaultBTCParams.Controller.OperatingVoltage = 120;
|
||||||
SelfParams.setPump_Min(16);
|
DefaultBTCParams.setPump_Min(16);
|
||||||
SelfParams.setPump_Max(55);
|
DefaultBTCParams.setPump_Max(55);
|
||||||
SelfParams.setFan_Min(1680);
|
DefaultBTCParams.setFan_Min(1680);
|
||||||
SelfParams.setFan_Max(4500);
|
DefaultBTCParams.setFan_Max(4500);
|
||||||
|
|
||||||
BluetoothDetect();
|
#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()
|
void loop()
|
||||||
{
|
{
|
||||||
unsigned long timenow = millis();
|
unsigned long timenow = millis();
|
||||||
|
|
||||||
// check for test commands received from PC Over USB
|
// check for test commands received from PC Over USB
|
||||||
if(USB.available()) {
|
if(DebugPort.available()) {
|
||||||
char rxval = USB.read();
|
char rxval = DebugPort.read();
|
||||||
if(rxval == '+') {
|
if(rxval == '+') {
|
||||||
TxManage.RequestOn();
|
TxManage.queueOnRequest();
|
||||||
}
|
}
|
||||||
if(rxval == '-') {
|
if(rxval == '-') {
|
||||||
TxManage.RequestOff();
|
TxManage.queueOffRequest();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for data coming back over Bluetooth
|
|
||||||
if(BlueTooth.available()) {
|
|
||||||
char rxVal = BlueTooth.read();
|
|
||||||
if(isControl(rxVal)) { // "End of Line"
|
|
||||||
BluetoothRxData += '\0';
|
|
||||||
BluetoothInterpret();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BluetoothRxData += rxVal; // append new char to our Rx buffer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BLUETOOTH
|
||||||
|
Bluetooth_Check(); // check for Bluetooth activity
|
||||||
|
#endif
|
||||||
|
|
||||||
// Handle time interval where we send data to the blue wire
|
// Handle time interval where we send data to the blue wire
|
||||||
if(CommState.is(CommStates::SelfTx)) {
|
if(CommState.is(CommStates::BTC_Tx)) {
|
||||||
lastRxTime = timenow; // we are pumping onto blue wire, track this activity!
|
lastRxTime = timenow; // we are pumping onto blue wire, track this activity!
|
||||||
if(TxManage.CheckTx(timenow) ) { // monitor our data delivery
|
if(TxManage.CheckTx(timenow) ) { // monitor our data delivery
|
||||||
CommState.set(CommStates::HeaterRx2); // then await heater repsonse
|
CommState.set(CommStates::HeaterRx2); // then await heater repsonse
|
||||||
|
@ -226,12 +218,15 @@ void loop()
|
||||||
// check for no rx traffic => no OEM controller
|
// check for no rx traffic => no OEM controller
|
||||||
if(CommState.is(CommStates::Idle) && (RxTimeElapsed >= 970)) {
|
if(CommState.is(CommStates::Idle) && (RxTimeElapsed >= 970)) {
|
||||||
// have not seen any receive data for a second.
|
// have not seen any receive data for a second.
|
||||||
// OEM controller probably not connected.
|
// OEM controller is probably not connected.
|
||||||
// Skip to SelfTx, sending our own settings.
|
// Skip state machine immediately to BTC_Tx, sending our own settings.
|
||||||
CommState.set(CommStates::SelfTx);
|
CommState.set(CommStates::BTC_Tx);
|
||||||
bool bOurParams = true;
|
bool isBTCmaster = true;
|
||||||
TxManage.Start(SelfParams, timenow, bOurParams);
|
TxManage.PrepareFrame(DefaultBTCParams, isBTCmaster); // use our parameters, and mix in NV storage values
|
||||||
BlueToothReport("[BTC]", SelfParams.Data); // BTC => Bluetooth Controller :-)
|
TxManage.Start(timenow);
|
||||||
|
#ifdef BLUETOOTH
|
||||||
|
Bluetooth_SendFrame("[BTC]", TxManage.getFrame()); // BTC => Bluetooth Controller :-)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// precautionary action if all 24 bytes were not received whilst expecting them
|
// precautionary action if all 24 bytes were not received whilst expecting them
|
||||||
|
@ -244,7 +239,7 @@ void loop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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()) {
|
if (BlueWire.available()) {
|
||||||
|
|
||||||
lastRxTime = timenow;
|
lastRxTime = timenow;
|
||||||
|
@ -257,19 +252,19 @@ void loop()
|
||||||
int inByte = BlueWire.read(); // read hex byte
|
int inByte = BlueWire.read(); // read hex byte
|
||||||
|
|
||||||
if( CommState.is(CommStates::ControllerRx) ) {
|
if( CommState.is(CommStates::ControllerRx) ) {
|
||||||
if(CommState.saveData(Controller.Data, inByte) ) {
|
if(CommState.saveData(OEMControllerFrame.Data, inByte) ) {
|
||||||
CommState.set(CommStates::ControllerReport);
|
CommState.set(CommStates::ControllerReport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( CommState.is(CommStates::HeaterRx1) ) {
|
else if( CommState.is(CommStates::HeaterRx1) ) {
|
||||||
if( CommState.saveData(Heater1.Data, inByte) ) {
|
if( CommState.saveData(HeaterFrame1.Data, inByte) ) {
|
||||||
CommState.set(CommStates::HeaterReport1);
|
CommState.set(CommStates::HeaterReport1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( CommState.is(CommStates::HeaterRx2) ) {
|
else if( CommState.is(CommStates::HeaterRx2) ) {
|
||||||
if( CommState.saveData(Heater2.Data, inByte) ) {
|
if( CommState.saveData(HeaterFrame2.Data, inByte) ) {
|
||||||
CommState.set(CommStates::HeaterReport2);
|
CommState.set(CommStates::HeaterReport2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,174 +274,127 @@ void loop()
|
||||||
|
|
||||||
if( CommState.is(CommStates::ControllerReport) ) {
|
if( CommState.is(CommStates::ControllerReport) ) {
|
||||||
// filled controller frame, report
|
// filled controller frame, report
|
||||||
BlueToothReport("[OEM]", Controller.Data);
|
#ifdef BLUETOOTH
|
||||||
SerialReport("Ctrl ", Controller.Data, " ");
|
// echo received OEM controller frame over Bluetooth, using [OEM] header
|
||||||
|
Bluetooth_SendFrame("[OEM]", OEMControllerFrame);
|
||||||
|
#endif
|
||||||
|
DebugReportFrame("OEM ", OEMControllerFrame, " ");
|
||||||
CommState.set(CommStates::HeaterRx1);
|
CommState.set(CommStates::HeaterRx1);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(CommState.is(CommStates::HeaterReport1) ) {
|
else if(CommState.is(CommStates::HeaterReport1) ) {
|
||||||
// received heater frame (after controller message), report
|
// received heater frame (after controller message), report
|
||||||
SerialReport("Htr1 ", Heater1.Data, "\r\n");
|
DebugReportFrame("Htr1 ", HeaterFrame1, "\r\n");
|
||||||
BlueToothReport("[HTR]", Heater1.Data);
|
#ifdef BLUETOOTH
|
||||||
|
// echo heater reponse data to Bluetooth client
|
||||||
|
Bluetooth_SendFrame("[HTR]", HeaterFrame1);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(digitalRead(ListenOnlyPin)) {
|
if(digitalRead(ListenOnlyPin)) {
|
||||||
bool bOurParams = false;
|
bool isBTCmaster = false;
|
||||||
TxManage.Start(Controller, timenow, bOurParams);
|
TxManage.PrepareFrame(OEMControllerFrame, isBTCmaster); // parrot OEM parameters, but block NV modes
|
||||||
CommState.set(CommStates::SelfTx);
|
TxManage.Start(timenow);
|
||||||
|
CommState.set(CommStates::BTC_Tx);
|
||||||
}
|
}
|
||||||
else {
|
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) ) {
|
else if( CommState.is(CommStates::HeaterReport2) ) {
|
||||||
// received heater frame (after our control message), report
|
// received heater frame (after our control message), report
|
||||||
SerialReport("Htr2 ", Heater2.Data, "\r\n");
|
DebugReportFrame("Htr2 ", HeaterFrame2, "\r\n");
|
||||||
// if(!digitalRead(ListenOnlyPin)) {
|
// if(!digitalRead(ListenOnlyPin)) {
|
||||||
BlueToothReport("[HTR]", Heater2.Data); // pin not grounded, suppress duplicate to BT
|
#ifdef BLUETOOTH
|
||||||
|
Bluetooth_SendFrame("[HTR]", HeaterFrame2); // pin not grounded, suppress duplicate to BT
|
||||||
|
#endif
|
||||||
// }
|
// }
|
||||||
CommState.set(CommStates::Idle);
|
CommState.set(CommStates::Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // 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++) {
|
for(int i=0; i<24; i++) {
|
||||||
char str[16];
|
char str[16];
|
||||||
sprintf(str, "%02X ", pData[i]); // build 2 dig hex values
|
sprintf(str, "%02X ", Frame.Data[i]); // build 2 dig hex values
|
||||||
USB.print(str); // and print
|
DebugPort.print(str); // and print
|
||||||
}
|
}
|
||||||
USB.print(ftr); // footer
|
DebugPort.print(ftr); // footer
|
||||||
}
|
}
|
||||||
|
|
||||||
void BluetoothDetect()
|
void Command_Interpret(String line)
|
||||||
{
|
{
|
||||||
#if defined(__ESP32__)
|
unsigned char cVal;
|
||||||
#else
|
unsigned short sVal;
|
||||||
// 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.
|
|
||||||
BlueTooth.begin(9600);
|
|
||||||
digitalWrite(KeyPin, HIGH);
|
|
||||||
delay(500);
|
|
||||||
|
|
||||||
USB.println("\r\n\r\nAttempting to detect HC-05 Bluetooth module...");
|
#ifdef DEBUG_BTRX
|
||||||
|
DebugPort.println(line);
|
||||||
int BTidx = 0;
|
DebugPort.println();
|
||||||
int maxTries = sizeof(BTRates)/sizeof(int);
|
|
||||||
for(BTidx = 0; BTidx < maxTries; BTidx++) {
|
|
||||||
USB.print(" @ ");
|
|
||||||
USB.print(BTRates[BTidx]);
|
|
||||||
USB.print(" baud... ");
|
|
||||||
BlueTooth.begin(BTRates[BTidx]); // open serial port at a certain baud rate
|
|
||||||
BlueTooth.print("\r\n");
|
|
||||||
BlueTooth.setTimeout(50);
|
|
||||||
|
|
||||||
if(BlueToothCommand("AT\r\n")) {
|
|
||||||
USB.println(" OK.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// failed, try another baud rate
|
|
||||||
USB.println("");
|
|
||||||
BlueTooth.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
USB.println("");
|
|
||||||
if(BTidx == maxTries) {
|
|
||||||
USB.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.");
|
|
||||||
bBlueToothAvailable = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
do {
|
|
||||||
USB.println("HC-05 found");
|
|
||||||
|
|
||||||
USB.print(" Setting Name to \"DieselHeater\"... ");
|
|
||||||
if(!BlueToothCommand("AT+NAME=\"DieselHeater\"\r\n")) {
|
|
||||||
USB.println("FAILED");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
USB.println("OK");
|
|
||||||
|
|
||||||
USB.print(" Setting baud rate to 115200N81...");
|
|
||||||
if(!BlueToothCommand("AT+UART=115200,1,0\r\n")) {
|
|
||||||
USB.println("FAILED");
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
USB.println("OK");
|
|
||||||
|
|
||||||
BlueTooth.begin(115200);
|
|
||||||
bBlueToothAvailable = true;
|
|
||||||
|
|
||||||
} while(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
digitalWrite(KeyPin, LOW); // leave HC-05 command mode
|
|
||||||
|
|
||||||
delay(500);
|
|
||||||
|
|
||||||
if(!bBlueToothAvailable)
|
|
||||||
BlueTooth.end(); // close serial port if no module found
|
|
||||||
|
|
||||||
USB.println("");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
bool BlueToothCommand(const char* cmd)
|
if(line.startsWith("[CMD]") ) {
|
||||||
{
|
DebugPort.write("BT command Rx'd: ");
|
||||||
if(bBlueToothAvailable) {
|
|
||||||
BlueTooth.print(cmd);
|
|
||||||
char RxBuffer[16];
|
|
||||||
memset(RxBuffer, 0, 16);
|
|
||||||
int read = BlueTooth.readBytesUntil('\n', RxBuffer, 16); // \n is not included in returned string!
|
|
||||||
if((read == 3) && (0 == strcmp(RxBuffer, "OK\r")) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlueToothReport(const char* pHdr, const unsigned char Data[24])
|
|
||||||
{
|
|
||||||
if(bBlueToothAvailable) {
|
|
||||||
BlueTooth.print(pHdr);
|
|
||||||
BlueTooth.write(Data, 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BluetoothInterpret()
|
|
||||||
{
|
|
||||||
if(BluetoothRxData.startsWith("[CMD]") ) {
|
|
||||||
USB.write("BT command Rx'd: ");
|
|
||||||
// incoming command from BT app!
|
// incoming command from BT app!
|
||||||
BluetoothRxData.remove(0, 5); // strip away "[CMD]" header
|
line.remove(0, 5); // strip away "[CMD]" header
|
||||||
if(BluetoothRxData.startsWith("ON")) {
|
if(line.startsWith("ON") ) {
|
||||||
USB.write("ON\n");
|
DebugPort.write("ON\n");
|
||||||
TxManage.RequestOn();
|
TxManage.queueOnRequest();
|
||||||
}
|
}
|
||||||
else if(BluetoothRxData.startsWith("OFF")) {
|
else if(line.startsWith("OFF")) {
|
||||||
USB.write("OFF\n");
|
DebugPort.write("OFF\n");
|
||||||
TxManage.RequestOff();
|
TxManage.queueOffRequest();
|
||||||
}
|
}
|
||||||
else if(BluetoothRxData.startsWith("Pmin")) {
|
else if(line.startsWith("Pmin")) {
|
||||||
USB.write("Pmin\n");
|
line.remove(0, 4);
|
||||||
|
DebugPort.write("Pmin=");
|
||||||
|
cVal = (line.toFloat() * 10) + 0.5;
|
||||||
|
DebugPort.println(cVal);
|
||||||
|
pNVStorage->setPmin(cVal);
|
||||||
}
|
}
|
||||||
else if(BluetoothRxData.startsWith("Pmax")) {
|
else if(line.startsWith("Pmax")) {
|
||||||
USB.write("Pmax\n");
|
line.remove(0, 4);
|
||||||
|
DebugPort.write("Pmax=");
|
||||||
|
cVal = (line.toFloat() * 10) + 0.5;
|
||||||
|
DebugPort.println(cVal);
|
||||||
|
pNVStorage->setPmax(cVal);
|
||||||
}
|
}
|
||||||
else if(BluetoothRxData.startsWith("Fmin")) {
|
else if(line.startsWith("Fmin")) {
|
||||||
USB.write("Fmin\n");
|
line.remove(0, 4);
|
||||||
|
DebugPort.print("Fmin=");
|
||||||
|
sVal = line.toInt();
|
||||||
|
DebugPort.println(sVal);
|
||||||
|
pNVStorage->setFmin(sVal);
|
||||||
}
|
}
|
||||||
else if(BluetoothRxData.startsWith("Fmax")) {
|
else if(line.startsWith("Fmax")) {
|
||||||
USB.write("Fmax\n");
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BluetoothRxData = ""; //flush string, ready for new data
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,52 +1,90 @@
|
||||||
#include <Arduino.h>
|
|
||||||
#include "TxManage.h"
|
#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) :
|
CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) :
|
||||||
m_Serial(serial),
|
m_BlueWireSerial(serial),
|
||||||
m_Frame(CProtocol::CtrlMode)
|
m_TxFrame(CProtocol::CtrlMode)
|
||||||
{
|
{
|
||||||
m_bOnReq = false;
|
m_bOnReq = false;
|
||||||
m_bOffReq = false;
|
m_bOffReq = false;
|
||||||
m_bTxPending = false;
|
m_bTxPending = false;
|
||||||
m_nStartTime = 0;
|
m_nStartTime = 0;
|
||||||
m_nTxEnbPin = TxEnbPin;
|
m_nTxGatePin = TxGatePin;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxManage::begin()
|
void CTxManage::begin()
|
||||||
{
|
{
|
||||||
pinMode(m_nTxEnbPin, OUTPUT);
|
pinMode(m_nTxGatePin, OUTPUT);
|
||||||
digitalWrite(m_nTxEnbPin, LOW);
|
digitalWrite(m_nTxGatePin, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTxManage::RequestOn()
|
CTxManage::queueOnRequest()
|
||||||
{
|
{
|
||||||
m_bOnReq = true;
|
m_bOnReq = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTxManage::RequestOff()
|
CTxManage::queueOffRequest()
|
||||||
{
|
{
|
||||||
m_bOffReq = true;
|
m_bOffReq = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTxManage::Start(const CProtocol& ref, unsigned long timenow, bool self)
|
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
|
// 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
|
// 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++;
|
timenow++;
|
||||||
|
|
||||||
m_nStartTime = timenow;
|
m_nStartTime = timenow;
|
||||||
m_bTxPending = true;
|
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
|
bool
|
||||||
CTxManage::CheckTx(unsigned long timenow)
|
CTxManage::CheckTx(unsigned long timenow)
|
||||||
{
|
{
|
||||||
|
@ -56,51 +94,20 @@ CTxManage::CheckTx(unsigned long timenow)
|
||||||
|
|
||||||
if(diff > m_nStartDelay) {
|
if(diff > m_nStartDelay) {
|
||||||
// begin front porch of Tx gating pulse
|
// begin front porch of Tx gating pulse
|
||||||
digitalWrite(m_nTxEnbPin, HIGH);
|
digitalWrite(m_nTxGatePin, HIGH);
|
||||||
}
|
}
|
||||||
if(m_bTxPending && (diff > (m_nStartDelay + m_nFrontPorch))) {
|
if(m_bTxPending && (diff > (m_nStartDelay + m_nFrontPorch))) {
|
||||||
// begin serial transmission
|
// begin serial transmission
|
||||||
m_bTxPending = false;
|
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)) {
|
if(diff > (m_nStartDelay + m_nFrameTime)) {
|
||||||
// conclude Tx gating
|
// conclude Tx gating
|
||||||
m_nStartTime = 0;
|
m_nStartTime = 0;
|
||||||
digitalWrite(m_nTxEnbPin, LOW);
|
digitalWrite(m_nTxGatePin, LOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_nStartTime == 0;
|
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,23 +8,25 @@ class CTxManage
|
||||||
const int m_nFrontPorch = 2;
|
const int m_nFrontPorch = 2;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CTxManage(int TxEnbPin, HardwareSerial& serial);
|
CTxManage(int TxGatePin, HardwareSerial& serial);
|
||||||
void RequestOn();
|
void queueOnRequest();
|
||||||
void RequestOff();
|
void queueOffRequest();
|
||||||
void Start(const CProtocol& ref, unsigned long timenow, bool self);
|
void PrepareFrame(const CProtocol& Frame, bool isBTCmaster);
|
||||||
|
void Start(unsigned long timenow);
|
||||||
bool CheckTx(unsigned long timenow);
|
bool CheckTx(unsigned long timenow);
|
||||||
void Report();
|
|
||||||
void begin();
|
void begin();
|
||||||
|
const CProtocol& getFrame() const { return m_TxFrame; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CProtocol m_Frame;
|
CProtocol m_TxFrame;
|
||||||
bool m_bOnReq;
|
bool m_bOnReq;
|
||||||
bool m_bOffReq;
|
bool m_bOffReq;
|
||||||
bool m_bTxPending;
|
bool m_bTxPending;
|
||||||
int m_nTxEnbPin;
|
int m_nTxGatePin;
|
||||||
unsigned long m_nStartTime;
|
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
|
8
Arduino/SenderTrial2/pins.h
Normal file
8
Arduino/SenderTrial2/pins.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
const int TxEnbPin = 22;
|
||||||
|
const int ListenOnlyPin = 21;
|
||||||
|
const int KeyPin = 15;
|
||||||
|
const int Tx1Pin = 18;
|
||||||
|
const int Rx1Pin = 19;
|
||||||
|
const int Tx2Pin = 16;
|
||||||
|
const int Rx2Pin = 17;
|
||||||
|
|
Loading…
Reference in a new issue