Last active
August 5, 2024 11:54
-
-
Save toxicantidote/76de0a92cd471c7a746325a81903f1f7 to your computer and use it in GitHub Desktop.
Compressor interfacing for new fridge controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <avr/wdt.h> | |
// how long to wait after a UART command before considering the link dead and | |
// resetting self (ms) | |
#define KEEPALIVE_WAIT 10000 | |
// pins where things are connected | |
#define PIN_INTERRUPT 2 | |
#define PIN_LED_R 11 | |
#define PIN_LED_G 10 | |
#define PIN_LED_B 9 | |
#define PIN_STATUS 13 | |
#define PIN_RELAY_1 A0 | |
#define PIN_RELAY_2 A1 | |
// let the compiler know to expect flash count changes anytime | |
volatile unsigned char flash_count = 0; | |
// initialise other state variables | |
unsigned char last_flash_count = 0; | |
unsigned long last_flash_time = 0; | |
unsigned long keep_alive = 0; | |
unsigned long last_command = 0; | |
char cmdByte; | |
void reboot() { | |
wdt_disable(); | |
wdt_enable(WDTO_15MS); | |
while (1) {} | |
} | |
void setup() { | |
// set the pins to input or output as needed | |
pinMode(PIN_INTERRUPT, INPUT_PULLUP); | |
pinMode(PIN_RELAY_1, OUTPUT); | |
pinMode(PIN_RELAY_2, OUTPUT); | |
pinMode(PIN_LED_R, OUTPUT); | |
pinMode(PIN_LED_G, OUTPUT); | |
pinMode(PIN_LED_B, OUTPUT); | |
pinMode(PIN_STATUS, OUTPUT); | |
digitalWrite(PIN_STATUS, LOW); | |
// cycle the RGB LED through red-green-blue | |
digitalWrite(PIN_LED_R, HIGH); | |
digitalWrite(PIN_LED_G, LOW); | |
digitalWrite(PIN_LED_B, LOW); | |
delay(200); | |
digitalWrite(PIN_LED_R, LOW); | |
digitalWrite(PIN_LED_G, HIGH); | |
digitalWrite(PIN_LED_B, LOW); | |
delay(200); | |
digitalWrite(PIN_LED_R, LOW); | |
digitalWrite(PIN_LED_G, LOW); | |
digitalWrite(PIN_LED_B, HIGH); | |
delay(200); | |
digitalWrite(PIN_LED_R, HIGH); | |
digitalWrite(PIN_RELAY_1, LOW); | |
digitalWrite(PIN_RELAY_2, LOW); | |
// attach the interrupt to watch for a falling edge on the interrupt pin | |
attachInterrupt(digitalPinToInterrupt(PIN_INTERRUPT), isr_flash, FALLING); | |
// start the UART | |
Serial1.begin(9600); | |
} | |
void loop() { | |
// turn off interrupts while getting the flash count so that the interrupt | |
// handler doesn't run while we are getting the value | |
noInterrupts(); | |
unsigned char fc = flash_count; | |
interrupts(); | |
// get the current time (since starting) | |
unsigned long now = millis(); | |
unsigned long age = now - last_flash_time; | |
unsigned long ka_age = now - keep_alive; | |
// send a keepalive roughly every second | |
if (ka_age > 1000) { | |
Serial1.print(F("PING")); | |
keep_alive = now; | |
} | |
// give a 250ms buffer after a flash sequence before considering 'finished'. | |
// (250ms on, 250ms off) | |
if ((age > 750) || (fc > 5)) { | |
noInterrupts(); | |
flash_count = 0; | |
fc = 0; | |
last_flash_count = 0; | |
interrupts(); | |
} | |
// if the flash count has increased since last loop, reset the timer | |
if (fc > last_flash_count) { | |
last_flash_time = now; | |
last_flash_count = fc; | |
} | |
// look for data on the serial line | |
for (int i = 0; i < Serial1.available(); i++) { // if serial data is available to read | |
digitalWrite(PIN_STATUS, HIGH); // turn on the inbuilt led | |
cmdByte = Serial1.read(); // read it | |
if (cmdByte == 0x0A || cmdByte == 0x53) { // if the character is an S or a newline | |
Serial1.flush(); // clear the input buffer | |
if (fc > 0) { // if there is an error.. | |
Serial1.print(F("STATUS ERROR ")); // start with an error message | |
Serial1.print(fc); // then number of flashes | |
Serial1.print(F(" ")); | |
// and then a description of the error | |
if (fc == 1) { | |
Serial1.println(F("Battery low")); | |
} else if (fc == 2) { | |
Serial1.println(F("Fan fault or excessive restarts")); | |
} else if (fc == 3) { | |
Serial1.println(F("Compressor blockage")); | |
} else if (fc == 4) { | |
Serial1.println(F("Compressor overload")); | |
} else if (fc == 5) { | |
Serial1.println(F("Over temperature")); | |
} else { | |
Serial1.println(F("Unknown error")); | |
} | |
} else { // if there is no error | |
Serial1.println(F("STATUS OKAY")); | |
} | |
} else if (cmdByte == 0x31) { // if 1 is received | |
// set the compressor to low speed and led to green | |
digitalWrite(PIN_RELAY_1, LOW); | |
digitalWrite(PIN_RELAY_2, LOW); | |
digitalWrite(PIN_LED_R, LOW); | |
digitalWrite(PIN_LED_G, HIGH); | |
digitalWrite(PIN_LED_B, LOW); | |
Serial1.println(F("COMPRESSOR LOW")); | |
} else if (cmdByte == 0x30) { // if 0 is received | |
// set the compressor to off and led to red | |
digitalWrite(PIN_RELAY_1, HIGH); | |
digitalWrite(PIN_RELAY_2, LOW); | |
digitalWrite(PIN_LED_R, HIGH); | |
digitalWrite(PIN_LED_G, LOW); | |
digitalWrite(PIN_LED_B, LOW); | |
Serial1.println(F("COMPRESSOR OFF")); | |
} else if (cmdByte == 0x32) {// if 2 is received | |
// set the compressor to high speed and the led to blue | |
digitalWrite(PIN_RELAY_1, LOW); | |
digitalWrite(PIN_RELAY_2, HIGH); | |
digitalWrite(PIN_LED_R, LOW); | |
digitalWrite(PIN_LED_G, LOW); | |
digitalWrite(PIN_LED_B, HIGH); | |
Serial1.println(F("COMPRESSOR HIGH")); | |
} else { // if the command is unknown | |
// show some help | |
Serial1.println(F("Unknown command. Commands:")); | |
Serial1.println(F("S or newline - Get fault status")); | |
Serial1.println(F("0 - Compressor off")); | |
Serial1.println(F("1 - Compressor low speed")); | |
Serial1.println(F("2 - Compressor high speed")); | |
} | |
// turn off the onboard led once the command has been processed | |
digitalWrite(PIN_STATUS, LOW); | |
// save the last command time | |
last_command = now; | |
} | |
// flush the serial buffer | |
Serial1.flush(); | |
// if there is no command within the maximum keepalive wait time, reset self | |
unsigned long command_age = last_command - now; | |
if (command_age > KEEPALIVE_WAIT) {reboot();} | |
} | |
// called by the falling edge interrupt on the fault pin | |
void isr_flash () { | |
// keep it short and sweet, just increment the flash counter | |
flash_count++; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment