Fine tuning OLED presentation, adding mini font

This commit is contained in:
rljonesau 2018-11-17 13:08:22 +11:00
parent 5158630996
commit 9d79c107c5
8 changed files with 730 additions and 12 deletions

View file

@ -113,6 +113,7 @@ static HardwareSerial& BlueWireSerial(Serial1);
OneWire ds(DS18B20_Pin); // on pin 5 (a 4.7K resistor is necessary)
DallasTemperature TempSensor(&ds);
long lastTemperatureTime; // used to moderate DS18B20 access
unsigned long lastAnimationTime;
float fFilteredTemperature = 0;
const float fAlpha = 0.995;
@ -126,6 +127,7 @@ CSmartError SmartError;
sRxLine PCline;
long lastRxTime; // used to observe inter character delays
bool hasOEMController = false;
bool stateDebug = false;
////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -191,6 +193,7 @@ void setup() {
TempSensor.setWaitForConversion(false);
TempSensor.requestTemperatures();
lastTemperatureTime = millis();
lastAnimationTime = millis();
initOLED();
@ -314,6 +317,9 @@ void loop()
val--;
bSendVal = true;
}
else if(rxVal == 's') {
stateDebug = !stateDebug;
}
}
if(bSendVal) {
switch(mode) {
@ -331,6 +337,7 @@ void loop()
}
}
Bluetooth.check(); // check for Bluetooth activity
// calc elapsed time since last rxd byte
@ -363,24 +370,44 @@ void loop()
// Reads data from the "blue wire" Serial port, (to/from heater)
// If an OEM controller exists we will also see it's data frames
// Note that the data is read now, then held for later use in the state machine
//
//s
sRxData BlueWireData;
if (BlueWireSerial.available()) {
// Data is avaialable, read and store it now, use it later
// Note that if not in a recognised data receive frame state, the data
// will be deliberately lost!
unsigned long dT = timenow - lastRxTime;
lastRxTime = timenow; // tickle last rx time, for rx data timeout purposes
BlueWireData.setValue(BlueWireSerial.read()); // read hex byte, store for later use
if(stateDebug) {
Serial.print("dT{");
Serial.print(dT);
Serial.print("}");
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// do our state machine to track the reception and delivery of blue wire data
unsigned long tDelta;
switch(CommState.get()) {
case CommStates::Idle:
if(stateDebug) {
Serial.print(":0");
}
// only update OLED when not processing blue wire
tDelta = timenow - lastAnimationTime;
if(tDelta >= 250) {
lastAnimationTime += 250;
animateOLED();
}
#if RX_LED == 1
digitalWrite(LED_Pin, LOW);
#endif
@ -408,7 +435,7 @@ void loop()
hasOEMController = true;
CommState.set(CommStates::OEMCtrlRx); // we must add this new byte!
//
// ** IMPORTANT - we must drop through to OEMCtrlRx *NOW* (skip break) **
// ** IMPORTANT - we must drop through to OEMCtrlRx *NOW* (skipping break) **
//
}
else {
@ -417,11 +444,18 @@ void loop()
case CommStates::OEMCtrlRx:
if(stateDebug) {
Serial.print(":1");
}
#if RX_LED == 1
digitalWrite(LED_Pin, HIGH);
#endif
// collect OEM controller frame
if(BlueWireData.available()) {
if(stateDebug) {
Serial.print(",RD1");
}
if(CommState.collectData(OEMCtrlFrame, BlueWireData.getValue()) ) {
CommState.set(CommStates::OEMCtrlReport); // collected 24 bytes, move on!
}
@ -430,6 +464,9 @@ void loop()
case CommStates::OEMCtrlReport:
if(stateDebug) {
Serial.print(":2");
}
#if RX_LED == 1
digitalWrite(LED_Pin, LOW);
#endif
@ -451,11 +488,17 @@ void loop()
case CommStates::HeaterRx1:
if(stateDebug) {
Serial.print(":3");
}
#if RX_LED == 1
digitalWrite(LED_Pin, HIGH);
#endif
// collect heater frame, always in response to an OEM controller frame
if(BlueWireData.available()) {
if(stateDebug) {
Serial.print(",RD2");
}
if( CommState.collectData(HeaterFrame1, BlueWireData.getValue()) ) {
CommState.set(CommStates::HeaterReport1);
}
@ -464,6 +507,9 @@ void loop()
case CommStates::HeaterReport1:
if(stateDebug) {
Serial.print(":4");
}
#if RX_LED == 1
digitalWrite(LED_Pin, LOW);
#endif
@ -505,6 +551,9 @@ void loop()
case CommStates::BTC_Tx:
if(stateDebug) {
Serial.print(":5");
}
// Handle time interval where we send data to the blue wire
lastRxTime = timenow; // *we* are pumping onto blue wire, track this activity!
if(TxManage.CheckTx(timenow) ) { // monitor progress of our data delivery
@ -518,12 +567,20 @@ void loop()
case CommStates::HeaterRx2:
if(stateDebug) {
Serial.print(":6");
}
#if RX_LED == 1
digitalWrite(LED_Pin, HIGH);
#endif
// collect heater frame, in response to our control frame
if(BlueWireData.available()) {
if( CommState.collectData(HeaterFrame2, BlueWireData.getValue()) ) {
if(stateDebug) {
Serial.print(",RD(");
Serial.print(BlueWireData.getValue(), HEX);
Serial.print(")");
}
if( CommState.collectDataEx(HeaterFrame2, BlueWireData.getValue()) ) {
CommState.set(CommStates::HeaterReport2);
}
}
@ -531,6 +588,9 @@ void loop()
case CommStates::HeaterReport2:
if(stateDebug) {
Serial.print(":7");
}
#if RX_LED == 1
digitalWrite(LED_Pin, LOW);
#endif
@ -550,6 +610,9 @@ void loop()
break;
case CommStates::TemperatureRead:
if(stateDebug) {
Serial.print(":8");
}
// update temperature reading,
// synchronised with serial reception as interrupts do get disabled in the OneWire library
unsigned Tdelta = timenow - lastTemperatureTime;
@ -562,17 +625,13 @@ void loop()
TempSensor.requestTemperatures(); // prep sensor for future reading
updateOLED(TxManage.getFrame(), HeaterFrame2);
/* display.clearDisplay();
showThermometer(TxManage.getFrame().getTemperature_Desired(), // read values from most recently sent [BTC] frame
TxManage.getFrame().getTemperature_Actual());
showBodyThermometer(HeaterFrame2.getTemperature_HeatExchg());
showBTicon();
showBatteryIcon();
display.display();*/
}
CommState.set(CommStates::Idle);
break;
} // switch(CommState)
BlueWireData.reset(); // ensure we flush any used data
} // loop

View file

@ -0,0 +1,169 @@
// 'Thermometer', 8x50px
const unsigned char thermometerBitmap [] PROGMEM = {
0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x24, 0x24, 0x24, 0x24, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff,
0x7e, 0x3c
};
// 'ThermoPtr', 3x5px
const unsigned char thermoPtr [] PROGMEM = {
0x80, 0xc0, 0xe0, 0xc0, 0x80
};
// 'Bluetooth icon', 6x11px
const unsigned char BTicon [] PROGMEM = {
0x20, 0x30, 0x28, 0xa4, 0x68, 0x30, 0x68, 0xa4, 0x28, 0x30, 0x20,
};
// 'BatteryIcon', 15x10px
const unsigned char BatteryIcon [] PROGMEM = {
0x30, 0x18, 0xff, 0xfe, 0x80, 0x02, 0xb6, 0xda, 0xb6, 0xda, 0xb6, 0xda, 0xb6, 0xda, 0xb6, 0xda,
0x80, 0x02, 0xff, 0xfe
};
// 'GlowPlugIcon', 16x10px
const unsigned char GlowPlugIcon [] PROGMEM = {
0x00, 0x00, 0xe3, 0x8e, 0x1c, 0x70, 0x28, 0x28, 0x24, 0x48, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
0x14, 0x50, 0x1c, 0x70
};
// 'Fan3_1a', 16x16px
const unsigned char FanIcon1 [] PROGMEM = {
0x03, 0xc0, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x03, 0xc0, 0x07, 0xe0, 0x06, 0x60,
0x7e, 0x7e, 0x87, 0xe1, 0x87, 0xe1, 0x84, 0x21, 0x84, 0x21, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00
};
// 'Fan3_2a', 16x16px
const unsigned char FanIcon2 [] PROGMEM = {
0x00, 0x78, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x7b, 0xf8, 0x87, 0xe0, 0x86, 0x60,
0x86, 0x60, 0x87, 0xe0, 0x7b, 0xf8, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x78
};
// 'Fan3_3a', 16x16px
const unsigned char FanIcon3 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x78, 0x1e, 0x84, 0x21, 0x84, 0x21, 0x87, 0xe1, 0x87, 0xe1, 0x7e, 0x7e,
0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x03, 0xc0
};
// 'Fan3_4a', 16x16px
const unsigned char FanIcon4 [] PROGMEM = {
0x1e, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x1f, 0xde, 0x07, 0xe1, 0x06, 0x61,
0x06, 0x61, 0x07, 0xe1, 0x1f, 0xde, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x1e, 0x00
};
// 'FuelIcon', 7x12px
const unsigned char FuelIcon [] PROGMEM = {
0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38
};
// 'Target', 13x13px
const unsigned char TargetIcon [] PROGMEM = {
0x0f, 0x80, 0x10, 0x40, 0x20, 0x20, 0x47, 0x10, 0x88, 0x88, 0x92, 0x48, 0x97, 0x48, 0x92, 0x48,
0x88, 0x88, 0x47, 0x10, 0x20, 0x20, 0x10, 0x40, 0x0f, 0x80
};
// '0', 3x5px
const unsigned char Mini0 [] PROGMEM = {
0xe0, 0xb0, 0xb0, 0xb0, 0xe0
};
// '1', 3x5px
const unsigned char Mini1 [] PROGMEM = {
0x40, 0xc0, 0x40, 0x40, 0x40
};
// '2', 3x5px
const unsigned char Mini2 [] PROGMEM = {
0xe0, 0x20, 0xe0, 0x80, 0xe0
};
// '3', 3x5px
const unsigned char Mini3 [] PROGMEM = {
0xe0, 0x20, 0x60, 0x20, 0xe0
};
// '4', 3x5px
const unsigned char Mini4 [] PROGMEM = {
0x80, 0xb0, 0xe0, 0x20, 0x20
};
// '5', 3x5px
const unsigned char Mini5 [] PROGMEM = {
0xe0, 0x80, 0xe0, 0x20, 0xe0
};
// '6', 3x5px
const unsigned char Mini6 [] PROGMEM = {
0xe0, 0x80, 0xe0, 0xb0, 0xe0
};
// '7', 3x5px
const unsigned char Mini7 [] PROGMEM = {
0xe0, 0x20, 0x20, 0x20, 0x20
};
// '8', 3x5px
const unsigned char Mini8 [] PROGMEM = {
0xe0, 0xb0, 0xe0, 0xb0, 0xe0
};
// '9', 3x5px
const unsigned char Mini9 [] PROGMEM = {
0xe0, 0xb0, 0xe0, 0x20, 0xe0
};
// 'DP', 3x5px
const unsigned char MiniDP [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x40
};
// 'Deg', 3x5px
const unsigned char MiniDeg [] PROGMEM = {
0xc0, 0xc0, 0x00, 0x00, 0x00
};
// 'C', 3x5px
const unsigned char MiniC [] PROGMEM = {
0xe0, 0x80, 0x80, 0x80, 0xe0
};
// 'H', 3x5px
const unsigned char MiniH [] PROGMEM = {
0xb0, 0xb0, 0xe0, 0xb0, 0xb0
};
// 'z', 3x5px
const unsigned char Miniz [] PROGMEM = {
0x00, 0x00, 0xe0, 0x40, 0xe0
};
// ' ', 3x5px
const unsigned char MiniSpc [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00
};
const char* Runstates [] PROGMEM = {
" Stopped/Ready ",
"Starting...",
"Igniting...",
" Ignition retry ",
"Ignited",
"Running",
"Stopping",
"Shutdown",
"Cooling"
};
const char* Errstates [] PROGMEM = {
"Low voltage", // E-01
"High voltage", // E-02
"Glow plug fault", // E-03
"Pump fault", // E-04
"Overheat", // E-05
"Motor fault", // E-06
"Comms fault", // E-07
"Flame out", // E-08
"Temp sense", // E-09
"Ignition fail", // E-10
"Unknown error?" // mystery code!
};

View file

@ -158,6 +158,7 @@ public:
unsigned char getTemperature_Max() const { return Controller.MaxTemperature; };
unsigned char getTemperature_Actual() const { return Controller.ActualTemperature; };
void setThermostatMode(unsigned on) { Controller.OperatingMode = on ? 0x32 : 0xCD; };
bool isThermostat() const { return Controller.OperatingMode == 0x32; };
// glow plug
short getGlowPlug_Current() const; // glow plug current
short getGlowPlug_Voltage() const; // glow plug voltage

View file

@ -30,8 +30,18 @@ public:
}
bool collectData(CProtocol& Frame, unsigned char val, int limit = 24) { // returns true when buffer filled
Frame.Data[m_Count++] = val;
return m_Count == limit;
return m_Count >= limit;
}
bool collectDataEx(CProtocol& Frame, unsigned char val, int limit = 24) { // returns true when buffer filled
// guarding against rogue rx kernel buffer stutters....
if((m_Count == 0) && (val != 0x76)) {
Serial.println("First heater byte not 0x76 - SKIPPING");
return false;
}
Frame.Data[m_Count++] = val;
return m_Count >= limit;
}
private:
eCS m_State;
int m_Count;

View file

@ -0,0 +1,319 @@
#include <SPI.h>
#include "AdaFruit_SH1106.h"
#include "protocol.h"
#include "display.h"
#include "pins.h"
#include "BluetoothAbstract.h"
#include "OLEDconsts.h"
#define X_FANICON 60 //46
#define Y_FANICON 39
#define X_FUELICON 90 // 80
#define Y_FUELICON 39
#define X_TARGETICON 30
#define Y_TARGETICON 39
#define Y_BASELINE 57
//
// **** NOTE: There are two very lame libaries conspiring to make life difficult ****
// A/ The ESP32 SPI.cpp library instatiates an instance of SPI, using the VSPI port (and pins)
// B/ The Adfruit_SH1106 library has hard coded "SPI" as the SPI port instance
//
// As an ESP32 has a pin multiplexer, this is very bad form.
// The design uses the defacto HSPI pins (and port),
// You **MUST comment out the SPIClass SPI(VSPI);** at the end of the ESP32 SPI library
// then we declare "SPI" here, which will use HSPI!!!!
// 128 x 64 OLED support
SPIClass SPI; // default constructor opens HSPI on pins
Adafruit_SH1106 display(LCDpin_DC, -1, LCDpin_CS);
int prevPump;
int prevRPM;
extern float fFilteredTemperature;
extern CBluetoothAbstract& getBluetoothClient();
void showThermometer(float desired, float actual);
void showBodyThermometer(int actual);
void showBTicon();
void showBatteryIcon(float voltage);
void showGlowPlug(int power);
void showFan(int RPM);
void showFuel(float rate);
void showRunState(int state, int errstate);
void printMiniNumericString(int xPos, int yPos, const char* str);
void initOLED()
{
SPI.setFrequency(8000000);
// SH1106_SWITCHCAPVCC = generate display voltage from 3.3V internally
display.begin(SH1106_SWITCHCAPVCC, 0, false);
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
}
void updateOLED(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
{
int runstate = HtrFrame.getRunState();
int errstate = HtrFrame.getErrState();
if(errstate) errstate--; // correct for +1 biased return value
display.clearDisplay();
float desiredT = 0;
if(runstate) {
if(CtlFrame.isThermostat())
desiredT = CtlFrame.getTemperature_Desired();
else
desiredT = -HtrFrame.getPump_Fixed() * 0.1f;
}
showThermometer(desiredT, // read values from most recently sent [BTC] frame
fFilteredTemperature);
if(getBluetoothClient().isConnected())
showBTicon();
float voltage = HtrFrame.getVoltage_Supply() * 0.1f;
showBatteryIcon(voltage);
if(runstate) {
float power = HtrFrame.getGlowPlug_Current() * 0.01 * HtrFrame.getGlowPlug_Voltage() * 0.1;
if(power > 1)
showGlowPlug(int(power));
showFan(HtrFrame.getFan_Actual());
showFuel(HtrFrame.getPump_Actual() * 0.1f);
showBodyThermometer(HtrFrame.getTemperature_HeatExchg());
}
else {
prevRPM = 0;
prevPump = 0;
}
showRunState(runstate, errstate);
}
void animateOLED()
{
static int fan = 0;
static int drip = 0;
if(prevPump || prevRPM) {
if(prevPump) {
// erase region of fuel icon
display.fillRect(X_FUELICON, Y_FUELICON, 7, 16, BLACK);
display.drawBitmap(X_FUELICON, Y_FUELICON+drip, FuelIcon, 7, 12, WHITE);
drip++;
drip &= 0x03;
}
if(prevRPM) {
// erase region of fuel icon
display.fillRect(X_FANICON, Y_FANICON, 16, 16, BLACK);
switch(fan) {
case 0: display.drawBitmap(X_FANICON, Y_FANICON, FanIcon1, 16, 16, WHITE); break;
case 1: display.drawBitmap(X_FANICON, Y_FANICON, FanIcon2, 16, 16, WHITE); break;
case 2: display.drawBitmap(X_FANICON, Y_FANICON, FanIcon3, 16, 16, WHITE); break;
case 3: display.drawBitmap(X_FANICON, Y_FANICON, FanIcon4, 16, 16, WHITE); break;
}
fan++;
fan &= 0x03;
}
}
display.display();
}
#define TEMP_YPOS(A) ((((20 - A) * 3) / 2) + 22)
#define BULB_X 1 // >= 1
#define BULB_Y 4
void showThermometer(float desired, float actual)
{
display.clearDisplay();
// draw bulb design
display.drawBitmap(BULB_X, BULB_Y, thermometerBitmap, 8, 50, WHITE);
// draw mercury
int yPos = BULB_Y + TEMP_YPOS(actual);
display.drawLine(BULB_X + 3, yPos, BULB_X + 3, BULB_Y + 42, WHITE);
display.drawLine(BULB_X + 4, yPos, BULB_X + 4, BULB_Y + 42, WHITE);
// print actual temperature
display.setTextColor(WHITE);
display.setCursor(0, Y_BASELINE);
display.print(actual, 1);
// draw set point
if(desired) {
char msg[16];
int desY = 19;
display.drawBitmap(X_TARGETICON, Y_TARGETICON, TargetIcon, 13, 13, WHITE); // set indicator against bulb
desY += 14;
if(desired > 0) {
int yPos = BULB_Y + TEMP_YPOS(desired) - 2;
display.drawBitmap(BULB_X-1, yPos, thermoPtr, 3, 5, WHITE); // set indicator against bulb
sprintf(msg, "%.0fC", desired);
}
else {
sprintf(msg, "%.1fHz", -desired);
}
int xPos = X_TARGETICON + 6 - ( strlen(msg) * 3); // 3 = 1/2 width font
display.setCursor(xPos, Y_BASELINE);
display.print(msg);
}
}
#define BODYBULB_X 119
#define BODY_YPOS(A) ((((100 - A) * 3) / 16) + 22) // 100degC centre - ticks +- 80C
void showBodyThermometer(int actual)
{
// draw bulb design
display.drawBitmap(BODYBULB_X, BULB_Y, thermometerBitmap, 8, 50, WHITE);
// draw mercury
int yPos = BULB_Y + BODY_YPOS(actual);
display.drawLine(BODYBULB_X + 3, yPos, BODYBULB_X + 3, BULB_Y + 42, WHITE);
display.drawLine(BODYBULB_X + 4, yPos, BODYBULB_X + 4, BULB_Y + 42, WHITE);
// print actual temperature
display.setTextColor(WHITE);
char label[16];
sprintf(label, "%d", actual);
// determine width and position right justified
int width = strlen(label) * 6;
display.setCursor(127-width, Y_BASELINE);
display.print(label);
}
void showBTicon()
{
display.drawBitmap(12, 0, BTicon, 6, 11, WHITE);
}
void showBatteryIcon(float voltage)
{
display.drawBitmap(95, 0, BatteryIcon, 15, 10, WHITE);
display.setCursor(85, 12);
display.setTextColor(WHITE);
display.print(voltage, 1);
display.print("V");
// nominal 10.5 -> 13.5V bargraph
int Capacity = int((voltage - 11.0) * 4.5);
if(Capacity < 0) Capacity = 0;
if(Capacity > 11) Capacity = 11;
display.fillRect(97 + Capacity, 2, 11-Capacity, 6, BLACK);
}
#define XPOS_GLOW 35
#define YPOS_GLOW 0
void showGlowPlug(int power)
{
display.drawBitmap(XPOS_GLOW, YPOS_GLOW, GlowPlugIcon, 16, 10, WHITE);
display.setCursor(XPOS_GLOW, YPOS_GLOW+12);
display.setTextColor(WHITE);
display.print(power);
display.print("W");
}
void showFan(int RPM)
{
// NOTE: fan rotation animation performed in animateOLED
prevRPM = RPM; // used by animation routine
display.setTextColor(WHITE);
char msg[16];
sprintf(msg, "%d", RPM);
int xPos = X_FANICON + 8 - ( strlen(msg) * 3); // 3 = 1/2 width font
display.setCursor(xPos, Y_BASELINE);
display.print(msg);
}
void showFuel(float rate)
{
// NOTE: fuel drop animation performed in animateOLED
prevPump = rate > 0; // used by animation routine
if(rate) {
char msg[16];
sprintf(msg, "%.1f", rate);
int xPos = X_FUELICON + 3 - ( strlen(msg) * 3); // 3 = 1/2 width font
display.setCursor(xPos, Y_BASELINE);
display.setTextColor(WHITE);
display.print(rate, 1);
}
}
void showRunState(int runstate, int errstate)
{
static bool toggle = false;
const char* toPrint = NULL;
int yPos = 25;
display.setTextColor(WHITE, BLACK);
if(runstate >= 0 && runstate <= 8) {
if(runstate == 0 && errstate) {
// create an "E-XX" message to display
char msg[16];
sprintf(msg, "E-%02d", errstate);
int xPos = 64 - ((strlen(msg)/2) * 6);
display.setCursor(xPos, yPos);
yPos += 8;
// flash error code
toggle = !toggle;
if(toggle)
display.print(msg);
else {
display.print(" ");
}
// bounds limit error and gather message
if(errstate > 10) errstate = 11;
toPrint = Errstates[errstate-1];
}
else {
toPrint = Runstates[runstate];
}
}
if(toPrint) {
int width = strlen(toPrint);
int xPos = 64 - ((width/2) * 6);
display.setCursor(xPos, yPos);
display.print(toPrint);
}
}
void printMiniNumericString(int xPos, int yPos, const char* str)
{
const char* pNext = str;
while(*pNext) {
const uint8_t* pBmp = NULL;
switch(*pNext) {
case '0': pBmp = Mini0; break;
case '1': pBmp = Mini1; break;
case '2': pBmp = Mini2; break;
case '3': pBmp = Mini3; break;
case '4': pBmp = Mini4; break;
case '5': pBmp = Mini5; break;
case '6': pBmp = Mini6; break;
case '7': pBmp = Mini7; break;
case '8': pBmp = Mini8; break;
case '9': pBmp = Mini9; break;
case '.': pBmp = MiniDP; break;
case '`': pBmp = MiniDeg; break;
case 'C': pBmp = MiniC; break;
case 'H': pBmp = MiniH; break;
case 'z': pBmp = Miniz; break;
case ' ': pBmp = MiniSpc; break;
}
if(pBmp) {
display.drawBitmap(xPos, yPos, pBmp, 3, 5, WHITE);
}
xPos += 4;
pNext++;
}
}

View file

@ -0,0 +1,12 @@
#ifndef __DISPLAY_H__
#define __DISPLAY_H__
#include <Arduino.h>
class CProtocol;
void initOLED();
void updateOLED(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void animateOLED();
#endif // __DISPLAY_H__

View file

@ -0,0 +1,102 @@
1249177ms [BTC] 76 16 00 11 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 13 74
+21ms [HTR] 8B 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 verifyCRC FAILED: calc:E388 data:6400
Bluetooth data not sent, CRC error
1250198ms [BTC] 76 16 00 11 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 13 74
+23ms [HTR] 8B 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 verifyCRC FAILED: calc:E388 data:6400
Bluetooth data not sent, CRC error
*** SWITCHED INTO VERBOSE MODE ****
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5
1251221ms [BTC] 76 16 00 11 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 13 74 :6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6
dT{16}:6,RD(8B)
dT{1}:6,RD(1D)
dT{1}:6,RD(76) <<<<<<<<<<<<<<<<<<<<<<<<<< THIS SHOULD BE FIRST RX BYTE!!!!
dT{1}:6,RD(16)
dT{1}:6,RD(0)
dT{2}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(84)
dT{1}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(84)
dT{2}:6,RD(0)
dT{1}:6,RD(2F)
dT{1}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(0)
dT{2}:6,RD(0)
dT{1}:6,RD(8)
dT{1}:6,RD(0)
dT{1}:6,RD(1A)
dT{1}:6,RD(64)
dT{1}:6,RD(0)
:7 +48ms [HTR] 8B 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 verifyCRC FAILED: calc:E388 data:6400
Bluetooth data not sent, CRC error
:8
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
8< (lots of state :0 snipped)
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5
:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5
:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5
:5:5:5:5:5:5:5:5:5:5
1252268ms [BTC] 76 16 00 11 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 13 74
:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6
dT{16}:6,RD(8B)
dT{1}:6,RD(1D)
dT{1}:6,RD(76) <<<<<<<<<<<<<<<<<<<<<<<<<< THIS SHOULD BE FIRST RX BYTE!!!!
dT{2}:6,RD(16)
dT{1}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(84)
dT{1}:6,RD(0)
dT{2}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(84)
dT{1}:6,RD(0)
dT{1}:6,RD(2F)
dT{1}:6,RD(0)
dT{2}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(0)
dT{1}:6,RD(8)
dT{1}:6,RD(0)
dT{1}:6,RD(1A)
dT{2}:6,RD(64)
dT{1}:6,RD(0):7
+49ms [HTR] 8B 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 verifyCRC FAILED: calc:E388 data:6400
Bluetooth data not sent, CRC error
:8
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0

View file

@ -0,0 +1,46 @@
1174404ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
1175426ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
1176448ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+23ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
1177471ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
1178493ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+21ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
1179515ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
1180537ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
1181559ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+23ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
1182583ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30 Timeout collecting BTC heater response data, returning to Idle State
1183588ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
1184611ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+21ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
1185632ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
1186654ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30 Timeout collecting BTC heater response data, returning to Idle State
1187676ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B verifyCRC FAILED: calc:58A8 data:8B
Bluetooth data not sent, CRC error
1188699ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 1D 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A verifyCRC FAILED: calc:B94 data:9A
Bluetooth data not sent, CRC error
1189721ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 4E 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A verifyCRC FAILED: calc:27B2 data:9A
Bluetooth data not sent, CRC error
1190743ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 4E 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B verifyCRC FAILED: calc:748E data:8B
Bluetooth data not sent, CRC error
1191765ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+22ms [HTR] 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B verifyCRC FAILED: calc:58A8 data:8B
Bluetooth data not sent, CRC error
1192788ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+21ms [HTR] 1D 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A verifyCRC FAILED: calc:B94 data:9A
Bluetooth data not sent, CRC error
1193810ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
+23ms [HTR] 4E 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B verifyCRC FAILED: calc:748E data:8B
Bluetooth data not sent, CRC error
1194833ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30 Timeout collecting BTC heater response data, returning to Idle State