Aes encryption code
Dependencies: Crypto USBDevice mbed
Fork of larada by
Diff: main.cpp
- Revision:
- 0:aaf22a04f350
- Child:
- 1:ccb26dd9845a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Feb 04 03:42:24 2016 +0000 @@ -0,0 +1,826 @@ +#include "mbed.h" +#include "USBSerial.h" +#include "IAP.h" + +#define SERIAL //comment for USB operation, uncomment for serial +//#define DEBUG 1 +#define CALIBRATE 0 +#define FUNCTION_CHECK 0 + +// longest user command we will accept +#define MAX_COMMAND_LEN 64 + +// where to start reading stored values from the EEPROM +#define BASE_ADDRESS 1 + +// temperature control stuff + +// fixed values +#define CONTROL_INTERRUPT 1000 // every 1ms +#define MAX_DUTY 100 // This is both the number of times the heater_control interrupt will run per control period and the max amount of interrupts the heater triac can be on. + +// adjustable values +#define DEFAULT_FILTER 0.05 // first order digital filter parameter, should be [0.0 - 1]. less means filter more, a value of 1 should turn it off +//#define INITIAL_DUTY 25 // 25% duty generally results in a few degrees under 57C output for the ambient temperatures I've been testing at +#define DEFAULT_INITIAL_DUTY 45 +#define DEFAULT_NOMINAL_DUTY 7 // 11% duty is a good set point for Beta init (testing at 20C ambient) +//#define SETPOINT 435 // this results in roughly 57C at the tines on the Alphas (really 53) +#define DEFAULT_SETPOINT 463 //445 -> 53.1-54.1//475 -> 58-59.5// 500 -> 62.5 // 505 -> 59 //475 -> 53C // 445 // 505 seems right for second unit //535-> first unit //527 // this results in roughly 57C at the tines on the Betas +#define DEFAULT_TOLERANCE 2 // if we are within this many ADC counts of the setpoint don't make any changes to the duty cycle +//#define DUTY_TOO_LARGE 40 // If the duty gets larger than this we have problems (Alphas) +#define DEFAULT_DUTY_TOO_LARGE 70 // If the duty gets larger than this we have problems (Betas) -> 65 duty should result in roughly 62C tip temps +//#define DUTY_TOO_LARGE 85 // For testing +//#define DEFAULT_TEMP_LIMIT_LOWER 50 // If the temperature measures too low during operation we are either doing a bad job or have a faulty temperature sensor +#define DEFAULT_TEMP_LIMIT_LOWER 0 // For testing +//#define TEMP_LIMIT_UPPER 485 // No burning allowed (Alphas) +#define DEFAULT_TEMP_LIMIT_UPPER 625 // No burning allowed (Betas) + +float filter = DEFAULT_FILTER; +uint8_t initial_duty = DEFAULT_INITIAL_DUTY; +uint8_t nominal_duty = DEFAULT_NOMINAL_DUTY; +uint16_t setpoint = DEFAULT_SETPOINT; +uint8_t tolerance = DEFAULT_TOLERANCE; +uint8_t duty_too_large = DEFAULT_DUTY_TOO_LARGE; +uint16_t temp_limit_lower = DEFAULT_TEMP_LIMIT_LOWER; +uint16_t temp_limit_upper = DEFAULT_TEMP_LIMIT_UPPER; + +enum State { + IDLE, + WAIT_FOR_TIP, + INITIAL_RAMP, + ACTIVE, + ERROR, +}; + +enum Heater_State { + ON, + OFF, +}; + +// not used yet +enum Error { + NONE, + TEMP_TOO_LOW, + TEMP_TOO_HIGH, + DUTY_TOO_LARGE, +}; + +// Heater control pins +DigitalOut fan(P0_22); +DigitalOut heater_pin(P1_27); +AnalogIn temp_sense(P0_16); + +// LED pins +DigitalInOut empty_led(P0_10); +DigitalInOut fuel_gage_1(P0_9); +DigitalInOut fuel_gage_2(P0_8); +DigitalInOut fuel_gage_3(P1_21); +DigitalInOut fuel_gage_4(P1_31); +DigitalOut tip_light(P1_14); + +DigitalIn tip_sensor(P0_14); + +#define ON_TIME_S 2700L // The device is active for 45 minutes +//#define ON_TIME_S 150L +#define RED_LED_ON_TIME_S 300L // The red LED is active for the last 5 minutes +//#define RED_LED_ON_TIME_S 30L +#define TIP_FLASH_INTERVAL_S 20L // How often the tip will flash +//Serial pc(0x1f00, 0x2012, 0x0001, false); + +#ifdef SERIAL +Serial pc(P0_19, P0_18); // tx, rx +#else +USBSerial pc(0x1f00, 0x2012, 0x0001); +#endif + +Ticker control_interrupt; +Ticker check_limits_interrupt; +Ticker temperature_interrupt; +Ticker tick_interrupt; + +volatile Heater_State heater = OFF; +volatile State state = WAIT_FOR_TIP; +volatile Error error_state = NONE; + +volatile uint8_t duty = DEFAULT_INITIAL_DUTY; +volatile float temperature = 0.0; +unsigned long start_time = 0L; +unsigned long current_time = 0L; +bool connected = false; +volatile uint32_t millis = 0; + +void loop(void); +void calibrate(bool first); +void interpret(char parameter, int value); +void spin_lights(bool first); + +//INTERRUPT - increment this every ms since the normal mbed timer returns an int and real code needs an unsigned type +void tick(void) {millis++;} + +uint32_t get_time(void){ + uint32_t copy = 0; + __disable_irq(); + copy = millis; + __enable_irq(); + return copy; +} + +uint8_t get_duty(void){ + __disable_irq(); + uint8_t duty_copy = duty; + __enable_irq(); + return duty_copy; +} + +void set_duty(uint8_t new_duty){ + __disable_irq(); + duty = new_duty; + __enable_irq(); +} + +float get_temperature(void){ + __disable_irq(); + float temperature_copy = temperature; + __enable_irq(); + return temperature_copy; +} + +//pull the settings saved to flash into memory +void read_settings(void){ + uint8_t address = BASE_ADDRESS; + uint16_t filter_temp = 0; + + IAP iap; + + iap.read_eeprom((char*)address, (char*)&filter_temp, sizeof(filter_temp)); + address += sizeof(filter_temp); + filter = (float)filter_temp/100; + iap.read_eeprom((char*)address, (char*)&initial_duty, sizeof(initial_duty)); + address += sizeof(initial_duty); + iap.read_eeprom((char*)address, (char*)&setpoint, sizeof(setpoint)); + address += sizeof(setpoint); + iap.read_eeprom((char*)address, (char*)&tolerance, sizeof(tolerance)); + address += sizeof(tolerance); + iap.read_eeprom((char*)address, (char*)&duty_too_large, sizeof(duty_too_large)); + address += sizeof(duty_too_large); + iap.read_eeprom((char*)address, (char*)&temp_limit_lower, sizeof(temp_limit_lower)); + address += sizeof(temp_limit_lower); + iap.read_eeprom((char*)address, (char*)&temp_limit_upper, sizeof(temp_limit_upper)); + address += sizeof(temp_limit_upper); + iap.read_eeprom((char*)address, (char*)&nominal_duty, sizeof(nominal_duty)); + address += sizeof(nominal_duty); +} + +//write settings to persistent memory +void write_settings(void){ + IAP iap; + uint8_t address = 1; //BASE_ADDRESS; + uint16_t filter_temp = 0; + + filter_temp = (int)(filter*100); + + iap.write_eeprom((char*)&filter_temp, (char*)address, sizeof(filter_temp)); + address += sizeof(filter_temp); + iap.write_eeprom((char*)&initial_duty, (char*)address, sizeof(initial_duty)); + address += sizeof(initial_duty); + iap.write_eeprom((char*)&setpoint, (char*)address, sizeof(setpoint)); + address += sizeof(setpoint); + iap.write_eeprom((char*)&tolerance, (char*)address, sizeof(tolerance)); + address += sizeof(tolerance); + iap.write_eeprom((char*)&duty_too_large, (char*)address, sizeof(duty_too_large)); + address += sizeof(duty_too_large); + iap.write_eeprom((char*)&temp_limit_lower, (char*)address, sizeof(temp_limit_lower)); + address += sizeof(temp_limit_lower); + iap.write_eeprom((char*)&temp_limit_upper, (char*)address, sizeof(temp_limit_upper)); + address += sizeof(temp_limit_upper); + iap.write_eeprom((char*)&nominal_duty, (char*)address, sizeof(nominal_duty)); + address += sizeof(nominal_duty); +} + +//parse commands. commands take the form of a character followed by a number, delimited by "\r|\n|;" +void getInput(void){ + static int i = 0; + static char parameter = '_'; + static char buffer[MAX_COMMAND_LEN + 1]; + int value = 0; + //char *endp = NULL; + + if(!connected) return; + + // listen for commands coming in +#ifdef SERIAL + while (pc.readable()){ + char ch = pc.getc(); +#else + while (pc.available()){ + char ch = pc._getc(); +#endif + if((ch == '\r' || ch == ';' || ch == '\n') && parameter != '_'){ + if(i > 1){ + buffer[i-1] = 0; + value = atoi(buffer); + } + pc.printf("%c, %d", parameter, value); + //Serial.println("not _"); + interpret(parameter, value); + parameter = '_'; + buffer[0] = 0; + i=0; + break; + } + else{ + if(i==0) parameter = ch; + else buffer[i-1] = ch; + i++; + } + + if(ch == '_' || ch == '\r' || ch == ';' || ch == '\n'){ + parameter = '_'; + buffer[0] = 0; + i=0; + } + } +} + +//print usage info +void usage(void){ + if(!connected)return; + pc.printf("\r\nCommands are a character followed by a number.\r\n"); + wait_ms(1); + pc.printf("Available commands are:\r\n"); + wait_ms(1); + pc.printf("'c': duty cap [1-100]\r\n"); + wait_ms(1); + pc.printf("'d': set the initial duty used on startup [1-100]\r\n"); + wait_ms(1); + pc.printf("'f': set the smoothing filter for the temperature sensor."); + wait_ms(1); + pc.printf(" smaller is more smoothing. [1-100]\r\n"); + wait_ms(1); + pc.printf("'l': lower temperature limit. arbitrary units. [1-1000]\r\n"); + wait_ms(1); + pc.printf("'r': reset all parameters to default values.\r\n"); + wait_ms(1); + pc.printf("'n': set the nominal duty used on control cycle start [1-100]\r\n"); + wait_ms(1); + pc.printf("'s': setpoint. same units as upper and lower temperature"); + wait_ms(1); + pc.printf(" limit [1-1000]\r\n"); + wait_ms(1); + pc.printf("'t': tolerance. no control action within this band. same "); + wait_ms(1); + pc.printf("units as upper and lower temperature limit [1-1000]\r\n"); + wait_ms(1); + pc.printf("'u': upper temperature limit. arbitrary units. [1-1000]\r\n"); + wait_ms(1); + pc.printf("'w': write the current control parameters to permanent memory\r\n"); + wait_ms(1); + pc.printf("\r\n\r\n"); + wait_ms(1); + + pc.printf("Values can be modified by entering a "); + pc.printf("command followed by a number."); + wait_ms(1); + pc.printf(" For example, entering 'c50' <enter> would limit the duty"); + wait_ms(1); + pc.printf(" to 50%\r\n\r\n"); + wait_ms(1); + + pc.printf("Status of individual variables can be queried by entering "); + wait_ms(1); + pc.printf("that command name (no number afterwards), or typing any "); + wait_ms(1); + pc.printf("unrecognised command (which prints this message).\r\n\r\n"); + wait_ms(1); +} + +void print_active_settings(void){ + if(!connected)return; + pc.printf("Duty capped at: %u%\r\n", duty_too_large); + wait_ms(1); + pc.printf("Initial duty is: %u\r\n", initial_duty); + wait_ms(1); + pc.printf("Nominal duty is: %u\r\n", nominal_duty); + wait_ms(1); + pc.printf("Temperature filter is: %d\r\n", (int)(filter * 100)); + wait_ms(1); + pc.printf("Lower temperature limit is: %u\r\n", temp_limit_lower); + wait_ms(1); + pc.printf("Upper temperature limit is: %u\r\n", temp_limit_upper); + wait_ms(1); + pc.printf("Setpoint is: %u\r\n", setpoint); + wait_ms(1); + pc.printf("Tolerance is %u\r\n\r\n", tolerance); + wait_ms(1); +} + +//interpret a user command +void interpret(char parameter, int value){ + switch(parameter){ + case 'c': + if(value != 0) duty_too_large = value; + pc.printf("Duty cap is %u\r\n", duty_too_large); + break; + case 'd': + if(value != 0) initial_duty = value; + pc.printf("Initial duty is %u\r\n", initial_duty); + break; + case 'f': + if(value != 0) filter = ((float)value) / 100.0; + pc.printf("Filter is %d\r\n", (int)(filter * 100)); + break; + case 'r': + filter = DEFAULT_FILTER; + initial_duty = DEFAULT_INITIAL_DUTY; + nominal_duty = DEFAULT_NOMINAL_DUTY; + setpoint = DEFAULT_SETPOINT; + tolerance = DEFAULT_TOLERANCE; + duty_too_large = DEFAULT_DUTY_TOO_LARGE; + temp_limit_lower = DEFAULT_TEMP_LIMIT_LOWER; + temp_limit_upper = DEFAULT_TEMP_LIMIT_UPPER; + write_settings(); + pc.printf("All parameters reset to default values:\r\n"); + print_active_settings(); + break; + case 'l': + if(value != 0) temp_limit_lower = value; + pc.printf("Lower temperature limit is %u\r\n", temp_limit_lower); + break; + case 'n': + if(value != 0) nominal_duty = value; + pc.printf("Nominal duty is %u\r\n", nominal_duty); + break; + case 's': + if(value != 0) setpoint = value; + pc.printf("Setpoint is %u\r\n", setpoint); + break; + case 't': + if(value != 0) tolerance = value; + pc.printf("Tolerance is %u\r\n", tolerance); + break; + case 'u': + if(value != 0) temp_limit_upper = value; + pc.printf("Upper temperature limit is %u\r\n", temp_limit_upper); + break; + case 'w': + write_settings(); + pc.printf("Wrote the current control parameters to memory.\r\n"); + break; + + + default: + usage(); + print_active_settings(); + break; + } +} + +//put everything into a low power/off state. control loop will be unaffected by this command, so that will also need to be disabled before the heater will stay off +void all_off(){ + heater_pin = 0; + heater = OFF; //need to treat this as volatile + fan = 0; + empty_led.input(); // + fuel_gage_1.input(); // = 1; + fuel_gage_2.input(); // = 1; + fuel_gage_3.input(); // = 1; + fuel_gage_4.input(); // = 1; + tip_light = 0; +} + +// run this to manually check the hardware works +// probably best to disable the heater on the first try +void functional_check(void){ + all_off(); + if(connected)pc.printf("Tip light\r\n"); + tip_light = 1; + wait_ms(1000); + all_off(); + if(connected)pc.printf("Empty\r\n"); + empty_led.output(); + empty_led = 0; + wait_ms(1000); + all_off(); + if(connected)pc.printf("Fuel Gage 1\r\n"); + fuel_gage_1.output(); + fuel_gage_1 = 0; + wait_ms(1000); + all_off(); + if(connected)pc.printf("Fuel Gage 2\r\n"); + fuel_gage_2.output(); + fuel_gage_2 = 0; + wait_ms(1000); + all_off(); + if(connected)pc.printf("Fuel Gage 3\r\n"); + fuel_gage_3.output(); + fuel_gage_3 = 0; + wait_ms(1000); + all_off(); + if(connected)pc.printf("Fuel Gage 4\r\n"); + fuel_gage_4.output(); + fuel_gage_4 = 0; + wait_ms(1000); + all_off(); + if(connected)pc.printf("Fan\r\n"); + fan = 1; + wait_ms(5000); + if(connected)pc.printf("Heater\r\n"); + heater_pin = 1; + + while(1){ + if(connected)pc.printf("Temp: %u\r\n", temp_sense.read_u16()>>6); + wait_ms(50); + tip_light = 1; + wait_ms(50); + tip_light = 0; + } +} + +// INTERRUPT - called every 4ms, samples the ADC and filters the value with a low pass first order digital filter +void get_temp(void){ + // not bothering with units, this means we need to keep the update constant at once every 4ms or we will need to set the filter again + //temperature = filter * (temp_sense.read_u16()>>6) + (1 - filter) * temperature; + // temperature is now in degrees C (value is at sensor, not at tips) + temperature = filter * (51.282 * (temp_sense.read()*3.3 - 0.4)) + (1 - filter) * temperature; +} + +// INTERRUPT - called every millisecond to handle maintaining the on/off state of the triac +void heater_control(void){ + static uint8_t count = 0; + + // count up once per interrupt. + // safety: check to make sure we haven't exceeded MAX_DUTY safety limit + // after duty is reached for this control period, turn the heat off + count++; + + if(heater == ON && fan.read()){ + if(count > MAX_DUTY){ + count = 0; + heater_pin = 1; + } + if(count > duty)heater_pin = 0; + } + else heater_pin = 0; +} + +// bail, something is wrong +void abort(bool error){ + uint16_t period = 1000; + if(error) period = 250; + // turn everything off, leave the fan on for a few seconds and flash the red LED + control_interrupt.detach(); + all_off(); + empty_led.input(); + fan = 1; + wait_ms(3000); + fan = 0; + while(1){ + empty_led.output(); + empty_led = 0; + heater_pin = 0; + wait_ms(period); + heater_pin = 0; + empty_led.input(); + heater_pin = 0; + wait_ms(period); + } +} + +// INTERRUPT - monitor stuff that might indicate an error condition +void check_limits(void){ +// need to move printing to the main loop + if(duty >= duty_too_large){ + if(connected){ + pc.printf("Error!!! Duty cycle has become unreasonably "); + pc.printf("large, Aborting.\r\n"); + } + abort(true); + } + + if(get_temperature() > temp_limit_upper){ + if(connected)pc.printf("Error!!! Temperature is too high, Aborting.\r\n"); + abort(true); + } + + if((state == ACTIVE || state == INITIAL_RAMP) && (get_temperature() < temp_limit_lower)){ + if(connected){ + pc.printf("%f\r\n", get_temperature()); + pc.printf("Error!!! Abnormally low temperature detected. "); + pc.printf("Please check the sensor, Aborting.\r\n"); + } + abort(true); + } +} + +// values pulled from the MCP9701T-E/LT datasheet +// 19.5mV/deg-C, 400mV @ 0C +float adc_to_temp(float adc_value){ + //return 0.195 * adc_value - + return 0.196 * adc_value - 31.322; +} + +void init(void){ +#ifdef SERIAL + pc.baud(115200); + connected = true; +#else + pc.connect(); + connected = pc.vbusDetected(); +#endif + + if(connected)pc.printf("hello\r\n"); + + tick_interrupt.attach(&tick, 0.001); + control_interrupt.attach(&heater_control, 0.001); + temperature_interrupt.attach(&get_temp, 0.004); + if(!CALIBRATE)check_limits_interrupt.attach(&check_limits, 0.5); + + read_settings(); + set_duty(initial_duty); + all_off(); +} + +// tip neeeds to be present before we can start the cycle +// later we will also abort the cycle if the tip is removed +void do_wait_for_tip(bool first){ + unsigned long time = get_time(); + unsigned long time_increment = time % 1800; + + if(first){ + if(connected)pc.printf("Looking for tip\r\n"); + } + if(!tip_sensor){ //tip present is low == present + tip_light = 1; + fuel_gage_1.output(); + fuel_gage_1 = 0; + fuel_gage_2.output(); + fuel_gage_2 = 0; + fuel_gage_3.output(); + fuel_gage_3 = 0; + fuel_gage_4.output(); + fuel_gage_4 = 0; + empty_led.input(); + state = INITIAL_RAMP; + if(connected)pc.printf("Found the tip\r\n"); + return; + } + + if(time_increment < 300){ + fuel_gage_1.input(); // = 1; + fuel_gage_2.input(); // = 1; + fuel_gage_3.input(); // = 1; + fuel_gage_4.input(); // = 1; + } + if(time_increment > 600){ + fuel_gage_1.output(); + fuel_gage_1 = 0; + } + if(time_increment > 900){ + fuel_gage_2.output(); + fuel_gage_2 = 0; + } + if(time_increment > 1200){ + fuel_gage_3.output(); + fuel_gage_3 = 0; + } + if(time_increment > 1500){ + fuel_gage_4.output(); + fuel_gage_4 = 0; + } +} + +//This should quickly take us up from ambient to the setpoint. +void do_initial_ramp(bool first){ + // set duty to initial_duty and wait to reach the setpoint to break out + static uint32_t start_time = 0; + static uint32_t last_print = get_time(); + + if(first){ + start_time = get_time(); + fan = 1; + set_duty(initial_duty); + heater = ON; + if(connected)pc.printf("Initial ramp up. Duty will be held constant until setpoint is reached.\r\n"); + } + + if(get_time() - start_time > 60000){ + if(connected)pc.printf("Took too long to reach setpoint, aborting.\r\n"); + abort(true); + } + + if(get_time() - last_print > 5000){ + if(connected)pc.printf("Duty: %u, Temp: %f, Time: %.2fs\r\n", get_duty(), get_temperature(), (float)get_time()/1000); + last_print = get_time(); + } + + if(get_temperature() > setpoint - tolerance){ + //now we are roughly up to temperature + set_duty(nominal_duty); + state = ACTIVE; + return; + } +} + +void do_treatment_cycle(bool first){ + static uint32_t start_time = 0; + static uint32_t control_timer = 0; + uint8_t duty_copy; + float temperature_copy; + + if(first){ + start_time = get_time(); + control_timer = start_time; + } + + uint32_t current_time = get_time() - start_time; + + // check if we're done + if(current_time >= ON_TIME_S * 1000L){ + if(connected)pc.printf("Done!\r\n"); + abort(false); + state = IDLE; + } + + //if(!tip->in_place())abort(false); + + if(current_time - control_timer > 5000){ // run the control loop every 5 seconds + control_timer = current_time; + duty_copy = get_duty(); + temperature_copy = get_temperature(); + if(temperature_copy > setpoint + tolerance) duty_copy--; + if(temperature_copy < setpoint - tolerance) duty_copy++; + set_duty(duty_copy); + + if(connected)pc.printf("Duty: %u, Temp: %f, Time: %.2fs\r\n", get_duty(), get_temperature(), ((float)get_time() - (float)start_time)/1000); + } +} + +void print_state(void){ + if(!connected)return; + switch(state){ + case IDLE: + printf("IDLE\r\n"); + break; + case WAIT_FOR_TIP: + printf("WAIT_FOR_TIP\r\n"); + break; + case INITIAL_RAMP: + printf("INITIAL_RAMP\r\n"); + break; + case ACTIVE: + printf("ACTIVE\r\n"); + break; + case ERROR: + printf("ERROR\r\n"); + break; + default: break; + } +} + +int main(){ + static State last_state = IDLE; + init(); + //if(FUNCTION_CHECK) functional_check(); + if(CALIBRATE){ + calibrate(true); + while(1)calibrate(false); + } + + while(1){ + getInput(); + + bool state_change = false; + if(state != last_state){ + state_change = true; + last_state = state; + print_state(); + } + + switch(state){ + case IDLE: + // later put a check to exit state per on/off switch + break; + case WAIT_FOR_TIP: + do_wait_for_tip(state_change); + break; + case INITIAL_RAMP: + do_initial_ramp(state_change); + spin_lights(state_change); + break; + case ACTIVE: + do_treatment_cycle(state_change); + spin_lights(false); + break; + case ERROR: + abort(true); + break; + default: break; + } + } +} + +void spin_lights(bool first){ + static uint32_t start_time = 0; + + if(first) start_time = get_time(); + uint32_t current_time = get_time() - start_time; + + uint32_t tip_time = current_time % 23000; + if(tip_time < 20000) tip_light = 1; + else tip_light = (tip_time % 100 < 50)?1:0; + //if(current_time > 4600) current_time = 0; + + // handle fule gage LEDs + // this should be more directly linked to the treatment stop condition + uint32_t step = (ON_TIME_S - RED_LED_ON_TIME_S)/5; + step *= 1000; + + if(current_time > step) fuel_gage_4.input(); + else{ + fuel_gage_4.output(); + fuel_gage_4 = 0; + } + if(current_time > 2*step) fuel_gage_3.input(); + else{ + fuel_gage_3.output(); + fuel_gage_3 = 0; + } + if(current_time > 3*step) fuel_gage_2.input(); + else{ + fuel_gage_2.output(); + fuel_gage_2 = 0; + } + if(current_time > 4*step) fuel_gage_1.input(); + else{ + fuel_gage_1.output(); + fuel_gage_1 = 0; + } + if(current_time > 5*step){ + empty_led.output(); + empty_led = 0; + } + else empty_led.input(); +} + +void calibrate(bool first){ + static uint32_t start_time = 0; + static uint32_t control_timer = 0; + uint8_t duty_copy; + + if(first){ + start_time = get_time(); + control_timer = start_time; + fan = 1; + set_duty(5); + heater = ON; + } + + uint32_t current_time = get_time() - start_time; + + if(current_time - control_timer > 15000){ // increase the duty by 5% every 15 seconds + if(connected)pc.printf("Duty: %u, Temp: %f, Time: %.2fs\r\n", get_duty(), get_temperature(), ((float)get_time() - (float)start_time)/1000); + control_timer = current_time; + duty_copy = get_duty(); + duty_copy += 5; + // check if we're done + if(duty > 75 && connected){ + set_duty(1); + pc.printf("Done!\r\n"); + abort(false); + } + set_duty(duty_copy); + } +} + +/* +void calibrate(void){ + // this is really not necessary because all we care about is the temperature we need to hold the sensor at, + // which we are assuming directly correlates to output air temp. + // in reality it will probably be affected by ambient temperature, + // humidity, air flow rate, elevation (air density), and other factors + static uint16_t count = 0; + static uint8_t duty_copy = 5; //inital duty + float temperature_copy; + static int tester_count = 0; + + current_time = get_time(); + count++; + + check_limits(); + + if(count > 200){ // run the control loop every second + count = 0; + tester_count++; + if(tester_count % 30 == 0){ //30 seconds each duty cycle + duty_copy += 5; + if(duty > 85)abort(false); + if(connected)pc.printf("Duty: %u\r\nTemps:\r\n", duty_copy); + } + __disable_irq(); + duty = duty_copy; + temperature_copy = temperature; + __enable_irq(); + + if(DEBUG && (tester_count % 30) > 24)pc.printf("\t%f\t%u\t%f\r\n", temperature_copy, temp_sense.read_u16(), temp_sense.read()); + } +}*/ \ No newline at end of file