/*********************************************************************
Bedside Clock
This device is battery-operated, self contained, and uses a graphic OLED display.
Since the display uses 50+ MA it is normally off.
A jolt turns it on via an accelerometer which is always powered, via its interrupt output.
The power is maintained by a PWM signal until turned off under program control.
It is controlled by a 16-position selector and a 3-way momentary switch.
Modes are selected by tilting the box and by selected positions.
The initial mode is to tell the time at night and is the default on power-up by tapping or a sideways movement.
For this, large numerals appear and the power goes off after a short time.
Two modes are entered from the initial display by rotating the box around its two horizontal exes.
These modes provide control of remote devices via 433 MHz transmissions.
They have a longer timeout which resets by any control action.
The last mode is entered by selection from specified mode positions.
It consists of information pages and settings.
All selections display the results of switch operation.
It is made with four sub-assemblies:
The controller has a Teensy 3.2 micro controller and a LIS3DH 3-axis accelerometer.
The display is a 32x256 pixel OLED using I2C.
The power assembly contains a 1.2AH Li-ion battery, its charger circuit, and the power relay.
Jphn Saunders 4/15/2020,
5/26/2020 Added NAXIM 31820 temperature sensor to replace the failed BME680
*********************************************************************
*/
// For communications:
#include <SPI.h>
#include <OneWire.h>
// For the MAX31820 temperature sensor
OneWire ds(18); // on pin 18
// For the Newhaven Display NHD-2.23-12832-UMBH:
#include <Adafruit_SSD1305.h>
// Important! comment out the x line of case 2 of getRotation() in Adafruit_SSD1305.cpp
#include "Fonts/FreeSerif18pt7b.h"
#include "Fonts/FreeSerif9pt7b.h"
// For the accelerometer: (Failed and replacemnet ot-of-stock
// A work-around uses a pressure sensitive switch with adhesive backing
// It is connected from 3.7V to the interrupt pin.
// #include <Adafruit_LIS3DH.h>
// For the PJRC Teensy 3.3 MCU built-in RTC:
#include "teensyTimeLib.h"
// System mode values:
#define MODE_INIT 0
#define MODE_SETTINGS 1
#define MODE_CMD 3
#define MODE_DISP 2
// Timeout values in loop rotations:
#define TM_SHORT 80
#define TM_LONG 200
// Transmit pulse lengths
#define PREPULSE_LEN 20
#define SETUP_LEN 10
// For accelerometer sensitivity:
#define TH_LOW 6
#define TH_HIGH 15
// For power maintenance:
#define hold_Port 21
#define minVolts 3.5 // Time to charge the battery
// globals:
byte mode;
int loopCount;
int attCode;
// For the front porch of the command transmission:
#define PULSE_PORT 23
/*********************************************************************
Transmitter function
The serial port 'Serial' is not the same as RX1 and TX1, which are 'Serial1'
RX1 cannot be made an output
Serial!.write produces a negative-going output in TX1.
There is no 'begin' option to invert this, so I had to add a hardware inverter.
After Serial1.begin() digitalWrite is ignored, so I had to add a hardware 'OR' gate.
**********************************************************************
*/
void transmit(char onCode, char offCode) {
char charBuffer[] = {"14L1776?nl"};
if ((digitalRead(2) == 1) && (digitalRead(3) == 0)) {
charBuffer[7] = onCode;
}
if ((digitalRead(2) == 0) && (digitalRead(3) == 1)) {
charBuffer[7] = offCode;
}
if (charBuffer[7] != '?') {
charBuffer[8] = 0x0d;
charBuffer[9] = 0x0a;
digitalWrite(PULSE_PORT, HIGH);
delay(PREPULSE_LEN);
digitalWrite(PULSE_PORT, LOW);
delay(SETUP_LEN);
Serial1.write(charBuffer, 10);
loopCount = 0;
}
}
void displaySelect(char upCode, char downCode) {
char charBuffer[] = {"14L1776O,?nl"};
if ((digitalRead(2) == 1) && (digitalRead(3) == 0)) {
charBuffer[9] = upCode;
}
if ((digitalRead(2) == 0) && (digitalRead(3) == 1)) {
charBuffer[9] = downCode;
}
if (charBuffer[9] != '?') {
charBuffer[10] = 0x0a;
charBuffer[11] = 0x0d;
digitalWrite(PULSE_PORT, HIGH);
delay(20);
digitalWrite(PULSE_PORT, LOW);
delay(10);
Serial1.write(charBuffer, 11);
loopCount = 0;
}
}
//For the display:
#define OLED_RESET 16
#define OLED_DC 15
#define OLED_CS 17
Adafruit_SSD1305 display(OLED_DC, OLED_RESET, OLED_CS); // Hardware SPI: MOSI=11,CLK 13
// For the display Multi-font chip:
#define MFC_PORT 10
// Accelerometer object:
// #define LIS3DH_CS 14
// Adafruit_LIS3DH lis = Adafruit_LIS3DH(LIS3DH_CS); // This implies using hardware SPI on pins 11-13
// RTC object:
utime_t pstTt;
tmElements_t pstTm;
//For battery voltage reference LM135
#define LM135V 1.2
/*********************************************************************
Accelerometerfunctions
**********************************************************************
*/
#define numAttSamples 10
#define offFlat 3000
#define flick 3000
int attY[numAttSamples];
int attZ[numAttSamples];
/*
void gesture(void) {
int lastIndex = numAttSamples - 1;
for (int i = 0; i < lastIndex; i++) {
attY[i] = attY[(i + 1)];
attZ[i] = attZ[(i + 1)];
}
lis.read(); // get X Y and Z data at once
attY[numAttSamples - 1] = lis.y;
attZ[numAttSamples - 1] = lis.z;
if ((abs(attY[lastIndex]) > offFlat) || (abs(attZ[lastIndex]) > offFlat)) {
// loopCount = 0;
}
/*
if (millis() > 1500) {
if ((abs(attZ[lastIndex] - attZ[0]) > flick) && (loopCount > 10)) {
mode = MODE_CMD;
}
if ((abs(attY[lastIndex] - attY[0]) > flick) && (loopCount > 10)) {
mode = MODE_DISP;
}
}
if((abs(attZ[8]) > 2000) && (abs(attY[8]) < 1000)) {
mode = MODE_CMD;
// loopCount = 0;
}
if((abs(attY[8]) > 2000) && (abs(attZ[8]) < 1000)) {
mode = MODE_DISP;
// loopCount = 0;
}
}
*/
// RTC time & date structures:
typedef struct {
byte loc; // character in clock display to srart blinking
byte len; // The number of characters to blink
int8_t val; // Value in timeDate
byte ul; // Maximum item value
byte ll; // Minimum item value
} adj_t;
adj_t clockList[] = {
// sec min hour month day year weekday
{6, 2, 0, 59, 0}, {3, 2, 2, 59, 0}, { 0, 2, 1, 23, 0}, {13, 3, 3, 12, 1}, {17, 2, 4, 31, 1}, {20, 4, 5, 99, 0}, {6, 3, 6, 7, 1}
};
/*********************************************************************
Timekeeping functions
**********************************************************************
*/
void timeDateGet(void) {
breakTime(pstTt, &pstTm);
clockList[0].val = pstTm.Second; // Not adjustable 0 - 59
clockList[1].val = pstTm.Minute; // 0 - 59
clockList[2].val = pstTm.Hour; // 0 - 23
clockList[3].val = pstTm.Month; // 1 (Jan) -12
clockList[4].val = pstTm.Day; // 1 up
clockList[5].val = pstTm.Year; // - 2000
clockList[6].val = pstTm.Wday; // Not adjustable 1 (Sun) - 7
}
void adjustTimeDate(int adjustIndex) {
bool changed = false;
if (digitalRead(3) == 0) { //Increase value
clockList[adjustIndex].val++;
if (clockList[adjustIndex].val > clockList[adjustIndex].ul) {
clockList[adjustIndex].val = clockList[adjustIndex].ll;
}
changed = true;
}
if (digitalRead(2) == 0) { //Decrease value
if (clockList[adjustIndex].val > clockList[adjustIndex].ll) {
clockList[adjustIndex].val--;
}
else {
clockList[adjustIndex].val = clockList[adjustIndex].ul;
}
changed = true;
}
if (changed == true) {
pstTm.Second = clockList[0].val;
pstTm.Minute = clockList[1].val;
pstTm.Hour = clockList[2].val;
pstTm.Month = clockList[3].val;
pstTm.Day = clockList[4].val;
pstTm.Year = clockList[5].val;
setRTCtm(&pstTm);
do {
delay(10);
} while ((digitalRead(2) == 0) || (digitalRead(3) == 0));
}
}
/*********************************************************************
Display functions
**********************************************************************
*/
const char weekdays[] = {"SATSUNMONTUEWEDTHUFRISAT"};
void displayWeekday(void) {
char c;
byte indx;
for (byte i = 0; i < 3; i++) {
indx = (3 * (clockList[6].val) + i);
c = weekdays[indx];
display.print(c);
}
}
const char months[] = {"DECJANFEBMARAPRMAYJUNJLYAUGSEPOCTNOVDEC"};
void displayMonth(void) {
char c;
byte indx;
for (byte i = 0; i < 3; i++) {
indx = (3 * (clockList[3].val)) + i;
c = months[indx];
display.print(c);
}
}
/*
*********************************************************************
Temperature
**********************************************************************
*/
byte dsAddr[8];
byte getTemperature(void) {
byte present = 0, fah;
byte data[12];
float celsius;
ds.reset();
ds.select(dsAddr);
ds.write(0x44); // start conversion, with parasite power on at the end
delay(100);
ds.reset();
ds.select(dsAddr);
ds.write(0xBE); // Read Scratchpad
delay(100);
for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
int16_t raw = (data[1] << 8) | data[0];
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms ----
celsius = (float)raw / 16.0;
celsius = celsius * 1.8 + 32.0;
fah = int(celsius);
return fah;
}
void checkSwitch(byte upSw, byte downSw) {
if (digitalRead(3) == 0) { //Up toggle
if (upSw > 3) {
loopCount = TM_LONG; // Shuts off power
}
else {
mode = upSw;
loopCount = 0;
}
while (digitalRead(3) == 0);
delay(100);
}
if (digitalRead(2) == 0) { //Down toggle
if (downSw > 3) {
loopCount = TM_LONG; // Shuts off power
}
else {
mode = downSw;
loopCount = 0;
}
while (digitalRead(2) == 0);
delay(100);
}
}
/*********************************************************************
Program
**********************************************************************
*/
int timeout;
void setup() {
pinMode(hold_Port, OUTPUT);
digitalWrite(hold_Port, HIGH); // Keeps power relay closed using 10% power.
// pinMode(LIS3DH_CS, OUTPUT); //LIS3DH CS
pinMode( MFC_PORT, OUTPUT); //MFC CS
// digitalWrite(LIS3DH_CS, HIGH);
digitalWrite( MFC_PORT, HIGH);
Serial1.begin(2400);
pinMode(PULSE_PORT, OUTPUT); //For the 433 MHz pre-pulse
digitalWrite(PULSE_PORT, LOW);
loopCount = 0;
for (int i = 2; i < 8; i++) { // Switches and dial
pinMode(i, INPUT_PULLUP);
}
/*
lis.begin(0x18);
lis.setRange(LIS3DH_RANGE_2_G);
lis.setDataRate(LIS3DH_DATARATE_25_HZ); // Default value is 0 (50 Hz), see table 3 in Application Note
lis.setClick(0, TH_HIGH); //0=off,1=i-click,2=2-click
*/
display.begin();
display.setRotation(2); // Width & Height reverse direction
display.command(0xC8); //Upside-down
// display.command(0xA1);
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
initRTC(); // set the Time library to use Teensy 3.2's RTC to keep time
if ( !ds.search(dsAddr)) {
ds.reset_search();
delay(250);
return;
}
timeout = TM_SHORT;
mode = MODE_INIT;
}
byte oldDialCode;
byte dialCode;
void loop() {
loopCount++;
pstTt = readRTC();
timeDateGet();
int hr12 = clockList[2].val;
if ( hr12 > 12) {
hr12 = hr12 - 12;
}
int rawCount;
float refVolts, battVolts;
rawCount = analogRead(20);
refVolts = LM135V * 1024 / rawCount;
rawCount = analogRead(22);
battVolts = refVolts * rawCount / 512;
// gesture();
/*********************************************************************
Dial Code
Position: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Code: 15 13 9 11 3 1 0 2 10 8 12 14 6 4 5 7
**********************************************************************
*/
dialCode = digitalRead(4) + (digitalRead(5) << 1) + (digitalRead(6) << 2) + (digitalRead(7) << 3);
if (dialCode != oldDialCode) {
loopCount = 0;
oldDialCode = dialCode;
}
if (loopCount > timeout) {
if (dialCode == 2) {
display.clearDisplay();
display.setTextColor(WHITE);
display.setFont();
display.setCursor(25, 0);
display.print("Made in 2020 by");
display.setCursor(45, 25);
display.print("");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 25);
display.print("John Saunders");
display.display();
delay(5000);
}
digitalWrite(hold_Port, LOW); //Shuts off power
while (true);
}
display.clearDisplay();
if (mode == MODE_SETTINGS) {
display.setTextColor(WHITE);
display.setFont();
switch (dialCode) {
default:
case 15: //0
display.setCursor(90, 0);
display.print("Time");
display.setCursor(90, 25);
display.print("Exit");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 12);
displayWeekday();
display.setCursor(43, 22);
displayMonth();
display.print(' ');
display.print(clockList[4].val);
display.setCursor(0, 30);
display.print("20");
display.print(clockList[5].val);
checkSwitch(MODE_INIT, 4);
break;
case 13: //1
display.setCursor(100, 0);
display.print("Up");
display.setCursor(100, 25);
display.print("Down");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Minutes: ");
display.print(clockList[1].val);
adjustTimeDate(1);
break;
case 9: //2
display.setCursor(100, 0);
display.print("Up");
display.setCursor(100, 25);
display.print("Down");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Hours: ");
display.print(clockList[2].val);
adjustTimeDate(2);
break;
case 11: //3
display.setCursor(100, 0);
display.print("Up");
display.setCursor(100, 25);
display.print("Down");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Month: ");
display.print(clockList[3].val);
adjustTimeDate(3);
break;
case 3: //4
display.setCursor(100, 0);
display.print("Up");
display.setCursor(100, 25);
display.print("Down");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Date: ");
display.print(clockList[4].val);
adjustTimeDate(4);
break;
case 1: //5
display.setCursor(100, 0);
display.print("Up");
display.setCursor(100, 25);
display.print("Down");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Year: 20");
display.print(clockList[5].val);
adjustTimeDate(5);
break;
case 0:
display.setCursor(90, 0);
display.print("Siren");
display.setCursor(90, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Cube Alarm");
transmit('h', 'H');
break;
case 2:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Yellow lead");
transmit('j', 'm');
break;
case 10:
display.setCursor(90, 0);
display.print("BaBa");
display.setCursor(90, 25);
display.print("Chime");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Play Tune");
transmit('B', 'Q');
break;
case 8:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Clear: Blue Lead");
transmit('n', 'N');
break;
case 7: //15
display.setCursor(80, 0);
display.print("Display");
display.setCursor(84, 25);
display.print("Command");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 12);
display.print(battVolts);
display.print('V');
display.fillCircle(22, 21, 2, WHITE);
display.setCursor(25, 30);
display.print('F');
int degF = getTemperature();
display.setCursor(0, 30);
display.print(degF);
checkSwitch(MODE_DISP, MODE_CMD);
break;
}
}
if (mode == MODE_INIT) {
if ( battVolts >= minVolts) {
if (dialCode < 15) {
display.setTextColor(WHITE);
display.setFont();
display.setCursor(84, 0);
display.print("Display");
display.setCursor(84, 25);
display.print("Command");
}
display.setFont(&FreeSerif18pt7b);
display.setCursor(25, 29);
}
else {
display.setFont(&FreeSerif9pt7b);
display.setCursor(30, 9);
display.print("Battery Low!");
display.setCursor(25, 29);
}
display.print(hr12);
if ((clockList[0].val & 0x01) == 0 ) {
display.setTextColor(BLACK);
}
display.print(':');
display.setTextColor(WHITE);
display.print(clockList[1].val);
checkSwitch(MODE_DISP, MODE_CMD);
}
if (mode == MODE_DISP) {
timeout = TM_LONG;
display.setTextColor(WHITE);
display.setFont();
switch (dialCode) {
case 15: //0
display.setCursor(90, 0);
display.print("Time");
display.setCursor(90, 25);
display.print("Exit");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 12);
displayWeekday();
display.setCursor(43, 22);
displayMonth();
display.print(' ');
display.print(clockList[4].val);
display.setCursor(0, 30);
display.print("20");
display.print(clockList[5].val);
checkSwitch(MODE_INIT, 4);
break;
case 13: //1
display.setCursor(50, 0);
display.print("Temperature");
display.setCursor(60, 25);
display.print("Humidity");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("rgb LED Display");
displaySelect('C', 'D');
break;
case 9: //2
display.setCursor(20, 0);
display.print("Baro/Solar Current");
display.setCursor(60, 25);
display.print("Night Time");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("rgb LED Display");
displaySelect('E', 'F');
break;
case 11: //3
display.setCursor(80, 0);
display.print("Garage");
display.setCursor(5, 25);
display.print("Battery/Solar Volts");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("rgb LED Display");
displaySelect('A', 'B');
break;
case 3: //4
display.setCursor(80, 0);
display.print("Time");
display.setCursor(80, 25);
display.print("Date");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("RED LED Disp");
displaySelect('L', 'K');
break;
case 1: //5
display.setCursor(30, 0);
display.print("Temperature");
display.setCursor(30, 25);
display.print("Humidity");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("RED LED Disp");
displaySelect('M', 'N');
break;
case 0: //6
display.setCursor(30, 0);
display.print("Solar Current");
display.setCursor(30, 25);
display.print("Battery Volts");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("RED LED Disp");
displaySelect('O', 'P');
break;
case 2: //7
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Eggs");
transmit('d', '9');
break;
case 10: //8
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Circle Light");
transmit(0x50, 0x6C);
break;
case 8: //9
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Bullseye");
transmit('M', 'g');
break;
case 12: //10
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Flashing Light");
transmit('Y', 'W');
break;
case 14: //11
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Vegas Light");
transmit('L', 'V');
break;
case 6: //12
display.setCursor(40, 0);
display.print("Solar Current");
display.setCursor(60, 25);
display.print("Pressure");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Atmosphere");
displaySelect('e', 'f');
break;
case 4: //13
display.setCursor(12, 0);
display.print("Outsode Humidity");
display.setCursor(20, 25);
display.print("Room Humidity");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Atmosphere");
displaySelect('d', 'b');
break;
case 5: //14
display.setCursor(10, 0);
display.print("Outside Temperature");
display.setCursor(30, 25);
display.print("Room Temperature");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Atmosphere");
displaySelect('c', 'a');
break;
case 7: //15
display.setCursor(80, 0);
display.print("Settings");
display.setCursor(84, 25);
display.print("Command");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 12);
display.print(battVolts);
display.print('V');
display.fillCircle(22, 21, 2, WHITE);
display.setCursor(25, 30);
display.print('F');
int degF = getTemperature();
display.setCursor(0, 30);
display.print(degF);
checkSwitch(MODE_SETTINGS, MODE_CMD);
break;
}
}
if (mode == MODE_CMD) {
timeout = TM_LONG;
display.setTextColor(WHITE);
display.setFont();
switch (dialCode) {
case 15: //0
display.setCursor(90, 0);
display.print("Time");
display.setCursor(90, 25);
display.print("Exit");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 12);
displayWeekday();
display.setCursor(43, 22);
displayMonth();
display.print(' ');
display.print(clockList[4].val);
display.setCursor(0, 30);
display.print("20");
display.print(clockList[5].val);
checkSwitch(MODE_INIT, 4);
break;
case 13:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Ceiling Light");
transmit('R', 'G');
break;
case 9:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Bluetuth Speaker");
transmit('S', 'U');
break;
case 11:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Reading Light");
transmit('b', 'f');
break;
case 3:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Pinapple Light");
transmit('K', '8');
break;
case 1:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Shelf Light");
transmit('E', 'F');
break;
case 0:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Hanging lamp");
transmit(0x49, 'C'); //uc eye
break;
case 2:
case 10:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Clear: Outlet");
transmit('m', 'J');
break;
case 8:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Flower");
transmit('a', 'c');
break;
case 12:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("X10 - Pole Light");
transmit('i', 'k');
break;
case 14:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Girl Fountain");
transmit('j', 'T');
break;
case 6:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Green Outlet");
transmit('5', '4');
break;
case 4:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Owl Fountain");
transmit('1', '0'); // one
break;
case 5:
display.setCursor(100, 0);
display.print("On");
display.setCursor(100, 25);
display.print("Off");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 20);
display.print("Gazebo Lights");
transmit('7', '6');
break;
case 7: //15
display.setCursor(80, 0);
display.print("Settings");
display.setCursor(84, 25);
display.print("Display");
display.setFont(&FreeSerif9pt7b);
display.setCursor(0, 12);
display.print(battVolts);
display.print('V');
display.fillCircle(22, 21, 2, WHITE);
display.setCursor(25, 30);
display.print('F');
int degF = getTemperature();
display.setCursor(0, 30);
display.print(degF);
checkSwitch(MODE_SETTINGS, MODE_DISP);
break;
}
}
display.display();
delay(100);