/*
Default:
Sketch uses 8116 bytes (99%) of program storage space. Maximum is 8192 bytes.
Global variables use 363 bytes (70%) of dynamic memory, leaving 149 bytes for local variables. Maximum is 512 bytes.
LCD update led blink to toggle
Sketch uses 8110 bytes (98%) of program storage space. Maximum is 8192 bytes.
Global variables use 363 bytes (70%) of dynamic memory, leaving 149 bytes for local variables. Maximum is 512 bytes.
Setup blink to toggle
Sketch uses 8104 bytes (98%) of program storage space. Maximum is 8192 bytes.
Global variables use 363 bytes (70%) of dynamic memory, leaving 149 bytes for local variables. Maximum is 512 bytes.
setup/loop to main
Sketch uses 8080 bytes (98%) of program storage space. Maximum is 8192 bytes.
Global variables use 363 bytes (70%) of dynamic memory, leaving 149 bytes for local variables. Maximum is 512 bytes.
*/
#define PIN_USI_SDA PINB1 // pin: 5
#define PIN_USI_SCL PINB2 // pin: 7
#include <EEPROM.h>
#include <OneButton.h>
#include <TimerEvent.h>
#include <TinyWireM.h>
#include <DallasTemperature.h>
#include "LiquidCrystal_I2C.h"
//#include <LiquidCrystal_I2C.h>
#define LED_PIN 4
#define BUTTON_PIN 1
#define ONE_WIRE_BUS 3
TimerEvent timerTemperatureRefresh;
TimerEvent timerSearch1Wire;
OneButton btn = OneButton(
BUTTON_PIN, // Input pin for the button
true, // Button is active LOW
true // Enable internal pull-up resistor
);
//LiquidCrystal_I2C lcd(0x3f,16,2); // HARDWARE: set address & 16 chars / 2 lines
LiquidCrystal_I2C lcd(0x27, 16, 2); // WOKWI: set address & 16 chars / 2 lines
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Addresses of 4 DS18B20s
struct Configuration {
uint8_t addr_sensor_x[8];
uint8_t addr_sensor_z[8];
uint8_t addr_sensor_y1[8];
uint8_t addr_sensor_y2[8];
};
// Default config
Configuration appConfig = {
{ 0x28, 0xB8, 0x3D, 0x95, 0xF0, 0x01, 0x3C, 0xE4 },
{ 0x28, 0xB4, 0x76, 0x95, 0xF0, 0x01, 0x3C, 0x00 },
{ 0x28, 0x8C, 0xB6, 0x95, 0xF0, 0x01, 0x3C, 0x6E },
{ 0x28, 0x07, 0xD0, 0x95, 0xF0, 0x01, 0x3C, 0xF1 }
};
bool temperatureRefreshState = false;
bool searchState = false;
bool setupMode = false;
int setupStep = 0;
void (*resetFunc)(void) = 0; //declare reset function @ address 0
int main() {
init();
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT);
for (int i = 0; i < 10; i++) {
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
delay(80);
}
loadConfig(appConfig);
initLcd();
oneWire.reset();
sensors.begin();
timerTemperatureRefresh.set(1000, doTemperatureRefresh);
timerSearch1Wire.set(1000, doSearch1Wire);
timerSearch1Wire.disable();
btn.attachClick(handleClick);
btn.attachLongPressStart(handleLongClick);
for (;;) {
btn.tick();
if (setupMode == true) {
timerSearch1Wire.update();
} else {
// Monitoring
timerTemperatureRefresh.update();
}
}
}
void loadConfig(Configuration& config) {
EEPROM.get(0, config);
}
void saveConfig(Configuration& config) {
EEPROM.put(0, config);
}
void doTemperatureRefresh() {
updateLcdTemperature();
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
/*
digitalWrite(LED_PIN, LOW); // on
delay(100);
digitalWrite(LED_PIN, HIGH); // off
delay(100);
*/
}
void initLcd() {
lcd.init();
// Print a message to the LCD.
lcd.backlight();
printLcdBackground();
}
void printLcdBackground() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("X:"));
lcd.setCursor(0, 1);
lcd.print(F("Z:"));
lcd.setCursor(8, 0);
lcd.print(F("Y1:"));
lcd.setCursor(8, 1);
lcd.print(F("Y2:"));
}
void updateLcdTemperature() {
sensors.requestTemperatures(); // Send the command to get temperature readings
printTemperature(appConfig.addr_sensor_x, 2, 0);
printTemperature(appConfig.addr_sensor_z, 2, 1);
printTemperature(appConfig.addr_sensor_y1, 11, 0);
printTemperature(appConfig.addr_sensor_y2, 11, 1);
temperatureRefreshState = !temperatureRefreshState;
lcd.setCursor(7, 1);
if (temperatureRefreshState == true) {
lcd.print(".");
} else {
lcd.print(" ");
}
}
void printTemperature(DeviceAddress deviceAddress, int x, int y) {
char str_temp[5];
float tempC = sensors.getTempC(deviceAddress);
if (tempC != DEVICE_DISCONNECTED_C) {
dtostrf(tempC, 4, 1, str_temp);
} else {
strncpy(str_temp, "--.-", 5);
}
lcd.setCursor(x, y);
lcd.print(str_temp);
lcd.print((char)223);
}
static void handleClick() {
//Debug.println(F("-- handleClick --"));
if (setupMode == true) {
// Click in menu.. step forward
if (timerSearch1Wire.isEnabled() == false) {
setupStep += 1;
setupMenu();
}
}
}
static void handleLongClick() {
//Debug.println(F("-- handleLongClick --"));
if (setupMode == false) {
setupMode = true;
setupStep = 0;
setupMenu();
} else {
setupMode = false;
printLcdBackground();
}
}
static void doSearch1Wire() {
//Debug.println(F("-- doSearch1Wire --"));
searchState = !searchState;
lcd.setCursor(15, 0);
if (searchState == true) {
lcd.print("|");
} else {
lcd.print("-");
}
uint8_t addr[8];
lcd.setCursor(0, 1);
while (oneWire.search(addr)) {
if (OneWire::crc8(addr, 7) != addr[7]) {
// CRC is not valid!
return;
}
// SET ADDRESS HERE
timerSearch1Wire.disable();
}
}
static void setupMenu() {
//Debug.println(F("-- setupMenu --"));
//Debug.println(setupStep);
lcd.clear();
lcd.setCursor(0, 0);
switch (setupStep) {
case 0:
// setup screen
lcd.print("!unplug sensors!");
lcd.setCursor(0, 1);
lcd.print("[press to start]");
break;
case 1:
// X
lcd.print("connect X axis");
timerSearch1Wire.enable();
break;
case 2:
// Z
lcd.print("connect Z axis");
timerSearch1Wire.enable();
break;
case 3:
// Y1
lcd.print("connect Y1 axis");
timerSearch1Wire.enable();
break;
case 4:
// Y2
lcd.print("connect Y2 axis");
timerSearch1Wire.enable();
break;
case 5:
// Save
lcd.print("Store settings?");
lcd.setCursor(0, 1);
lcd.print("[press to save]");
break;
case 6:
// Saved
saveConfig(appConfig);
lcd.print("Saved!");
break;
default:
// exit
setupMode = false;
printLcdBackground();
break;
}
}