Re: TEC1-12710 TEG (?) Devices August 21, 2020 07:22PM | Registered: 3 years ago Posts: 152 |
Re: TEC1-12710 TEG (?) Devices September 05, 2020 08:36PM | Registered: 3 years ago Posts: 152 |
Mark II October 30, 2020 07:20PM | Registered: 3 years ago Posts: 152 |
Re: Mark II October 30, 2020 07:55PM | Registered: 3 years ago Posts: 152 |
/* * ESP8266 Wemos D1 mini experimental controller * Remember to set to 160 MHz CPU speed * Don't enable mqtt unless there is a server to connect to. The connect routine blocks for a while. * * ** This is experimental and untested code. It is posted for reference only. Any use is at your own risk! ** 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 6 red blinks - Unknown error Status LEDs based on Thermistor voltage: Startup to ADLOW switch - solid Yellow/Orange 3.3v to 2.5 v - 1 blink Orange 2.5v to 2.0v - 2 blink 2.0v to 1.5v - 3 blink 1.35v to 1.5v - 4 blink Run Mode - Green LED 1.35v to 1.2v - No blink Green 1.2v to 1.0v - 1 blink 0.8v to 1.0v - 2 blink 0.6v to 0.8v - 3 blink 0.4v to 0.6v - 4 blink 0.2v to 0.4v - 5 blink 1.35v to 1.7v - 10 blink Cooldown Mode 5 blinks Yellow/Orange Fan Mode Alternate Green and Yellow/Orange 10/30/2020 - V1.0 - First version, includes OTA updater. For use on PCB V1.3 * */ // Set the specific variables below first!! //Define the client #define CLIENT "MM1 Wemos" // Client specific configurations below #define VERSION "V1.0 Oct 30th 2020 " CLIENT #define URL "/" #define CLIENTID "esp8266" CLIENT #define OTAMENU // Comment this out if you don't want firmware upgrade on menu. #define LOW_BATTERY 4.4 //SSID and Password of your WiFi router const char* ssid = "<your SSID>"; const char* password = "<Your WiFi password>"; //mqtt information const char* mqttServer = "<your MQTT server>"; const int mqttPort = 1883; const char* mqttUser = ""; const char* mqttPassword = ""; // End of user definable items #include <EEPROM.h> #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <PubSubClient.h> #include <Wire.h> #include <ESP8266WebServer.h> #include <ADS1115_WE.h> #include <Adafruit_MCP23017.h> #include <SparkFunBME280.h> BME280 mySensor; Adafruit_MCP23017 mcp; #define I2C_ADDRESS 0x48 ADS1115_WE adc(I2C_ADDRESS); WiFiClient espClient; PubSubClient client(espClient); //Declare a global object variable from the ESP8266WebServer class. ESP8266WebServer server(80); //Server on port 80 // This is the upgrade screen html script const char* upgradeIndex = "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>" CLIENT " OTA Firmware Updater<BR>" "Current Version: " VERSION " <BR>Compiled: " __DATE__ " " __TIME__ "<BR><BR>" "<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>" "<input type='file' name='update'>" "<input type='submit' value='Update'>" "</form>" "<div id='prg'>Progress: 0%</div>" "<script>" "$('form').submit(function(e){" "e.preventDefault();" "var form = $('#upload_form')[0];" "var data = new FormData(form);" " $.ajax({" "url: '/update'," "type: 'POST'," "data: data," "contentType: false," "processData:false," "xhr: function() {" "var xhr = new window.XMLHttpRequest();" "xhr.upload.addEventListener('progress', function(evt) {" "if (evt.lengthComputable) {" "var per = evt.loaded / evt.total;" "$('#prg').html('Progress: ' + Math.round(per*100) + '%');" "}" "}, false);" "return xhr;" "}," "success:function(d, s) {" "console.log('success!')" "}," "error: function (a, b, c) {" "}" "});" "});" "</script>"; // Use some macros to normalize Wemos and MCP23017 pin actions. Also defines pin functions #define LEDSOFF digitalWrite(D3, LOW);digitalWrite(D4, LOW) #define GREENLEDON digitalWrite(D3, LOW);digitalWrite(D4, HIGH) #define GREENLEDOFF digitalWrite(D3, LOW);digitalWrite(D4, LOW) #define REDLEDON digitalWrite(D3, HIGH);digitalWrite(D4, LOW) #define REDLEDOFF digitalWrite(D3, LOW);digitalWrite(D4, LOW) #define YELLEDON digitalWrite(D3, HIGH);digitalWrite(D4, HIGH) #define YELLEDOFF digitalWrite(D3, LOW);digitalWrite(D4, LOW) #define IGNITORON mcp.digitalWrite(0, HIGH) #define IGNITOROFF mcp.digitalWrite(0, LOW) #define GETIGNITOR mcp.digitalRead(0) #define SOLENOIDON mcp.digitalWrite(1, HIGH) #define SOLENOIDOFF mcp.digitalWrite(1, LOW) #define GETSOLENOID mcp.digitalRead(1) #define TURN12VON mcp.digitalWrite(4, HIGH) #define TURN12VOFF mcp.digitalWrite(4, LOW) #define RELAYON mcp.digitalWrite(5, HIGH) #define RELAYOFF mcp.digitalWrite(5, LOW) #define GETRELAY mcp.digitalRead(5) #define ADC10K mcp.pinMode(3, INPUT);mcp.pinMode(2, OUTPUT) #define ADC100K mcp.pinMode(3, OUTPUT);mcp.pinMode(2, INPUT) #define GETSWITCH digitalRead(D5) #define FAN D6 // PWM pin for the fan // MQTT related definitions and variables #define MQTT_POLL 60000 // Default 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; // Debounce time in ms #define SW_DBNC_TM 300 unsigned long int switch_dbnc; //Thermistor definitions and variables // Voltage thresholds for Thermistor #define TH_UNDER 1.7 // Under temperature #define TH_OVER 0.2 // Over temperature #define TH_GREEN 1.35 // Run mode #define IGN_DETECT 0.2 // 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; // Generic definitions #define ON 1 #define OFF 0 #define DISABLED 0 #define ENABLED 1 // Define LED states for servicing. Set via set_led(STATE, #blinks) // Yellow and Orange are the same, depending on machine, but code uses Yellow #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 // Blink 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 based on thermistor voltage. Stored in led_mode to keep track of current mode so as not to set more than once #define WARM0 1 // Startup to ADLOW switch - solid Yel #define WARM1 2 // 3.3v to 2.5 v - 1 blink #define WARM2 3 // 2.5v to 2.0v - 2 blink #define WARM3 4 // 2.0v to 1.5v - 3 blink #define WARM4 5 // 1.35v to 1.5v - 3 blink #define RUN1 6 // 1.35v to 1.2v - No blink - Green #define RUN2 7 // 1.2v to 1.0v - 1 blink #define RUN3 8 // 0.8v to 1.0v - 2 blink #define RUN4 9 // 0.6v to 0.8v - 3 blink #define RUN5 10 // 0.4v to 0.6v - 4 blink #define RUN6 11 // 0.2v to 0.4v - 5 blink #define RUN7 12 // 1.35v to 1.7v - 10 blink // Some timer values in ms #define PURGE_TM 10000 // Amount of time to purge #define TO_IGNITOR 25000 // Before ignitor #define PRE_GAS 4000 // Ignitor on before gas #define IGNITOR_WT 15000 // Amount of time to fire ignitor 15 secs #define NO_IGNITE 240000 // Maximum time to wait for ignition 4 mins #define NORUN 3600000 // Max wait till run mode 1 hour // Fan PWM definitions, need to validate normal running speed #define FAN_NORMAL 700 #define FAN_FAST 921 // Cooldown fan speed #define FAN_90 921 // 90% fan speed #define FAN_80 819 // 80% fan speed #define FAN_65 665 // 65% #define FAN_FULL 1023 // Full speed // States for the main running routine. Not all states 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, batterymode, charger_state, tempflag; float temperature, humidity, battery, teg; 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){ Serial.begin(115200); EEPROM.begin(8); Wire.setClock(400000); // Set to fastest speed Wire.begin(); // Start i2c and initialize devices mcp.begin(); // Initialize the i2c GPIO expander // Initialize all the I/O first pinMode(D3, OUTPUT); pinMode(D4, OUTPUT); pinMode(D5, INPUT_PULLUP); pinMode(D6, OUTPUT); mcp.pinMode(0, OUTPUT); mcp.digitalWrite(0, LOW); mcp.pinMode(1, OUTPUT); mcp.digitalWrite(1, LOW); mcp.pinMode(2, INPUT); mcp.digitalWrite(2, HIGH); mcp.pinMode(3, OUTPUT); mcp.digitalWrite(3, HIGH); mcp.pinMode(4, OUTPUT); mcp.digitalWrite(4, LOW); mcp.pinMode(5, OUTPUT); mcp.digitalWrite(5, LOW); REDLEDOFF; GREENLEDOFF; IGNITOROFF; SOLENOIDOFF; ADC100K; TURN12VOFF; analogWrite(FAN, 0); pinMode(FAN, OUTPUT); // Fan off WiFi.begin(ssid, password); //Connect to your WiFi router Serial.println(""); // Wait for connection. This blocks so if it can't connect, the rest of the program won't run. 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("/decmqtt", decmqtt); // Decrease mqtt time server.on("/togglebat", togglebat); // Toggle battery mode server.on("/optiona", optiona); // Send options server.on("/optionb", optionb); // Send options server.on("/optionc", optionc); // Send options server.on("/optiond", optiond); // Send options // Set up the OTA upgrade code. This code is taken from the upgrade example file server.on("/upgrade", HTTP_GET, []() { server.sendHeader("Connection", "close"); server.send(200, "text/html", upgradeIndex); }); server.on("/update", HTTP_POST, []() { server.sendHeader("Connection", "close"); server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK"); ESP.restart(); }, []() { HTTPUpload& upload = server.upload(); if (upload.status == UPLOAD_FILE_START) { Serial.printf("Update: %s\n", upload.filename.c_str()); uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; if (!Update.begin(maxSketchSpace)) { //start with max available size Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_WRITE) { if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_END) { if (Update.end(true)) { //true to set the size to the current progress Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); } else { Update.printError(Serial); } } yield(); }); server.begin(); //Start webserver Serial.println("HTTP server started"); // Setup address of temp sensor and initialize 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); // Set widest measurement range adc.setCompareChannels(ADS1115_COMP_0_GND); // Start with first channel adc.startSingleMeasurement(); // Kick off first measurement; it is read in arrears and in 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 = switch_dbnc = thermistor_timer = temperature_timer = millis(); main_state = adc_state = thermistor_state = 0; batterymode = EEPROM.read(1); // Read the stored battery mode if (batterymode != OFF && batterymode != ON) { // Check for uninitialized memory batterymode = OFF; EEPROM.write(1, batterymode); // If uninitialized, set it to AC mode EEPROM.commit(); } if (batterymode == ON) // If in battery mode, turn off the relay to allow charging RELAYOFF; else // Otherwise, turn it on to enable reverse diode for AC supply RELAYON; 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_thermistor(); service_led(); service_mqtt(); service_temperature(); track_runtime(); if (batterymode) // Only service charger if in battery mode service_charger(); 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 (GETSWITCH == HIGH) { switch_dbnc = millis(); } else if (millis() - switch_dbnc >= SW_DBNC_TM) { // If fully debounced, turn on TURN12VON; // Enable fan and solenoid voltage if (batterymode == ON) // If in battery mode, turn off the relay to allow charging RELAYOFF; else // Otherwise, turn it on to enable reverse diode for AC supply RELAYON; analogWrite(FAN, FAN_FULL); // High Fan to purge fan_speed = FAN_FULL; set_led(LEDYELLOW,0); ADC100K; // Reset the thermistor range to high range thermistor_state = HIGHSTATE; main_timer = millis(); main_state = PURGE; Serial.println("Starting purge state.."); } break; case HIBERNATE: // This is essentially an OFF state, waits for OFF button or Wifi control if (GETSWITCH == LOW) switch_dbnc = millis(); else if (millis() - switch_dbnc >= SW_DBNC_TM) { main_timer = switch_dbnc = millis(); main_state = OFFSTATE; Serial.println("Exiting Hibernate state.."); } break; case PURGE: // Runs fan at full speed to purge chamber of gas if (GETSWITCH == LOW) switch_dbnc = millis(); else if (millis() - switch_dbnc >= SW_DBNC_TM) main_state = POWER_OFF; if (millis() - main_timer >= PURGE_TM ) { // After purge time, go wait, if necessary, before starting analogWrite(FAN, FAN_NORMAL); fan_speed = FAN_NORMAL; main_timer = switch_dbnc = 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 (GETSWITCH == LOW) switch_dbnc = millis(); else if (millis() - switch_dbnc >= SW_DBNC_TM) main_state = POWER_OFF; if (millis() - main_timer >= TO_IGNITOR && thermistor_state == HIGHSTATE) { // If all conditions met, proceed to ignition main_timer = switch_dbnc = millis(); IGNITORON; main_state = IGNITE; Serial.println("Ignitor turned on.."); } break; case IGNITE: // Start the ignition process if (GETSWITCH == LOW) switch_dbnc = millis(); else if (millis() - switch_dbnc >= SW_DBNC_TM) main_state = POWER_OFF; 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(); SOLENOIDON; 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 (GETSWITCH == LOW) switch_dbnc = millis(); else if (millis() - switch_dbnc >= SW_DBNC_TM) main_state = POWER_OFF; if (thermistor_pre - thermistor > IGN_DETECT ) { // If voltage is dropping, then we have ignition main_timer = millis(); IGNITOROFF; // Ignitor should have turned off by now, but turn it off just in case analogWrite(FAN, FAN_FULL); // Set fan to full speed fan_speed = FAN_FULL; main_state = WARMUP; Serial.print(thermistor); Serial.println(" Gas ignited, proceeding to warmup"); } if (millis() - ignitor_timer >= IGNITOR_WT ) // Check for maximum time for the ignitor IGNITOROFF; 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 (GETSWITCH == LOW) switch_dbnc = millis(); else if (millis() - switch_dbnc >= SW_DBNC_TM){ 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"); } // Added LED indicators if (thermistor >= 2.5 && thermistor < 3.3 && led_mode != WARM1) { led_mode = WARM1; set_led(YELBLNK,1); } if (thermistor >= 2.0 && thermistor < 2.5 && led_mode != WARM2) { led_mode = WARM2; set_led(YELBLNK,2); } if (thermistor >= 1.5 && thermistor < 2.0 && led_mode != WARM3) { led_mode = WARM3; set_led(YELBLNK,3); } if (thermistor >= 1.35 && thermistor < 1.5 && led_mode != WARM4) { led_mode = WARM4; set_led(YELBLNK,4); } } 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 (GETSWITCH == LOW) switch_dbnc = millis(); else if (millis() - switch_dbnc >= SW_DBNC_TM) { 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; } // Added LED indicators of operating temperature if (thermistor >= 1.2 && thermistor < 1.35 && led_mode != RUN1) { led_mode = RUN1; set_led(LEDGREEN,0); } if (thermistor >= 1.0 && thermistor < 1.2 && led_mode != RUN2) { led_mode = RUN2; set_led(GREENBLNK,1); } if (thermistor >= 0.8 && thermistor < 1.0 && led_mode != RUN3) { led_mode = RUN3; set_led(GREENBLNK,2); } if (thermistor >= 0.6 && thermistor < 0.8 && led_mode != RUN4) { led_mode = RUN4; set_led(GREENBLNK,3); } if (thermistor >= 0.4 && thermistor < 0.6 && led_mode != RUN5) { led_mode = RUN5; set_led(GREENBLNK,4); } if (thermistor >= 0.2 && thermistor < 0.4 && led_mode != RUN6) { led_mode = RUN6; set_led(GREENBLNK,5); } if (thermistor >= 1.35 && thermistor < 1.7 && led_mode != RUN7) { led_mode = RUN7; set_led(GREENBLNK,10); } break; case FAIL: // Comes here on error, turn off gas and set the error LEDs and error codes SOLENOIDOFF; IGNITOROFF; 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, 6); 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 (GETSWITCH == LOW) switch_dbnc = millis(); else if (millis() - switch_dbnc >= SW_DBNC_TM) { 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; TURN12VOFF; } else { analogWrite(FAN, FAN_NORMAL); fan_speed = FAN_NORMAL; } break; case COOLDOWN: // This is cooldown state before powering off or hibernating analogWrite(FAN, FAN_FAST); fan_speed = FAN_FAST; SOLENOIDOFF; 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 insects in the net till they die if (GETSWITCH == LOW) switch_dbnc = millis(); else if (millis() - switch_dbnc >= SW_DBNC_TM) { next_state = POWER_OFF; main_state = COOLDOWN; set_led(YELBLNK, 5); Serial.println("Cooldown before power off.."); } SOLENOIDOFF; // Keep forcing gas off if (battery < LOW_BATTERY && batterymode) { // If in battery mode, check for low battery previous_state = FANONLY; main_state = FAIL; } break; case POWER_OFF: // Set everything into OFF state before powering off SOLENOIDOFF; IGNITOROFF; ADC100K; TURN12VOFF; set_led(LEDOFF,0); error_code = led_mode = 0; analogWrite(FAN, 0); fan_speed = 0; main_state = OFFSTATE; Serial.println("Powering off"); break; case PRE_HIB: // Prepare for hibernation. This state is for battery powered devices to prepare for real hibernation SOLENOIDOFF; IGNITOROFF; ADC100K; TURN12VOFF; 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, always changing, not usually up to date.... 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(""); } 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 == 4) { SOLENOIDON; Serial.println("Solenoid ON!"); } if (param == 5) { SOLENOIDOFF; Serial.println("Solenoid OFF!"); } if (param == 6) { TURN12VON; Serial.println("12V turned ON!"); } if (param == 7) { set_led(LEDGREEN, 0); // Solid Green } if (param == 8) { set_led(LEDRED, 0); // Solid RED } if (param == 9) { set_led(LEDYELLOW, 0); // Solid Yel } if (param == 10) { set_led(GREENBLNK, 2); // Green Blink } if (param == 11) { set_led(REDBLNK, 2); // Red Blink } if (param == 12) { set_led(GREENYEL, 0); // Alt Blink } if (param > 100) { analogWrite(D6, param); Serial.println("Fan set!"); } } } if (auto_print && millis() - temp_timer >= 1000) { // This will print every sec when autoprint enabled Serial.print("Thermistor = "); Serial.print(thermistor,4); Serial.print("v Main St = "); Serial.print(main_state); Serial.print(" Ther St = "); Serial.print(thermistor_state); Serial.print(" Solenoid = "); Serial.print(GETSOLENOID); Serial.print(" Battery = "); Serial.print(battery,3); Serial.print("v TEG = "); Serial.print(teg,3); Serial.print("v Temperature = "); Serial.print(temperature,1); Serial.print(" Humidity = "); Serial.println(humidity,1); temp_timer = millis(); } } void track_runtime() { switch(tracking_state) { case 0: if (GETSOLENOID == 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 (GETSOLENOID == 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 service_temperature() { // Read the temperature and humidity every second if (millis()-temperature_timer >= 1000) { temperature_timer = millis(); temperature = mySensor.readTempF(); humidity = mySensor.readFloatHumidity(); } } 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_charger() { // Manages the 'charger', if TEGs are working... if (GETRELAY) charger_state = OFF; else charger_state = ON; switch (charger_state) { case ON: if (battery >= 6.15) { RELAYON; // Disable the charger Serial.println("Charger turned off!"); } break; case OFF: if (battery <= 5.4) { RELAYOFF; // Enable the charger Serial.println("Charger turned on!"); } } } void service_led() { // This service routine handles all the LEDs. Set up via set_led() call switch (led_state) { case LEDOFF: LEDSOFF; break; case LEDYELLOW: YELLEDON; break; case LEDRED: REDLEDON; break; case LEDGREEN: GREENLEDON; break; case REDBLNK: switch (led_blink_state) { case BLNK_START: REDLEDON; led_timer = millis(); led_blink_state = BLNK_ON; led_blink_cnt = 0; break; case BLNK_ON: if (millis() - led_timer >= LED_BLNK_ON) { REDLEDOFF; 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; REDLEDON; } 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: // Mostly on, blinks OFF number of times specified switch (led_blink_state) { case BLNK_START: YELLEDOFF; led_timer = millis(); led_blink_state = BLNK_OFF; led_blink_cnt = 0; break; case BLNK_OFF: if (millis() - led_timer >= LED_BLNK_ON) { YELLEDON; 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; YELLEDOFF; } 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: GREENLEDOFF; led_timer = millis(); led_blink_state = BLNK_OFF; led_blink_cnt = 0; break; case BLNK_OFF: if (millis() - led_timer >= LED_BLNK_ON) { GREENLEDON; 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; GREENLEDOFF; } 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: GREENLEDON; led_timer = millis(); led_blink_state = BLNK_OFF; led_blink_cnt = 0; break; case BLNK_OFF: if (millis() - led_timer >= LED_BLNK_ALT) { YELLEDON; led_timer = millis(); led_blink_state = BLNK_ON; } break; case BLNK_ON: if (millis() - led_timer >= LED_BLNK_ALT) { GREENLEDON; 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 3.6 // More than this value, switch to high range #define THERMISTOR_LOW 1.0 // 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; ADC100K; 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; ADC10K; Serial.print(thermistor); Serial.println(" Switching to Low state"); } break; default: break; } } 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.startSingleMeasurement(); adc_state = 1; } break; case 1: // This is battery voltage if (!adc.isBusy()) { adc1 = adc.getResult_V(); battery = adc1*3.0; adc.setCompareChannels(ADS1115_COMP_2_GND); adc.startSingleMeasurement(); adc_state = 2; } break; case 2: // This is TEG voltage if (!adc.isBusy()) { adc2 = adc.getResult_V(); teg = adc2*3.0; 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 "/battery", String(battery,3).c_str()); client.publish("sensor/" CLIENT "/teg", String(teg,3).c_str()); client.publish("sensor/" CLIENT "/fan", String(fan_speed).c_str()); client.publish("sensor/" CLIENT "/ignitor", String(GETIGNITOR).c_str()); client.publish("sensor/" CLIENT "/solenoid", String(GETSOLENOID).c_str()); client.publish("sensor/" CLIENT "/charger", String(charger_state).c_str()); client.publish("sensor/" CLIENT "/batterymode", String(batterymode).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><br>"; #ifdef OTAMENU webmessage += "<br><a href=\"upgrade\">Upgrade Firmware</a>"; #endif webmessage += "<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><a href=\"togglebat\">Toggle Battery Mode</a>: Now "; if (batterymode) webmessage += "Enabled"; else webmessage += "Disabled"; webmessage += "<br>Run Time (D:H:M) = "; if (days < 10) webmessage += "0"; webmessage += String(days); webmessage += ":"; if (hours < 10) webmessage += "0"; webmessage += String(hours); webmessage += ":"; if (mins < 10) webmessage += "0"; 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 (GETIGNITOR) webmessage += "On"; else webmessage += "Off"; webmessage += "<BR>Solenoid St = "; if (GETSOLENOID) webmessage += "On"; else webmessage += "Off"; webmessage += "<BR>Battery = "; webmessage += String(battery,3); webmessage += "V<BR>TEG = "; webmessage += String(teg,3); webmessage += "V<BR>Charger = "; if (GETRELAY) webmessage += "Off"; else webmessage += "On"; 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; 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); SOLENOIDOFF; // Turn off gas IGNITOROFF; // Also make sure ignitor is off TURN12VON; 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); SOLENOIDOFF; 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 togglebat() { String webmessage; webmessage = "<!DOCTYPE html><html><meta http-equiv = \"refresh\" content = \"1; url = "; webmessage += URL; webmessage += "\"></head><body>Battery mode toggled</body></html>"; server.send(200, "text/html", webmessage); if (batterymode) { batterymode = OFF; RELAYON; charger_state = OFF; } else { batterymode = ON; } EEPROM.write(1, batterymode); EEPROM.commit(); tracking_state = 0; Serial.println("Battery mode toggled"); } 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: Mark II October 30, 2020 08:20PM | Registered: 3 years ago Posts: 152 |
Re: Mark II July 13, 2021 02:03PM | Registered: 3 years ago Posts: 152 |
Swap Test and some TEG readings.. July 13, 2021 11:10PM | Registered: 3 years ago Posts: 152 |
Re: Independence Model version... July 14, 2021 12:01AM | Registered: 2 years ago Posts: 9 |
Re: Independence Model version... July 14, 2021 12:40AM | Registered: 3 years ago Posts: 152 |
Re: Independence Model version... July 14, 2021 02:53AM | Registered: 2 years ago Posts: 9 |
Re: Independence Model version... July 14, 2021 02:23PM | Registered: 3 years ago Posts: 152 |
External WiFi antenna for esp8266 July 15, 2021 06:25PM | Registered: 3 years ago Posts: 152 |
Re: External WiFi antenna for esp8266 July 16, 2021 01:40PM | Admin Registered: 7 years ago Posts: 164 |
Re: External WiFi antenna for esp8266 July 16, 2021 02:10PM | Registered: 3 years ago Posts: 152 |
Re: Independence Model version... October 10, 2021 09:04PM | Registered: 2 years ago Posts: 9 |
Re: Independence Model version... October 11, 2021 03:10PM | Registered: 3 years ago Posts: 152 |
134-061 Rev B October 11, 2021 06:09PM | Admin Registered: 7 years ago Posts: 164 |
Re: 134-061 Rev B October 11, 2021 10:07PM | Registered: 3 years ago Posts: 152 |
Re: Independence Model version... October 11, 2021 10:22PM | Registered: 2 years ago Posts: 9 |
Re: Independence Model version... October 11, 2021 10:29PM | Registered: 3 years ago Posts: 152 |
Re: Independence Model version... October 20, 2021 03:06AM | Registered: 2 years ago Posts: 9 |
Re: Independence Model version... October 20, 2021 03:54PM | Registered: 3 years ago Posts: 152 |
Re: Independence Model version... October 20, 2021 09:00PM | Registered: 2 years ago Posts: 9 |
Re: Independence Model version... October 21, 2021 03:48AM | Registered: 3 years ago Posts: 152 |
Re: Independence Model version... October 21, 2021 06:57PM | Registered: 2 years ago Posts: 9 |
Re: Independence Model version... October 21, 2021 10:20PM | Registered: 3 years ago Posts: 152 |