summaryrefslogtreecommitdiff
path: root/controller.c
diff options
context:
space:
mode:
Diffstat (limited to 'controller.c')
-rw-r--r--controller.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/controller.c b/controller.c
new file mode 100644
index 0000000..29ac0ab
--- /dev/null
+++ b/controller.c
@@ -0,0 +1,105 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+#include "controller.h"
+
+#include "bridge.h"
+
+static void adc_init(void)
+{
+ /* Configure the ADC */
+ ADMUX = (1 << REFS1) | (1 << REFS0);
+ /* select channel x (0 for now) */
+ ADMUX |= 0x0;
+ ADCSRA = (1 << ADEN) | (1 << ADIE)
+ | (1 << ADPS2) | (1 << ADPS1)
+ | (1 << ADPS0);
+}
+
+/* Initializes TIMER1 */
+static void timer_init(void)
+{
+ TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10);
+ OCR1A = 7200;
+ TIMSK|=(1<<OCIE1A);
+}
+
+static volatile char controller_in_init;
+static volatile char controller_active;
+static volatile long controller_target_temp;
+static volatile char controller_num_iterations;
+static volatile uint16_t controller_measured_temp;
+
+void controller_init(void)
+{
+ controller_active = 0;
+ controller_in_init = 1;
+
+ bridge_init();
+ adc_init();
+ timer_init();
+}
+
+int controller_set(long target)
+{
+ if (target < 50 || target > 974)
+ return 1;
+
+ controller_target_temp = target;
+ controller_num_iterations = 1;
+ controller_active = 1;
+ return 0;
+}
+
+long controller_get(void)
+{
+ return controller_measured_temp;
+}
+
+void controller_off(void)
+{
+ controller_active = 0;
+ bridge_off();
+}
+
+ISR(TIMER1_COMPA_vect)
+{
+ /* Start adc measurement */
+ ADCSRA |= (1<<ADSC);
+}
+
+ISR(ADC_vect)
+{
+ if (controller_in_init) {
+ controller_measured_temp = ADCW;
+ controller_in_init = 0;
+ } else {
+ controller_measured_temp = (0.8 * controller_measured_temp)
+ + (0.2 * ADCW);
+ }
+
+ if (! controller_active)
+ return;
+
+ controller_num_iterations--;
+ if (controller_num_iterations)
+ return;
+
+ controller_num_iterations = 60;
+
+ if ((long)controller_measured_temp < controller_target_temp - 20) {
+ /* Cooling required */
+ bridge_on_cool();
+ return;
+ }
+
+ if ((long)controller_measured_temp > controller_target_temp + 20) {
+ /* Heating required */
+ bridge_on_heat();
+ return;
+ }
+
+ /* Temperature is roughly okay, turn bridge off until next
+ * measurement. */
+ bridge_off();
+}