diff options
Diffstat (limited to 'pcr-controller')
-rw-r--r-- | pcr-controller/pcr-controller.c | 32 | ||||
-rw-r--r-- | pcr-controller/protocol_uc.txt | 31 | ||||
-rw-r--r-- | pcr-controller/pwm.c | 12 | ||||
-rw-r--r-- | pcr-controller/temp_curve.c | 88 | ||||
-rw-r--r-- | pcr-controller/temp_curve.h | 2 |
5 files changed, 95 insertions, 70 deletions
diff --git a/pcr-controller/pcr-controller.c b/pcr-controller/pcr-controller.c index 1b8741b..85c5b38 100644 --- a/pcr-controller/pcr-controller.c +++ b/pcr-controller/pcr-controller.c @@ -81,6 +81,7 @@ int16_t raw_temp_ = 0; uint8_t temp_is_fresh_ = 0; uint8_t debug_ = 0; uint8_t monitor_temp_ = 0; +uint8_t pump_autoon_ = 0; // at f_system_clk = 10Hz, system_clk_ will not overrun for at least 13 years. PCR won't run that long volatile uint32_t system_clk_ = 0; @@ -214,16 +215,16 @@ void setPeltierCoolingDirectionPower(int16_t value) if (value >= 0) { - PIN_HIGH(PELTIER_INA_PORT, PELTIER_INA_PIN); - PIN_LOW(PELTIER_INB_PORT, PELTIER_INB_PIN); - pwm_set((uint8_t) value); - } else { PIN_LOW(PELTIER_INA_PORT, PELTIER_INA_PIN); PIN_HIGH(PELTIER_INB_PORT, PELTIER_INB_PIN); + pwm_set((uint8_t) value); + } else { + PIN_HIGH(PELTIER_INA_PORT, PELTIER_INA_PIN); + PIN_LOW(PELTIER_INB_PORT, PELTIER_INB_PIN); pwm_set((uint8_t) (-1 * value)); } if (debug_) - printf("Peltier value: %d, INA: %d, INB: %d\r\n", value, (PELTIER_INA_PORT & _BV(PELTIER_INA_PIN)) > 0, (PELTIER_INB_PORT & _BV(PELTIER_INB_PIN)) > 0); + printf("Peltier value: %d, INA: %d, INB: %d, OCR1AH: %d, OCR1AL: %d\r\n", value, (PELTIER_INA_PORT & _BV(PELTIER_INA_PIN)) > 0, (PELTIER_INB_PORT & _BV(PELTIER_INB_PIN)) > 0, OCR1AH, OCR1AL); } void handle_cmd(uint8_t cmd) @@ -252,10 +253,17 @@ void handle_cmd(uint8_t cmd) case 'P': cmdq_queueCmdWithNumArgs((void*) pid_setP, 1); return; case 'I': cmdq_queueCmdWithNumArgs((void*) pid_setI, 1); return; case 'D': cmdq_queueCmdWithNumArgs((void*) pid_setD, 1); return; - case 'A': PIN_HIGH(PUMP_PORT, PUMP_PIN); break; - case 'a': PIN_LOW(PUMP_PORT, PUMP_PIN); break; + case 'A': + PIN_HIGH(PUMP_PORT, PUMP_PIN); + pump_autoon_ = 0; + break; + case 'a': + PIN_LOW(PUMP_PORT, PUMP_PIN); + pump_autoon_ = 0; + break; case 'B': PIN_HIGH(TOPHEAT_PORT, TOPHEAT_PIN); break; case 'b': PIN_LOW(TOPHEAT_PORT, TOPHEAT_PIN); break; + case '@': pump_autoon_ = 1; break; case '.': tcurve_printCurve(); return; case '-': //reset temp curve tcurve_reset(); @@ -264,9 +272,9 @@ void handle_cmd(uint8_t cmd) //~ tcurve_add(readNumber(), readNumber()); cmdq_queueCmdWithNumArgs((void*) tcurve_add, 2); return; - case '!': cmdq_queueCmdWithNumArgs((void*) tcurve_setRepeatStartPosToLatestEntry, 0); return; + case '>': cmdq_queueCmdWithNumArgs((void*) tcurve_setRepeatStartPosToLatestEntry, 0); return; + case '<': cmdq_queueCmdWithNumArgs((void*) tcurve_setRepeatEndPosToLatestEntry, 0); return; case 'Z': cmdq_queueCmdWithNumArgs((void*) tcurve_setRepeats, 1); return; - case 'E': cmdq_queueCmdWithNumArgs((void*) tcurve_setPostCycleTargetTemp, 1); return; default: printf("{\"cmd_ok\":false,\"error\":\"unknown cmd\"}\r\n"); return; } printf("{\"cmd_ok\":true}\r\n"); @@ -342,6 +350,8 @@ int main(void) // e.g. enable periodic temp monitoring 'm' rather than querying temp at some intervall 's' if (pid_isEnabled()) { + if (pump_autoon_) + PIN_HIGH(PUMP_PORT, PUMP_PIN); if (debug_) printf("pid_calc.."); while (system_clk_ - last_time2 < 5); //wait until at least 500ms have passed since last time. Should be enough time for everything else to finish. (after 13 years, code will hang here) @@ -352,7 +362,11 @@ int main(void) setPeltierCoolingDirectionPower(pid_calc(raw_temp_)); } else + { setPeltierCoolingDirectionPower(0); + if (pump_autoon_) + PIN_LOW(PUMP_PORT, PUMP_PIN); + } } anyio_task(); diff --git a/pcr-controller/protocol_uc.txt b/pcr-controller/protocol_uc.txt index 18a2465..9aeaad5 100644 --- a/pcr-controller/protocol_uc.txt +++ b/pcr-controller/protocol_uc.txt @@ -11,6 +11,7 @@ 'd' Same as above 'A' Switch on pump. 'a' Switch pump off. +'@' Switch pump on automatically if temp goes higher than 30°C or lower than 19°C 'B' Switch on top heater. 'b' Switch top heater off. 'L' Toggle LED (Debug) @@ -22,13 +23,14 @@ '.' Print out currently programmed temperature curve as JSON string. '+' Add a temperature curve point. <-TempValue <-Duration Excpects 2 arguments: Targettemperature and duration for which that temperature is to be held after it has been reached. -'!' Set the last added (with '+') temperature curve point to be the cycle start point. +'>' Set the last added (with '+') temperature curve point to be the cycle start point. E.g. if >0 curve repetitions are set (with 'Z') the repetitions will start here, instead of at the first added curve point. +'<' Set the last added (with '+') temperature curve point to be the cycle end point. + E.g. this and any temperature points added after this marker will not be repeated, but programmed after the main loop 'Z' Set number of cycle repetitions <-IntValue E.g: 0 == default == no repetitions == 1 cycle 1 == 1 repetitions == 2 cycles) .... -'E' Program a final hold temperature. PID will try to hold this value after all cycles have finished. <-TempValue 'm' Toggle periodic status output as JSON string. '?' Toggle Debug Output. '#' Disable PID (i.e. set PID target temperature to -2048.00) @@ -73,7 +75,7 @@ Responses to "t" or "s": {"t":9999999, "currtemp":5.02, "targettemp":5.00, "curve":true, "curve_t_elapsed":65535, "cycles_left":0} //we know all is finished because targettemp is hold-temp Response to "." -{"curve":[{"temp":1520,"duration":9000,"is_curr":1,"is_loop_start":1},{"temp":1040,"duration":10,"is_curr":0,"is_loop_start":0},{"temp":960,"duration":300,"is_curr":0,"is_loop_start":0},{"temp":1120,"duration":300,"is_curr":0,"is_loop_start":0},0],"end_temp:":80} +{"curve":[{"temp":1520,"duration":9000,"is_curr":1,"is_loop_start":0,"is_loop_end":0},{"temp":1040,"duration":10,"is_curr":0,"is_loop_start":1,"is_loop_end":0},{"temp":960,"duration":300,"is_curr":0,"is_loop_start":0,"is_loop_end":0},{"temp":1120,"duration":300,"is_curr":0,"is_loop_start":0,"is_loop_end":0},{"temp":1120,"duration":1000,"is_curr":0,"is_loop_start":0,"is_loop_end":1},0],"end_temp":80,"loop_repeats":30} Response to other commands: {"cmd_ok":false,"error": "No DS1820 sensors on 1wire bus, thus no temperature"} @@ -85,25 +87,26 @@ Response to other commands: s - = -A +@ b -+1520,9000 -+1040,10 -! -+960,300 -+1120,300 ++1536,300 +> ++448,300 ++1152,300 +< Z30 -E80 ++64,9999 m The sequence of above commands - prints current temperature - deletes any currenlty set temperature curve - instructs the PID controller to hold the current temperature -- enables the pump -- programms the following temperature curve: 95°C (15min) -> [ -> 65°C (1s) -> 60°C (30s) -> 70°C (30s) ] -- sets the curve to repeat the items in [] brackets 30 times -- programms final holding temperature of 5°C (after temperature curve and all cylces have finished). +- set the pump to auto +- switch off top heater +- programms the following temperature curve: [ 96°C (30s) -> 28°C (30s) -> 72°C (30s) ] +- sets the curve to repeat the items in >< brackets 30 times +- programms final holding temperature of 4°C (note that duration of last entry does not really matter since it will always be held indefinately). - activates periodic status output. diff --git a/pcr-controller/pwm.c b/pcr-controller/pwm.c index 918d37b..a4e3863 100644 --- a/pcr-controller/pwm.c +++ b/pcr-controller/pwm.c @@ -11,19 +11,23 @@ void pwm_init(void) TCCR1A = 0; TCNT1 = 0; OCR1A = 0; - TCCR1A = (1<<COM1A1) | (1<<WGM10); - TCCR1B = (1<<WGM12); + TCCR1A = (1<<WGM10); //Fast PWM, 8-bit + TCCR1B = (1<<WGM12); //Fast PWM, 8-bit + //TCCR1A |= (1<<COM1A1) // Clear OCnA/OCnB/OCnC on compare match when up-counting. Set OCnA/OCnB/OCnC on compare match when downcounting. } inline void pwm_on(void) { - TCCR1B = (TCCR1A & 0xF8) | (1<<CS10); + TCCR1A |= (1<<COM1A1); // Clear OCnA/OCnB/OCnC on compare match when up-counting. Set OCnA/OCnB/OCnC on compare match when downcounting. + TCCR1B = (TCCR1B & 0xF8) | (1<<CS10); // enable timer clock, no prescaling } inline void pwm_off(void) { - TCCR1B = (TCCR1A & 0xF8); + TCCR1A &= ~((1<<COM1A1) | (1<<COM1A0)); //normal port operation + TCCR1B = (TCCR1B & 0xF8); //no clock source, timer stopped TCNT1 = 0; + PORTB &= ~ (1 << PB5); //set pin to LOW (otherwise it will remain in state since last pwm toggle) } void pwm_set(uint8_t val) diff --git a/pcr-controller/temp_curve.c b/pcr-controller/temp_curve.c index 36ec55a..f44981f 100644 --- a/pcr-controller/temp_curve.c +++ b/pcr-controller/temp_curve.c @@ -33,16 +33,16 @@ struct tc_entry { tc_entry *next; }; -tc_entry *temp_curve_ = 0; -tc_entry *temp_curve_end_ = 0; -tc_entry *temp_curve_current_ = 0; -tc_entry *temp_curve_restart_pos_ = 0; +tc_entry *temp_curve_ = 0; //pointer to start of curve (so we can free it by going through the list) +tc_entry *temp_curve_end_ = 0; //pointer to last added entry in curve (so we know can quickly append new entries) +tc_entry *temp_curve_current_ = 0; //pointer to currently active entry (temp we currently hold) +tc_entry *temp_curve_loop_first_ = 0; //pointer to start of loop (loop is a subset of curve list) +tc_entry *temp_curve_loop_last_ = 0; //pointer to end of loop (loop is a subset of curve list) uint16_t temp_stable_time_ = 0; -uint8_t curve_num_repeats_ = 0; -uint8_t temp_curve_finished_ = 0; -int16_t post_cycle_target_temp_ = TCURVE_ERROR; +uint8_t temp_curve_original_num_repeats_ = 0; +uint8_t curve_loop_num_repeats_ = 0; // number of times the loop still needs to be reapeated before finishing the rest of the curve void tcurve_reset(void) { @@ -60,18 +60,14 @@ void tcurve_reset(void) temp_curve_ = 0; temp_curve_end_ = 0; temp_curve_current_ = 0; - curve_num_repeats_ = 0; - temp_curve_restart_pos_ = temp_curve_; - temp_curve_finished_ = 0; + temp_curve_original_num_repeats_ = 0; + curve_loop_num_repeats_ = 0; + temp_curve_loop_first_ = temp_curve_; + temp_curve_loop_last_ = 0; if (debug_) printf("tcreset: done\n\n"); } -uint8_t tcurve_hasFinished(void) -{ - return temp_curve_finished_; -} - uint16_t tcurve_getTimeElapsed(void) { return temp_stable_time_; @@ -79,7 +75,7 @@ uint16_t tcurve_getTimeElapsed(void) uint8_t tcurve_getRepeatsLeft(void) { - return curve_num_repeats_; + return curve_loop_num_repeats_; } uint8_t tcurve_isSet(void) @@ -89,13 +85,8 @@ uint8_t tcurve_isSet(void) void tcurve_setRepeats(uint8_t r) { - curve_num_repeats_ = r; - temp_curve_finished_ = 0; -} - -void tcurve_setPostCycleTargetTemp(int16_t v) -{ - post_cycle_target_temp_ = v; + curve_loop_num_repeats_ = r; + temp_curve_original_num_repeats_ = r; } void tcurve_add(int16_t temp, uint16_t hold_for_ticks) @@ -110,7 +101,7 @@ void tcurve_add(int16_t temp, uint16_t hold_for_ticks) temp_curve_end_ = new_entry; temp_curve_ = new_entry; temp_curve_current_ = new_entry; - temp_curve_restart_pos_ = new_entry; + temp_curve_loop_first_ = new_entry; } else { temp_curve_end_->next = new_entry; temp_curve_end_ = new_entry; @@ -119,7 +110,16 @@ void tcurve_add(int16_t temp, uint16_t hold_for_ticks) void tcurve_setRepeatStartPosToLatestEntry(void) { - temp_curve_restart_pos_= temp_curve_end_; + //calling this again, overwrites last set loop start entry + temp_curve_loop_first_= temp_curve_end_; + //no loop_last_ before loop_first_ + temp_curve_loop_last_ = 0; +} + +void tcurve_setRepeatEndPosToLatestEntry(void) +{ + //calling this again, overwrites last set loop stop entry + temp_curve_loop_last_ = temp_curve_end_; } void tcurve_printCurve(void) @@ -132,11 +132,17 @@ void tcurve_printCurve(void) printf("{\"curve\":["); for (tc_entry *ce = temp_curve_; ; ce=ce->next) { - printf("{\"temp\":%d,\"duration\":%u,\"is_curr\":%d,\"is_loop_start\":%d},",ce->target_temp, ce->hold_for_timeticks, ce == temp_curve_current_,ce == temp_curve_restart_pos_); + printf("{\"temp\":%d,\"duration\":%u,\"is_curr\":%d,\"is_loop_start\":%d,\"is_loop_end\":%d},", + ce->target_temp, + ce->hold_for_timeticks, + ce == temp_curve_current_, + ce == temp_curve_loop_first_, + ce == temp_curve_loop_last_); + if (ce == temp_curve_end_) break; } - printf("0],\"end_temp:\":%d}\r\n", post_cycle_target_temp_); + printf("0],\"loop_repeats\":%d}\r\n", temp_curve_original_num_repeats_); } int16_t tcurve_getTempToSet(int16_t current_temp, uint16_t ticks_elapsed) @@ -144,30 +150,28 @@ int16_t tcurve_getTempToSet(int16_t current_temp, uint16_t ticks_elapsed) if (temp_curve_current_ == 0) return TCURVE_ERROR; - if (temp_curve_finished_ && post_cycle_target_temp_ != TCURVE_ERROR) - return post_cycle_target_temp_; - if (current_temp > temp_curve_current_->target_temp - temp_margin_ && current_temp < temp_curve_current_->target_temp + temp_margin_) { temp_stable_time_ += ticks_elapsed; } // else: ignore the case of temp falling temporarily outside of temp_margin_ - // if time has been stable for long enough, advance to next - // if there is no next, repeat curve until curve_num_repeats_ == 0 - // once that happens, set to post_cycle_target_temp_ or hold last value + //if temp has been stable for the set amount of timeticks in current curve element if (temp_stable_time_ >= temp_curve_current_->hold_for_timeticks) { temp_stable_time_ = 0; - if (temp_curve_current_->next != 0) - { + + if (curve_loop_num_repeats_ && //if repetitions left + ( (temp_curve_loop_last_ != 0 && temp_curve_current_ == temp_curve_loop_last_) //and we have reached a set loop endpoint + || temp_curve_current_->next == 0 //or the end of the list + )) + { //go back to first point in loop + curve_loop_num_repeats_--; + temp_curve_current_ = temp_curve_loop_first_; + } else if (temp_curve_current_->next != 0) //else if elements left in curve list + { // go to next element temp_curve_current_ = temp_curve_current_->next; - } else if (curve_num_repeats_) - { - //restart temp curve from the beginning (or the set position) - temp_curve_current_ = temp_curve_restart_pos_; - curve_num_repeats_--; - } else - temp_curve_finished_ = 1; + } + //else stay on temperature of last element forever (until reset is called or new elements are added) } return temp_curve_current_->target_temp; }
\ No newline at end of file diff --git a/pcr-controller/temp_curve.h b/pcr-controller/temp_curve.h index 104ecb3..bbdd8b1 100644 --- a/pcr-controller/temp_curve.h +++ b/pcr-controller/temp_curve.h @@ -28,11 +28,11 @@ void tcurve_reset(void); void tcurve_setRepeats(uint8_t r); void tcurve_setRepeatStartPosToLatestEntry(void); +void tcurve_setRepeatEndPosToLatestEntry(void); uint8_t tcurve_isSet(void); uint8_t tcurve_hasFinished(void); uint16_t tcurve_getTimeElapsed(void); uint8_t tcurve_getRepeatsLeft(void); -void tcurve_setPostCycleTargetTemp(int16_t v); void tcurve_add(int16_t temp, uint16_t hold_for_s); int16_t tcurve_getTempToSet(int16_t current_temp, uint16_t time_elapsed); void tcurve_printCurve(void); |