Re: Liberty Schematic Rev 0.1 September 04, 2020 11:17PM | Admin Registered: 7 years ago Posts: 164 |
Liberty MM Schematic and Board Candidate September 10, 2020 08:03PM | Registered: 3 years ago Posts: 152 |
Re: Liberty MM Schematic and Board Candidate September 11, 2020 06:07PM | Admin Registered: 7 years ago Posts: 164 |
Re: Liberty MM Schematic and Board Candidate September 12, 2020 05:03AM | Registered: 3 years ago Posts: 152 |
Here it is, first version of the Liberty controller... September 19, 2020 09:05PM | Registered: 3 years ago Posts: 152 |
Re: Here it is, first version of the Liberty controller... September 19, 2020 09:13PM | Registered: 3 years ago Posts: 152 |
Re: Here it is, first version of the Liberty controller... September 22, 2020 02:36PM | Registered: 3 years ago Posts: 152 |
No Tach Signal? September 23, 2020 05:06AM | Admin Registered: 7 years ago Posts: 164 |
Re: No Tach Signal? September 23, 2020 03:32PM | Registered: 3 years ago Posts: 152 |
Re: Here it is, first version of the Liberty controller... September 25, 2020 10:27PM | Registered: 3 years ago Posts: 152 |
Some Thermistor musings... September 26, 2020 02:21AM | Registered: 3 years ago Posts: 152 |
Re: No Tach Signal? September 26, 2020 11:27PM | Admin Registered: 7 years ago Posts: 164 |
Re: No Tach Signal? September 27, 2020 09:15PM | Registered: 3 years ago Posts: 152 |
Use at own risk! September 29, 2020 07:30PM | Registered: 3 years ago Posts: 152 |
/* * ESP8266 Wemos D1 mini controller for Experimentation Failed states: 1 red blink - Failed to ignite 2 red blinks - Failed to reach operating temp in allocated time 3 red blinks - Under temperature 4 red blinks - Over temperature 5 red blinks - Low battery for AC (N/A) Status LEDs based on Thermistor voltage: Warmup mode - Yellow LED Startup - Solid Yellow Ignition Detected - 1 Blink Yellow Various Voltages - 2-4 blinks Run Mode - Green LED Run to 1.8v - Solid Green 2.0v to 1.8v - 1 Blink 1.8v to 1.1v - 2 Blink Cooldown Mode 5 blinks Yellow Fan Mode Alternate Green/Yellow Ver 1.0 - 9/26/2020 - First version Ver 1.1 - 9/29/2020 - Added temp/hum sensor, persistent ON/OFF state, and run time counter * */ // Set the specific variables below first!! //Define the client #define CLIENT "Liberty1" // Client specific configurations below #define VERSION "V1.1 Sep 29th 2020 " CLIENT #define URL "/" #define CLIENTID "esp8266" CLIENT //SSID and Password of your WiFi router const char* ssid = "<Your SSID>"; const char* password = "<Your Password>"; //mqtt information const char* mqttServer = "<your.mqtt.broker.com>"; const int mqttPort = 1883; const char* mqttUser = ""; const char* mqttPassword = ""; #include <EEPROM.h> #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <PubSubClient.h> #include <Wire.h> #include <ESP8266WebServer.h> #include<ADS1115_WE.h> #include <SparkFunBME280.h> BME280 mySensor; #define I2C_ADDRESS 0x48 ADS1115_WE adc(I2C_ADDRESS); #define ON 1 #define OFF 0 #define DISABLED 0 #define ENABLED 1 WiFiClient espClient; PubSubClient client(espClient); //Declare a global object variable from the ESP8266WebServer class. ESP8266WebServer server(80); //Server on port 80 // Define the Wemos pin mappings #define SOLENOID D8 // High turns on solenoid #define IGNITOR D0 // High turns on ignitor - not sure about cadence yet #define GREEN_LED D5 // Green LED - Low to turn on #define RED_LED D4 // Red LED - Low to turn on #define YEL_LED D6 // Yel LED #define ADLOW D7 // Out high to set A/D lower mode - Set to input otherwise #define FAN D3 // PWM pin for the fan // MQTT related definitions and variables #define MQTT_POLL 60000 // Amount of time between sending 1 min #define CONNECT_TM 2000 // Check for connection every 2 secs int mqtt_state; unsigned long int mqtt_timer, connect_timer, mqtt_poll_time = MQTT_POLL; //ADC Variables float adc0, adc1, adc2; int adc_state; //Membrane Switch definitions and variables // Voltage thresholds #define NULL_HIGH 5.0 #define NULL_LOW 3.24 #define OFF_HIGH 3.24 #define OFF_LOW 1.95 #define ON_HIGH 1.95 #define ON_LOW 0.2 // Debounce time in ms #define SW_DBNC_TM 300 byte switch_latch, on_sw_state, off_sw_state; unsigned long int on_switch_timer, off_switch_timer; //Thermistor definitions and variables // Voltage thresholds for Thermistor #define YEL_1BLNK 2.418 // 40C #define YEL_2BLNK 1.791 // 60C #define YEL_3BLNK 1.239 // 80C #define YEL_4BLNK 2.649 // 90C in low ADC range #define TH_GREEN 2.30 // Run mode #define GREEN_1BLNK 2.0 // Higher temps thresholds #define GREEN_2BLNK 1.8 // #define TH_UNDER 2.6 // Under temperature #define TH_OVER 1.1 // Over temperature #define IGN_DETECT 0.1 // Ignition detect difference // Define states of themistor #define HIGHSTATE 0 #define TRANSLOW 1 #define TRANSHI 2 #define LOWSTATE 3 char *thermistor_states[] = {"High", ">Low", ">High", "Low"}; byte thermistor_state, thermistor_block, thermistor_cnt, thermistor_dbnc; float thermistor, thermistor_pre, thermistor_temp; unsigned long int thermistor_timer; // Define LED states for servicing. Set via set_led(STATE, #blinks) #define LEDOFF 0 // All LEDs off #define LEDYELLOW 1 // Solid Yellow #define LEDRED 2 // Solid Red #define LEDGREEN 3 // Solid Green #define YELBLNK 4 // Yellow with Off blinks #define GREENBLNK 5 // Green with Off blinks #define REDBLNK 6 // Red with On blinks #define GREENYEL 7 // Alternate between // Blink times, states, and variables #define LED_BLNK_ON 300 // ms of ON blink time #define LED_BLNK_OFF 300 // ms of OFF blink time #define LED_BLNK_WT 3000 // Wait time between blinks #define LED_BLNK_ALT 1000 // ms between alternating green/yell // States #define BLNK_START 0 #define BLNK_ON 1 #define BLNK_OFF 2 #define BLNK_PAUSE 3 byte led_state, led_blink_state, led_mode, led_blinks, led_blink_cnt; unsigned long int led_timer; // Define LED indicator states. Stored in led_mode to keep track of current mode so as not to set more than once #define WARM1 1 // Warmup state 1, solid yellow #define WARM2 2 // Yellow 1 blinks #define WARM3 3 // Yellow 2 blinks #define WARM4 4 // Yellow 3 blinks #define WARM5 5 // Yellow 4 blinks #define RUN1 6 // Run mode, solid green #define RUN2 7 // Green 1 blink #define RUN3 8 // Green 2 blink // Ignitor slow ramp up definitions. PWM range is 0-1023 for esp8266 #define TIMEOUT 65000 // Total timeout before shutting off igniter. Starts when IGN turns on #define RAMPTHRESH 400 // PWM Threshold value for RAMP2 #define RAMP2HOLD 2000 // How many ms to hold on ramp2 wait stage #define RAMP1WAIT 200 // Ramp 1 increment time #define RAMP2WAIT 400 // Ramp 3 increment time #define INCREMENT 20 // How many PWM increments per time period #define PWMZERO 0 // PWM goes between 0 (OFF) and 255 (FULL ON) #define PWMFULL 1023 // Ignitor State machine States #define START 0 // Start here and wait for changes #define RAMP1 1 // First stage of ramp #define RAMPHOLD 2 // Hold stage of ramp #define RAMP2 3 // Final stage of ramp #define OFFHOLD 4 // Force igniter off, regardless of input int ignitor_state, pwm; unsigned long int ignitor_ramp_timer, ignitor_timeout; // Some timer values in ms #define PURGE_TM 25000 // Amount of time to purge #define TO_IGNITOR 000 // Before ignitor #define PRE_GAS 000 // Ignitor on before gas #define NO_IGNITE 240000 // Maximum time to wait for ignition 4 mins #define NORUN 1800000 // Max wait till run mode 30 mins // Fan PWM definitions, need to validate normal running speed #define FAN_NORMAL 1023 #define FAN_FAST 920 // Cooldown fan speed #define FAN_90 920 // 90% fan speed #define FAN_80 818 // 80% fan speed #define FAN_65 665 // 65% #define FAN_FULL 1023 // States for the main running routine. Not all used in all versions #define OFFSTATE 0 // Starting state, Switch is off #define PURGE 1 // Purge state to clear out any gas #define WAITSTART 2 // Wait a while before starting ignitor #define IGNITE 3 // Start the ignitor #define GASON 4 // Turn on gas #define CKIGNITE 5 // Check for ignite #define WARMUP 6 // Wait for running temperature #define RUN 7 // Running mode #define POWER_OFF 8 #define COOLDOWN 9 #define FAIL 10 #define DONOTHING 11 #define FANONLY 12 #define PRE_HIB 14 #define HIBERNATE 15 // Equivalent to OFF state with the switch ON. Power save mode set via remote interface #define RUN_OVER 16 // These run states are only used to indicate conditions, not real states #define RUN_UNDER 17 char *main_states[] = {"Off", "Purge", "Wait Ign", "Ignite", "Gas On", "Ck Ignite", "Warmup", "Run", "Power Off", "Cool Down", "Fail", "Do Nothing", "Fan Mode", "null", "Pre-Hib", "Hibernate"}; // Error codes, also corresponds to number of red blinks #define NO_ERROR 0 #define NO_IGN 1 #define NO_TEMP 2 #define UNDER_TEMP 3 #define OVER_TEMP 4 #define LOW_BAT 5 #define UNKNOWN_ERROR 6 char *error_codes[] = {"None", "No Ignition", "Didn't reach temperature", "Under Temperature", "Over Temperature", "Low Battery", "Unknown Error"}; int error_code; int main_state, next_state, previous_state, fan_speed, flag1, flag2, auto_print, terminal_flag; int days, hours, mins, tracking_state, tempflag; float temperature, humidity; unsigned long int main_timer, ignitor_timer, temperature_timer, tracking_timer, eeprom_save_timer, temp_timer; //---------------------------------- // End of definitions, start of code //---------------------------------- // One time setup code void setup(void){ EEPROM.begin(8); pinMode(RED_LED, INPUT); digitalWrite(RED_LED, LOW); // All LEDs off pinMode(GREEN_LED, INPUT); digitalWrite(GREEN_LED, LOW); pinMode(YEL_LED, INPUT); digitalWrite(YEL_LED, LOW); analogWrite(FAN, 0); pinMode(FAN, OUTPUT); // Fan off analogWrite(IGNITOR, 0); pinMode(IGNITOR, OUTPUT); // Ignitor off pinMode(SOLENOID, OUTPUT); digitalWrite(SOLENOID, LOW); // Gas Solenoid off pinMode(ADLOW, INPUT);digitalWrite(ADLOW, HIGH); // Disable low range of ADC Serial.begin(115200); WiFi.begin(ssid, password); //Connect to your WiFi router Serial.println(""); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } //If connection successful show IP address in serial monitor Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); //IP address assigned to your ESP // Set up the web server handler routines for each URL server.on("/", handleRoot); //Which routine to handle at root location. This is main display page server.on("/normal", normal); // Send normal command server.on("/fan", fan); // Send fan command server.on("/hibernate", hibernate); // Send hibernate command server.on("/mqtt", mqtt); // Toggle mqtt state server.on("/decmqtt", decmqtt); // Decrease mqtt time server.on("/resrun", resrun); // Reset run counter server.on("/optiona", optiona); // Send options server.on("/optionb", optionb); // Send options server.on("/optionc", optionc); // Send options server.on("/optiond", optiond); // Send options server.begin(); //Start server Serial.println("HTTP server started"); Wire.begin(); // Start i2c and initialize devices // Setup address of temp sensor mySensor.setI2CAddress(0x76); if (mySensor.beginI2C() == false) //Begin communication over I2C { Serial.println("BME280 temp sensor did not respond"); } // Setup and start the ADC via i2c if(!adc.init()){ Serial.println("ADS1115 not connected!"); } adc.setVoltageRange_mV(ADS1115_RANGE_6144); adc.setCompareChannels(ADS1115_COMP_0_GND); adc.startSingleMeasurement(); // Kick off first measurement; it is read in arrears and non-blocking mode as part of service_adc() routine // Setup MQTT client.setServer(mqttServer, mqttPort); mqtt_timer = connect_timer = millis(); // Take care of other initializations main_timer = on_switch_timer = off_switch_timer = thermistor_timer = temperature_timer = millis(); main_state = adc_state = thermistor_state = 0; if (EEPROM.read(1) != OFF) { on_sw_state = ON; // Force the unit to come on by spoofing the ON switch } days = EEPROM.read(2); // Recover the current gas runtime hours = EEPROM.read(3); mins = EEPROM.read(4); } //---------------------------- // Main code loop starts here //---------------------------- void loop(void){ // Service all the ancillary functions. Should all be non-blocking server.handleClient(); //Handle web client requests service_adc(); service_switches(); service_thermistor(); service_led(); service_mqtt(); service_temperature(); track_runtime(); service_terminal(); // Console may be removed for production // Now service the main state machine switch (main_state) { case OFFSTATE: // Comes here when off to wait for ON button or Wifi control if (off_sw_state == ON) off_sw_state = OFF; // Ignore off switch here if (on_sw_state == ON) { set_on(); // Save the state on_sw_state = OFF; analogWrite(FAN, FAN_FULL); // High Fan fan_speed = FAN_FULL; set_led(LEDYELLOW,0); pinMode(ADLOW, INPUT); // Reset the thermistor range thermistor_state = HIGHSTATE; main_timer = millis(); main_state = PURGE; Serial.println("Entering purge state.."); } break; case HIBERNATE: // This is essentially an OFF state, waits for ON button or Wifi control if (off_sw_state == ON) off_sw_state = OFF; // Ignore off switch here if (on_sw_state == ON) { // Don't reset switch state so it will continue to power on from OFFSTATE main_timer = millis(); main_state = OFFSTATE; Serial.println("Exiting Hibernate state.."); } break; case PURGE: // Runs fan at full speed to purge chamber of all gas if (on_sw_state == ON) on_sw_state = OFF; // Ignore on switch here if (off_sw_state == ON) { off_sw_state = OFF; main_state = POWER_OFF; } if (millis() - main_timer >= PURGE_TM ) { // After purge time, go wait, if necessary, before starting analogWrite(FAN, FAN_FULL); fan_speed = FAN_FULL; main_timer = millis(); main_state = WAITSTART; Serial.println("Entering wait start.."); } break; case WAITSTART: // Comes here to wait for TO_IGNITOR time and thermistor to be in HIGHSTATE (cool) if (on_sw_state == ON) on_sw_state = OFF; // Ignore on switch here if (off_sw_state == ON) { off_sw_state = OFF; main_state = POWER_OFF; } if (millis() - main_timer >= TO_IGNITOR && thermistor_state == HIGHSTATE) { // If all conditions met, proceed to ignition analogWrite(FAN, FAN_NORMAL); fan_speed = FAN_NORMAL; main_timer = ignitor_timer = millis(); ignitor_state = START; main_state = IGNITE; Serial.println("Ignitor turned on.."); } break; case IGNITE: // Start the ignition process if (on_sw_state == ON) on_sw_state = OFF; // Ignore on switch here if (off_sw_state == ON) { off_sw_state = OFF; main_state = POWER_OFF; } service_ignitor(); // Only serviced here and in GASON. Starts ramping up the ignitor PWM values if (millis() - main_timer >= PRE_GAS ) { // Wait to turn on gas (for Independence). For Liberty, PRE_GAS = 0, no wait. main_timer = ignitor_timer = millis(); digitalWrite(SOLENOID, HIGH); main_state = GASON; thermistor_pre = thermistor; // Save current value to check against for ignition Serial.println("Gas turned on.."); } break; case GASON: // Gas turned on, check for ignition or failure to ignite if (on_sw_state == ON) on_sw_state = OFF; // Ignore on switch here if (off_sw_state == ON) { off_sw_state = OFF; main_state = POWER_OFF; } service_ignitor(); // Ignitor should turn off automatically around this time... if (thermistor_pre - thermistor > IGN_DETECT ) { // If voltage is dropping, then we have ignition main_timer = millis(); digitalWrite(IGNITOR, LOW); // Ignitor should time out in service_ignitor(), but shut it off just in case ignitor_state = OFFHOLD; analogWrite(FAN, FAN_NORMAL); // Set fan to normal speed fan_speed = FAN_NORMAL; main_state = WARMUP; set_led(YELBLNK,1); Serial.print(thermistor); Serial.println(" Gas ignited, proceeding to warmup"); } if (millis() - main_timer >= NO_IGNITE) { // If we time out here, that means we didn't get ignition, so error out previous_state = GASON; main_state = FAIL; } break; case WARMUP: // This is the main warm up state, just check for operating temperatures, or timeout if (on_sw_state == ON) on_sw_state = OFF; // Ignore on switch here if (off_sw_state == ON) { off_sw_state = OFF; next_state = POWER_OFF; main_state = COOLDOWN; set_led(YELBLNK,5); Serial.println("Cooling down before power off.."); } if (thermistor_state == LOWSTATE) { // Should be in low ADC state to check for RUN mode. if (thermistor <= TH_GREEN && thermistor_block == OFF) { main_timer = millis(); main_state = RUN; set_led(LEDGREEN,0); Serial.print(thermistor); Serial.println(" Proceeding to run state"); } if ( thermistor <= YEL_4BLNK && thermistor > TH_GREEN && led_mode != WARM5 ) { led_mode = WARM5; set_led(YELBLNK,4); } } else { if ( thermistor <= YEL_1BLNK && thermistor > YEL_2BLNK && led_mode != WARM2 ) { led_mode = WARM2; set_led(YELBLNK,1); } if ( thermistor <= YEL_2BLNK && thermistor > YEL_3BLNK && led_mode != WARM3 ) { led_mode = WARM3; set_led(YELBLNK,2); } if ( thermistor <= YEL_3BLNK && thermistor > 1.1 && led_mode != WARM4 ) { led_mode = WARM4; set_led(YELBLNK,3); } } if (millis() - main_timer >= NORUN) { // Error out if we timed out and never made it to Run temperatures... previous_state = WARMUP; main_state = FAIL; } break; case RUN: // We are now in normal operating mode, just check for over and under temps if (on_sw_state == ON) on_sw_state = OFF; // Ignore on switch here if (off_sw_state == ON) { off_sw_state = OFF; next_state = POWER_OFF; main_state = COOLDOWN; set_led(YELBLNK, 5); Serial.println("Cooldown before power off.."); } if (thermistor < TH_OVER ) { previous_state = RUN_OVER; main_state = FAIL; } if (thermistor >= TH_UNDER) { previous_state = RUN_UNDER; main_state = FAIL; } // Monitor the temps and set the Green LED appropriately if ( thermistor <= TH_GREEN && thermistor > GREEN_1BLNK && led_mode != RUN1 ) { led_mode = RUN1; set_led(LEDGREEN,0); } if ( thermistor <= GREEN_1BLNK && thermistor > GREEN_2BLNK && led_mode != RUN2 ) { led_mode = RUN2; set_led(GREENBLNK,1); } if ( thermistor <= GREEN_2BLNK && thermistor > TH_OVER && led_mode != RUN3 ) { led_mode = RUN3; set_led(GREENBLNK,2); } break; case FAIL: // Comes here on error, turn off gas and set the error LEDs and error codes digitalWrite(SOLENOID, LOW); digitalWrite(IGNITOR, LOW); ignitor_state = OFFHOLD; if (thermistor_state == HIGHSTATE) { // Don't shut off fan until thermistor is in high state analogWrite(FAN, 0); fan_speed = 0; } else { analogWrite(FAN, FAN_NORMAL); fan_speed = FAN_NORMAL; } if (previous_state == GASON) { set_led(REDBLNK, 1); error_code = NO_IGN; } else if (previous_state == WARMUP) { set_led(REDBLNK, 2); error_code = NO_TEMP; } else if (previous_state == RUN_UNDER) { set_led(REDBLNK, 3); error_code = UNDER_TEMP; } else if (previous_state == RUN_OVER) { set_led(REDBLNK, 4); error_code = OVER_TEMP; } else if (previous_state == FANONLY) { // Can only be from low battery, only for Independence set_led(REDBLNK, 5); error_code = LOW_BAT; } else { set_led(REDBLNK, 10); error_code = UNKNOWN_ERROR; } Serial.print("Something failed, error code = "); Serial.println(error_codes[error_code]); main_state = DONOTHING; break; case DONOTHING: // Just sit here, blink LEDs and keep fan on till cooled down if (on_sw_state == ON) on_sw_state = OFF; // Ignore on switch here if (off_sw_state == ON) { next_state = POWER_OFF; main_state = COOLDOWN; set_led(YELBLNK, 5); error_code = NO_ERROR; Serial.println("Cooldown before power off.."); } if (thermistor_state == HIGHSTATE) { analogWrite(FAN, 0); fan_speed = 0; } else { analogWrite(FAN, FAN_NORMAL); fan_speed = FAN_NORMAL; } break; case COOLDOWN: // This is cooldown state before powering off or hibernating if (on_sw_state || off_sw_state) on_sw_state = off_sw_state = OFF; // Ignore both switches here analogWrite(FAN, FAN_FAST); fan_speed = FAN_FAST; digitalWrite(SOLENOID, LOW); if (thermistor_state == HIGHSTATE) { main_state = next_state; set_led(LEDOFF,0); // Either going to OFF or HIBERNATE } break; case FANONLY: // Comes here to keep fan on but no gas. Keeps mosquitoes in the net till they die if (on_sw_state == ON) { // Don't reset switch so it will power on normally from OFF state next_state = POWER_OFF; main_state = COOLDOWN; set_led(YELBLNK, 5); Serial.println("Cooldown before re-powering.."); } if (off_sw_state == ON) { off_sw_state = OFF; next_state = POWER_OFF; main_state = COOLDOWN; set_led(YELBLNK, 5); Serial.println("Cooldown before power off.."); } digitalWrite(SOLENOID, LOW); // Keep forcing gas off break; case POWER_OFF: // Set everything into OFF state before powering off digitalWrite(SOLENOID, LOW); digitalWrite(IGNITOR, LOW); ignitor_state = OFFHOLD; pinMode(ADLOW, INPUT); set_led(LEDOFF,0); error_code = led_mode = 0; analogWrite(FAN, 0); fan_speed = 0; main_state = OFFSTATE; set_off(); Serial.println("Powering off"); break; case PRE_HIB: // Prepare for hibernation. This state is for battery powered devices to prepare for real hibernation digitalWrite(SOLENOID, LOW); digitalWrite(IGNITOR, LOW); ignitor_state = OFFHOLD; pinMode(ADLOW, INPUT); set_led(LEDOFF,0); error_code = led_mode = 0; analogWrite(FAN, 0); fan_speed = 0; main_state = HIBERNATE; Serial.println("Going to Hibernate state"); break; default: break; } // End of main switch } // End of main loop // Service routines follow void service_terminal() { // Service console commands for debugging, etc int param; if (terminal_flag == OFF) { // Print one time help terminal_flag = ON; Serial.println(""); Serial.println("Terminal Help menu:"); Serial.println("0 = This help menu"); Serial.println("1 = Turn on autoprint"); Serial.println("2 = Turn off autoprint"); Serial.println("10-16 = Set error codes 0 to 6"); Serial.println("20 = Set ADC High range"); Serial.println("30 = Set ADC Low range"); Serial.println(""); } if (Serial.available() > 0) { param = Serial.parseInt(); if (Serial.read() == '\n') { // Set up for only one parameter if (param == 0) { terminal_flag = OFF; // Turn this off so Help menu will display again } if (param == 1) { auto_print = ON; Serial.println("Autoprint on"); } if (param == 2) { auto_print = OFF; Serial.println("Autoprint off"); } if (param == 3) { Serial.print("Days = "); Serial.print(days); Serial.print(" Hours = "); Serial.print(hours); Serial.print(" Mins = "); Serial.print(mins); Serial.print(" Secs = "); Serial.println((millis()-tracking_timer)/1000); } if (param >= 10 && param <=16) { error_code = param-10; Serial.println(error_codes[error_code]); } if (param == 20) { pinMode(ADLOW, INPUT); Serial.println("High ADC Range"); } if (param == 30) { pinMode(ADLOW, OUTPUT); Serial.println("Low ADC Range"); } } } if (auto_print && millis() - temp_timer >= 1000) { // This will print every sec when autoprint enabled Serial.print("Thermistor = "); Serial.print(thermistor,4); Serial.print(" Main St = "); Serial.print(main_state); Serial.print(" Ther St = "); Serial.print(thermistor_state); Serial.print(" Ignitor St = "); Serial.print(ignitor_state); Serial.print(" Ignitor = "); Serial.print(digitalRead(IGNITOR)); Serial.print(" Solenoid = "); Serial.print(digitalRead(SOLENOID)); Serial.print(" Fan Sp = "); Serial.print(fan_speed); Serial.print(" Temp = "); Serial.print(temperature,1); Serial.print(" Humidity = "); Serial.println(humidity,1); temp_timer = millis(); } } void track_runtime() { switch(tracking_state) { case 0: if (digitalRead(SOLENOID) == HIGH ) { // If solenoid is on, track run time tracking_state = 1; days = EEPROM.read(2); hours = EEPROM.read(3); mins = EEPROM.read(4); tracking_timer = eeprom_save_timer = millis(); } break; case 1: if (digitalRead(SOLENOID) == HIGH) { // As long as solenoid is on, track and advance timers if (millis() - tracking_timer >= 60000) { // Check for advance every minute tracking_timer = millis(); if (++mins == 60) { mins = 0; if (++hours == 24) { hours = 0; days++; } } } if (millis() - eeprom_save_timer >= 86400000 ) { // If on for more than 1 day, save it anyway EEPROM.write(2, days); EEPROM.write(3, hours); EEPROM.write(4, mins); EEPROM.commit(); eeprom_save_timer = millis(); } } else { EEPROM.write(2, days); EEPROM.write(3, hours); EEPROM.write(4, mins); EEPROM.commit(); tracking_state = 0; } break; } } void set_on() { // Set the EEPROM state to ON EEPROM.write(1, ON); EEPROM.commit(); } void set_off() { // Set the EEPROM state to OFF EEPROM.write(1, OFF); EEPROM.commit(); } void service_temperature() { // Read the temperature and humidity every second if (millis()-temperature_timer >= 1000) { temperature_timer = millis(); temperature = mySensor.readTempF(); humidity = mySensor.readFloatHumidity(); } } void service_ignitor() { // When serviced, starting with ignitor_state = START, will cycle through a ramp PWM cycle for the ignitor switch(ignitor_state) { case START: ignitor_state = RAMP1; pwm = PWMZERO; ignitor_ramp_timer = ignitor_timeout = millis(); break; case RAMP1: if (millis() - ignitor_ramp_timer >= RAMP1WAIT) { // Check for timed increment ignitor_ramp_timer = millis(); pwm = pwm + INCREMENT; if (pwm >= RAMPTHRESH) { ignitor_state = RAMPHOLD; } analogWrite(IGNITOR, pwm); } break; case RAMPHOLD: // Hold here for a bit if (millis() - ignitor_ramp_timer >= RAMP2HOLD) { ignitor_state = RAMP2; // If hold time expired, continue rest of ramp ignitor_ramp_timer = millis(); } break; case RAMP2: // Complete the ramp and hold till timeout if (millis() - ignitor_ramp_timer >= RAMP2WAIT) { ignitor_ramp_timer = millis(); if (pwm + INCREMENT >= PWMFULL) { pwm = PWMFULL; } else { pwm = pwm + INCREMENT; } analogWrite(IGNITOR, pwm); } if (millis() - ignitor_timeout >= TIMEOUT) { // If total ON timeout has expired, turn off and go to hold state ignitor_state = OFFHOLD; analogWrite(IGNITOR,PWMZERO); } break; case OFFHOLD: // Do nothing until state reset break; default: break; } } void set_led(int value, int blinks) { // Called to set the LEDs and blink states. Look up LED definitions for 'value' led_state = value; led_blinks = blinks; led_blink_state = BLNK_START; } void service_led() { // This service routine handles all the LEDs. Set up via set_led() call switch (led_state) { case LEDOFF: pinMode(RED_LED, INPUT); pinMode(GREEN_LED, INPUT); pinMode(YEL_LED, INPUT); break; case LEDYELLOW: pinMode(RED_LED, INPUT); pinMode(GREEN_LED, INPUT); pinMode(YEL_LED, OUTPUT); break; case LEDRED: pinMode(RED_LED, OUTPUT); pinMode(GREEN_LED, INPUT); pinMode(YEL_LED, INPUT); break; case LEDGREEN: pinMode(RED_LED, INPUT); pinMode(GREEN_LED, OUTPUT); pinMode(YEL_LED, INPUT); break; case REDBLNK: switch (led_blink_state) { case BLNK_START: pinMode(RED_LED, OUTPUT); pinMode(GREEN_LED, INPUT); pinMode(YEL_LED, INPUT); led_timer = millis(); led_blink_state = BLNK_ON; led_blink_cnt = 0; break; case BLNK_ON: if (millis() - led_timer >= LED_BLNK_ON) { pinMode(RED_LED, INPUT); led_timer = millis(); led_blink_state = BLNK_OFF; } break; case BLNK_OFF: if (millis() - led_timer >= LED_BLNK_OFF) { if (++led_blink_cnt >= led_blinks) { led_blink_state = BLNK_PAUSE; } else { led_blink_state = BLNK_ON; pinMode(RED_LED, OUTPUT); } led_timer = millis(); } break; case BLNK_PAUSE: if (millis() - led_timer >= LED_BLNK_WT) { led_blink_state = BLNK_START; } break; default: break; } break; case YELBLNK: // Blinks OFF number of times specified switch (led_blink_state) { case BLNK_START: pinMode(YEL_LED, INPUT); pinMode(RED_LED, INPUT); pinMode(GREEN_LED, INPUT); led_timer = millis(); led_blink_state = BLNK_OFF; led_blink_cnt = 0; break; case BLNK_OFF: if (millis() - led_timer >= LED_BLNK_ON) { pinMode(YEL_LED, OUTPUT); led_timer = millis(); led_blink_state = BLNK_ON; } break; case BLNK_ON: if (millis() - led_timer >= LED_BLNK_OFF) { if (++led_blink_cnt >= led_blinks) { led_blink_state = BLNK_PAUSE; } else { led_blink_state = BLNK_OFF; pinMode(YEL_LED, INPUT); } led_timer = millis(); } break; case BLNK_PAUSE: if (millis() - led_timer >= LED_BLNK_WT) { led_blink_state = BLNK_START; } break; } break; case GREENBLNK: // Blinks OFF number of times specified switch (led_blink_state) { case BLNK_START: pinMode(RED_LED, INPUT); pinMode(GREEN_LED, INPUT); pinMode(YEL_LED, INPUT); led_timer = millis(); led_blink_state = BLNK_OFF; led_blink_cnt = 0; break; case BLNK_OFF: if (millis() - led_timer >= LED_BLNK_ON) { pinMode(GREEN_LED, OUTPUT); led_timer = millis(); led_blink_state = BLNK_ON; } break; case BLNK_ON: if (millis() - led_timer >= LED_BLNK_OFF) { if (++led_blink_cnt >= led_blinks) { led_blink_state = BLNK_PAUSE; } else { led_blink_state = BLNK_OFF; pinMode(GREEN_LED, INPUT); } led_timer = millis(); } break; case BLNK_PAUSE: if (millis() - led_timer >= LED_BLNK_WT) { led_blink_state = BLNK_START; } break; default: break; } break; case GREENYEL: // Alternates between green and yellow switch (led_blink_state) { case BLNK_START: pinMode(GREEN_LED, OUTPUT); pinMode(YEL_LED, INPUT); led_timer = millis(); led_blink_state = BLNK_OFF; led_blink_cnt = 0; break; case BLNK_OFF: if (millis() - led_timer >= LED_BLNK_ALT) { pinMode(GREEN_LED, INPUT); pinMode(YEL_LED, OUTPUT); led_timer = millis(); led_blink_state = BLNK_ON; } break; case BLNK_ON: if (millis() - led_timer >= LED_BLNK_ALT) { pinMode(GREEN_LED, OUTPUT); pinMode(YEL_LED, INPUT); led_timer = millis(); led_blink_state = BLNK_OFF; } break; default: break; } break; default: break; } } void service_thermistor() { // Services the thermistor ranging. Blocks when transiting range to prevent suprious readings // Define the transition values #define THERMISTOR_HIGH 2.8 // More than this value, switch to high range #define THERMISTOR_LOW 1.1 // Less than this value, switch to low range switch (thermistor_state) { case LOWSTATE: if (thermistor >= THERMISTOR_HIGH ) thermistor_cnt++; else thermistor_cnt = 0; if (thermistor_cnt >= 100) { // Need at least 100 reads below threshold in order to change thermistor_state = TRANSHI; thermistor_timer = millis(); thermistor_cnt = 0; thermistor_block = ON; pinMode(ADLOW, INPUT); Serial.print(thermistor); Serial.println(" Switching to High state"); } break; case TRANSHI: if (millis() - thermistor_timer >= 100) { thermistor_block = OFF; thermistor_state = HIGHSTATE; } break; case TRANSLOW: if (millis() - thermistor_timer >= 100) { thermistor_block = OFF; thermistor_state = LOWSTATE; } break; case HIGHSTATE: if (thermistor <= THERMISTOR_LOW ) thermistor_cnt++; else thermistor_cnt = 0; if (thermistor_cnt >= 100) { thermistor_state = TRANSLOW; thermistor_cnt = 0; thermistor_timer = millis(); thermistor_block = ON; pinMode(ADLOW, OUTPUT); Serial.print(thermistor); Serial.println(" Switching to Low state"); } break; default: break; } } void service_switches() { // Sets on/off_sw_state to ON if ADC range detected for debounced time. Set to OFF once you've acknowledged it. if (adc2 >= NULL_LOW) { on_switch_timer = off_switch_timer = millis(); switch_latch = OFF; } else if (adc2 >= OFF_LOW && adc2 < OFF_HIGH) on_switch_timer = millis(); else if (adc2 < ON_HIGH) off_switch_timer = millis(); if (millis() - on_switch_timer >= SW_DBNC_TM && on_sw_state == OFF && switch_latch == OFF) { on_sw_state = switch_latch = ON; } if (millis() - off_switch_timer >= SW_DBNC_TM && off_sw_state == OFF && switch_latch == OFF) { off_sw_state = switch_latch = ON; } /*-* Debug for now if (millis() - on_switch_timer >= 5000 && switch_latch == ON) { Serial.println("ON switch pressed for 5 secs!"); on_switch_timer = millis(); } if (on_sw_state == ON) { Serial.println("ON switch detected!"); on_sw_state = OFF; } if (off_sw_state == ON) { Serial.println("OFF switch detected!"); off_sw_state = OFF; } *-*/ } void service_adc() { // Cycle through each ADC channel, one at a time, in non-blocking way... switch(adc_state) { case 0: // This is the thermistor if (!adc.isBusy()) { adc0 = thermistor = adc.getResult_V(); adc.setCompareChannels(ADS1115_COMP_1_GND); adc.setVoltageRange_mV(ADS1115_RANGE_0256); // Switch to more sensitive range for ignitor current resistor adc.startSingleMeasurement(); adc_state = 1; } break; case 1: // This is ignitor current resistor if (!adc.isBusy()) { adc1 = adc.getResult_V(); adc.setCompareChannels(ADS1115_COMP_2_GND); adc.setVoltageRange_mV(ADS1115_RANGE_6144); // Switch back to wide range for membrane switches and thermistor adc.startSingleMeasurement(); adc_state = 2; } break; case 2: // This is membrane switches if (!adc.isBusy()) { adc2 = adc.getResult_V(); adc.setCompareChannels(ADS1115_COMP_0_GND); adc.startSingleMeasurement(); adc_state = 0; } break; default: break; } } void service_mqtt() { // Sends MQTT messages periodically, if enabled int t; if (millis() - mqtt_timer >= mqtt_poll_time && client.connected() && mqtt_state == ENABLED) { mqtt_timer = millis(); client.publish("sensor/" CLIENT "/mstate", String(main_state).c_str()); client.publish("sensor/" CLIENT "/tstate", String(thermistor_state).c_str()); client.publish("sensor/" CLIENT "/therm", String(thermistor,3).c_str()); client.publish("sensor/" CLIENT "/fan", String(fan_speed).c_str()); client.publish("sensor/" CLIENT "/ignitor", String(digitalRead(IGNITOR)).c_str()); client.publish("sensor/" CLIENT "/solenoid", String(digitalRead(SOLENOID)).c_str()); client.publish("sensor/" CLIENT "/temperature", String(temperature).c_str()); client.publish("sensor/" CLIENT "/humidity", String(humidity).c_str()); client.publish("sensor/" CLIENT "/error", error_codes[error_code]); client.publish("sensor/" CLIENT "/flag1", String(flag1).c_str()); client.publish("sensor/" CLIENT "/flag2", String(flag2).c_str()); Serial.println("MQTT Published!"); } if (millis() - connect_timer >= CONNECT_TM && !client.connected() && mqtt_state == ENABLED) { // Check for mqtt broker periodically and reconnect as necessary connect_timer = millis(); Serial.println("Reconnecting to MQTT broker.."); if (client.connect(CLIENTID, mqttUser, mqttPassword )) { Serial.println("MQTT connected"); } else { Serial.print("MQTT Connect Failed with state "); Serial.println(client.state()); } } } //=============================================================== // The following routines handle the web interface //=============================================================== void handleRoot() { String webmessage; Serial.println("You called root page"); // This home page auto refreshes every 60 seconds webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"60; url = "; webmessage += URL; webmessage += "\"><body><center><br>Experimental Controller "; webmessage += VERSION; webmessage += "<br><br><a href=\"normal\">Normal Mode</a>"; webmessage += "<br><a href=\"fan\">Fan Mode</a>"; webmessage += "<br><a href=\"hibernate\">Hibernate Mode</a>"; webmessage += "<br>Options: <a href=\"optiona\"> A </a> <a href=\"optionb\"> B </a> <a href=\"optionc\"> C </a> <a href=\"optiond\"> D </a>"; webmessage += "<br><br><a href=\"mqtt\">Toggle MQTT State</a>: Now "; if (mqtt_state == ENABLED) { webmessage += String(mqtt_poll_time/1000); webmessage += " sec <a href=\"decmqtt\">Decrease</a>"; } else webmessage += "Disabled"; webmessage += "<br>Run Time (D:H:M) = "; webmessage += String(days); webmessage += ":"; webmessage += String(hours); webmessage += ":"; webmessage += String(mins); webmessage += " <a href=\"resrun\">Reset</a>"; webmessage += "<BR><BR>Flag 1 = "; webmessage += String(flag1); webmessage += "<BR>Flag 2 = "; webmessage += String(flag2); webmessage += "</body></html>"; webmessage += "<BR>Main St = "; webmessage += String(main_states[main_state]); webmessage += "<BR>Ignitor St = "; if (digitalRead(IGNITOR)) webmessage += "On"; else webmessage += "Off"; webmessage += "<BR>Solenoid St = "; if (digitalRead(SOLENOID)) webmessage += "On"; else webmessage += "Off"; webmessage += "<BR>Thermistor = "; if (thermistor_state == HIGHSTATE) webmessage += "Hi - "; else webmessage += "Lo - "; webmessage += String(thermistor,3); webmessage += "V<BR>Fan PWM Speed = "; webmessage += String(fan_speed); webmessage += " <BR>Ambient Temp = "; webmessage += String(temperature,0); webmessage += "F<BR>Humidity = "; webmessage += String(humidity,0); webmessage += "%<BR>Error Code = "; webmessage += error_codes[error_code]; server.send(200, "text/html", webmessage); } void normal() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Normal command sent</body></html>"; Serial.println("Normal page"); server.send(200, "text/html", webmessage); if (main_state == FANONLY || main_state == HIBERNATE || main_state == DONOTHING) { main_state = POWER_OFF; on_sw_state = ON; error_code = NO_ERROR; Serial.println("Coming out of fan or hibernate mode and restarting"); } } void fan() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Fan command sent</body></html>"; Serial.println("Fan page"); server.send(200, "text/html", webmessage); digitalWrite(SOLENOID, LOW); // Turn off gas digitalWrite(IGNITOR, LOW); // Also make sure ignitor is off ignitor_state = OFFHOLD; analogWrite(FAN, FAN_FULL); fan_speed = FAN_FULL; main_state = FANONLY; set_led(GREENYEL,0); Serial.println("Going into Fan only mode"); } void hibernate() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Hibernate command sent</body></html>"; Serial.println("Hibernate page"); server.send(200, "text/html", webmessage); digitalWrite(SOLENOID, LOW); next_state = PRE_HIB; main_state = COOLDOWN; set_led(YELBLNK, 5); Serial.println("Going to Cooldown mode and then Hibernate"); } void optiona() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Option A command sent</body></html>"; Serial.println("Option A page"); server.send(200, "text/html", webmessage); analogWrite(FAN, FAN_FULL); fan_speed = FAN_FULL; Serial.println("Fan set to 100%"); } void optionb() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Option B command sent</body></html>"; Serial.println("Option B page"); server.send(200, "text/html", webmessage); analogWrite(FAN, FAN_90); fan_speed = FAN_90; Serial.println("Fan set to 90%"); } void optionc() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Option C command sent</body></html>"; Serial.println("Option C page"); server.send(200, "text/html", webmessage); analogWrite(FAN, FAN_80); fan_speed = FAN_80; Serial.println("Fan set to 80%"); } void optiond() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Option D command sent</body></html>"; Serial.println("Option D page"); server.send(200, "text/html", webmessage); } void decmqtt() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Decremented MQTT time</body></html>"; server.send(200, "text/html", webmessage); if (mqtt_poll_time > 10000) mqtt_poll_time = mqtt_poll_time - 10000; else mqtt_poll_time = 5000; // Every 5 sec is min Serial.print("MQTT Poll time now "); Serial.print(mqtt_poll_time / 1000); Serial.println(" secs"); } void resrun() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Run counter reset</body></html>"; server.send(200, "text/html", webmessage); days = hours = mins = 0; EEPROM.write(2, days); EEPROM.write(3, hours); EEPROM.write(4, mins); EEPROM.commit(); tracking_state = 0; Serial.println("Run time counters reset!"); } void mqtt() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>MQTT State toggled to "; Serial.println("MQTT toggled page"); if (mqtt_state == ENABLED) { mqtt_state = DISABLED; webmessage += "DISABLED </body></html>"; } else { mqtt_state = ENABLED; mqtt_poll_time = MQTT_POLL; webmessage += String(MQTT_POLL/1000); webmessage += " sec and ENABLED </body></html>"; } server.send(200, "text/html", webmessage); }
Re: Use at own risk! September 29, 2020 07:38PM | Registered: 3 years ago Posts: 152 |
Temperature rise with gas off... September 30, 2020 07:20PM | Registered: 3 years ago Posts: 152 |
Re: Liberty MM Conversion Project November 01, 2020 02:10PM | Registered: 4 years ago Posts: 27 |
Re: Liberty MM Conversion Project November 01, 2020 08:49PM | Registered: 3 years ago Posts: 152 |
First real test of converted Liberty June 10, 2021 02:35PM | Registered: 3 years ago Posts: 152 |
Re: First real test of converted Liberty September 06, 2022 02:50PM | Registered: 4 years ago Posts: 23 |
Re: First real test of converted Liberty September 06, 2022 04:38PM | Registered: 3 years ago Posts: 152 |
Fix that Liberty September 10, 2022 02:36PM | Admin Registered: 7 years ago Posts: 164 |