diff --git a/firmware/main.c b/firmware/main.c
index 0632e1b..67ef63a 100644
--- a/firmware/main.c
+++ b/firmware/main.c
@@ -1,18 +1,33 @@
-/** SenseoControl 2.0
+/*****************************************************************************
+ * SenseoControl 2.0 *
+ * Copyright (C) 2013-2018 Stefan Kalscheuer *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see . *
+ *****************************************************************************/
+
+/**
+ * SenseoControl 2.0
*
- * File: main.c
- * Author: Stefan Kalscheuer
- * Date: 22.04.2013
- * Comments: Main program
- * Previous project by Paul Wilhelm (2009) - http://mosfetkiller.de/?s=kaffeecontroller
+ * @file main.c
+ * @author Stefan Kalscheuer
+ * @date 2013-04-22
+ * @brief Main program
*
* Platform: ATtiny26
* Internal RC-oscillator 8 MHz, CKDIV8 Enabled
- *
- * License: GNU GPL v3 (see License.txt)
*/
-#define F_CPU 1000000UL
+#define F_CPU 1000000UL
// includes
#include
@@ -21,400 +36,346 @@
#include
#include "main.h"
- // variables:
-volatile unsigned int time_counter, user_time_counter = 0, sec_counter = 0; // global and universal time counter (ms) and second-counter (for AutoOff)
-volatile unsigned int button_1_cup_counter = 0, button_2_cup_counter = 0; // button counter
+// variables:
+volatile unsigned int time_counter, user_time_counter = 0, sec_counter = 0; // Global and universal time counter (ms) and second-counter (for AutoOff).
+volatile unsigned int button_1_cup_counter = 0, button_2_cup_counter = 0; // Button counter.
volatile unsigned char button_power_counter = 0;
-volatile unsigned char led = 0; // LED status flags
-volatile bool water = false, temperature = false, make_clean = false; // water-, temperature-, clean-flags
-volatile unsigned char make_coffee = 0, pump_time = 0; // pump time, clean mode flag
+volatile unsigned char led = 0; // LED status flags.
+volatile bool water = false, temperature = false, make_clean = false; // Water-, temperature-, clean-flags.
+volatile unsigned char make_coffee = 0, pump_time = 0; // Pump time, clean mode flag.
-int main (void)
-{
- init (); // initialization
- power_off (); // power off after init sequece
+/**
+ * Main program.
+ *
+ * @return This method should never terminate.
+ */
+int main(void) {
+ init(); // Initialization.
+ power_off(); // Power off after init sequece.
- while (1) // main loop
- {
- if (sec_counter >= AUTO_OFF_THRESHOLD)
- button_power_counter = BUTTON_THRESHOLD; // check for AutoOff Timer (generate OnOff-button push)
+ while (1) { // Main loop.
+ if (sec_counter >= AUTO_OFF_THRESHOLD)
+ button_power_counter = BUTTON_THRESHOLD; // Check for AutoOff Timer (generate OnOff-button push).
- water = get_water (); // update water state
- temperature = get_temperature (); // update temperature
+ water = get_water(); // update water state
+ temperature = get_temperature(); // update temperature
- if (button_power_counter >= BUTTON_THRESHOLD) // button "OnOff" pushed:
- {
- set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // Boiler off
- make_coffee = 0; // clear coffee flag
+ if (button_power_counter >= BUTTON_THRESHOLD) { // button "OnOff" pushed:
+ set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // Boiler off
+ make_coffee = 0; // clear coffee flag
- while (button_power_counter > 0)
- ; // wait until button is releasd (debounce)
+ while (button_power_counter >
+ 0); // wait until button is releasd (debounce)
- power_off (); // call power off sequence
+ power_off(); // call power off sequence
- button_power_counter = BUTTON_THRESHOLD; // debounce again after wake up
- while (button_power_counter > 0)
- ;
- }
-
- if (button_1_cup_counter >= BUTTON_CLEAN_THR
- && button_2_cup_counter >= BUTTON_CLEAN_THR) // both coffee buttons pushed: clean mode:
- {
- make_clean = true; // clean flag true
- led = BLUE; // set blue LED
- while (button_1_cup_counter > 0 && button_2_cup_counter > 0)
- ; // debounce buttons
- }
-
- else if (button_1_cup_counter >= BUTTON_THRESHOLD
- && button_2_cup_counter < BUTTON_THRESHOLD) // left coffee button pushed: call espresso
- {
- sec_counter = 0; // reset AutoOff counter
-
- if (water && temperature) // machine ready:
- {
- while (button_1_cup_counter > 0) // check if button is pushed long time
- {
- if (button_1_cup_counter > BUTTON_LONG_THR) // button pushed for a long time:
- {
- make_coffee = 1; // set coffee flag to 1 (1 espresso)
- button_1_cup_counter = 0; // clear button counter
- }
+ button_power_counter = BUTTON_THRESHOLD; // debounce again after wake up
+ while (button_power_counter > 0);
}
- if (make_coffee != 1)
- make_coffee = 3; // set coffee flag to 3 (1 coffee) else
- }
- else if(COFFEE_WISH) { // Save coffee wish
- make_coffee = 3;
- }
- }
- else if (button_1_cup_counter < BUTTON_THRESHOLD
- && button_2_cup_counter >= BUTTON_THRESHOLD) // right coffee button pushed: call coffee
- {
- sec_counter = 0; // reset AutoOff counter
+ if (button_1_cup_counter >= BUTTON_CLEAN_THR && button_2_cup_counter >= BUTTON_CLEAN_THR) {
+ // Both coffee buttons pushed: enter clean mode.
+ make_clean = true; // Set clean flag.
+ led = BLUE; // Set blue LED.
+ while (button_1_cup_counter > 0 && button_2_cup_counter > 0); // Debounce buttons.
+ } else if (button_1_cup_counter >= BUTTON_THRESHOLD && button_2_cup_counter < BUTTON_THRESHOLD) {
+ // Left coffee button pushed: call espresso.
+ sec_counter = 0; // Reset AutoOff counter.
- if (water && temperature) // machine ready:
- {
- while (button_2_cup_counter > 0) // check if button is pushed long time
- {
- if (button_2_cup_counter > BUTTON_LONG_THR) // button pushed for a long time:
- {
- make_coffee = 2; // set coffee flag to 2 (2 espresso)
- button_2_cup_counter = 0; // clear button counter
- }
- }
- if (make_coffee != 2)
- make_coffee = 4; // set coffee flag to 4 (2 coffee) else
- }
- else if(COFFEE_WISH) { // Save coffee wish
- make_coffee = 4;
- }
- }
-
- if (water) // water OK:
- {
- if (make_clean) // if clean-flag is set:
- {
- set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // boiler off
- bool escape = false; // init escape-flag
- while (water && !escape)
- { // pump until water is empty or escape flag is set
-
- unsigned int sense = detect_zero_crossing (); // detect zero crossing
- if (sense <= 100)
- {
- clear_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin); // generate trigger impulse for pump triac
- _delay_ms (3);
- set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin);
- }
- water = get_water (); // update water state
-
- if (button_power_counter > BUTTON_THRESHOLD)
- escape = true; // check for power button counter and set escape flag
- }
- make_clean = false; // clear clean flag
- }
-
- else if (temperature) // temperature OK:
- {
- set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // boiler off
-
- led = GREEN; // set green LED
-
- if (make_coffee > 0) // if coffee flag is set:
- {
- if (make_coffee < 3)
- led = ORANGE_BLINK; // set orange LED blink
- else
- led = GREEN_BLINK; // set green LED blink
-
- if (make_coffee == 1)
- pump_time = TIME_1_ESPRESSO; // 1 cup of espresso (2s preinfusion included)
- else if (make_coffee == 2)
- pump_time = TIME_2_ESPRESSO; // 2 cups of espresso (2s preinfusion included)
- else if (make_coffee == 3)
- pump_time = TIME_1_COFFEE; // 1 cup of coffee
- else if (make_coffee == 4)
- pump_time = TIME_2_COFFEE; // 2 cups of coffee
- else
- make_coffee = 0;
-
- user_time_counter = 0; // reset user time counter
- bool escape = false; // init escape flag
- while (user_time_counter < (pump_time * 1000) && water && !escape)
- { // loop until pump time is reached or water is empty
- if (make_coffee > 2
- || (user_time_counter < 2000 || user_time_counter > 4000))
- { // check for preinfusion break
- unsigned int sense = detect_zero_crossing (); // detect zero crossing
- if (sense <= 100)
- {
- clear_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin); // generate trigger impulse for pump triac
- _delay_ms (3);
- set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin);
- }
+ if (water && temperature) { // Machine ready:
+ while (button_1_cup_counter > 0) { // Check if button is pushed long time.
+ if (button_1_cup_counter > BUTTON_LONG_THR) { // Button pushed for a long time:
+ make_coffee = 1; // Set coffee flag to 1 (1 espresso).
+ button_1_cup_counter = 0; // Clear button counter.
+ }
+ }
+ if (make_coffee != 1) {
+ make_coffee = 3; // Set coffee flag to 3 (1 coffee) otherwise.
+ }
+ } else if (COFFEE_WISH) { // Save coffee wish.
+ make_coffee = 3;
}
+ } else if (button_1_cup_counter < BUTTON_THRESHOLD && button_2_cup_counter >= BUTTON_THRESHOLD) {
+ // Right coffee button pushed: call coffee.
+ sec_counter = 0; // Reset AutoOff counter.
- water = get_water (); // update water state
-
- if (button_power_counter > BUTTON_THRESHOLD)
- escape = true; // check for power button counter and set escape flag
- }
-
- set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin); // pump off
-
- make_coffee = 0; // clear coffee flag
-
- sec_counter = 0; // reset AutoOff timer
+ if (water && temperature) { // machine ready:
+ while (button_2_cup_counter > 0) { // Check if button is pushed long time.
+ if (button_2_cup_counter > BUTTON_LONG_THR) { // Button pushed for a long time:
+ make_coffee = 2; // Set coffee flag to 2 (2 espresso).
+ button_2_cup_counter = 0; // Clear button counter.
+ }
+ }
+ if (make_coffee != 2) {
+ make_coffee = 4; // Set coffee flag to 4 (2 coffee) otherwise.
+ }
+ } else if (COFFEE_WISH) { // Save coffee wish
+ make_coffee = 4;
+ }
}
- }
- else // temperature too low:
- {
- clear_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // boiler on
- if (make_coffee > 0) // set red/blue LED blink if coffee wish is saved
- led = VIOLET_BLINK;
- else // set red LED blink if no coffee wish is saved
- led = RED_BLINK;
- }
- }
- else // water too low:
- {
- set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // boiler off
- set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin); // pump off
- led = BLUE_BLINK; // set blue LED blink
- }
+ if (water) { // Water OK:
+ if (make_clean) { // If clean-flag is set:
+ set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // Boiler off.
+ bool escape = false; // Init escape-flag.
+ while (water && !escape) { // Pump until water is empty or escape flag is set.
+ unsigned int sense = detect_zero_crossing(); // Detect zero crossing.
+ if (sense <= 100) {
+ clear_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin); // Generate trigger impulse for pump triac.
+ _delay_ms(3);
+ set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin);
+ }
+ water = get_water(); // Update water state.
- }
+ if (button_power_counter > BUTTON_THRESHOLD)
+ escape = true; // Check power button counter and set escape flag.
+ }
+ make_clean = false; // Clear clean flag.
+ } else if (temperature) { // Temperature OK:
+ set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // Boiler off.
+
+ led = GREEN; // Set green LED.
+
+ if (make_coffee > 0) { // If coffee flag is set:
+ if (make_coffee < 3) {
+ led = ORANGE_BLINK; // Set orange LED blink for espresso.
+ } else {
+ led = GREEN_BLINK; // Set green LED blink for coffee.
+ }
+
+ if (make_coffee == 1) {
+ pump_time = TIME_1_ESPRESSO; // 1 cup of espresso (2s preinfusion included).
+ } else if (make_coffee == 2) {
+ pump_time = TIME_2_ESPRESSO; // 2 cups of espresso (2s preinfusion included).
+ } else if (make_coffee == 3) {
+ pump_time = TIME_1_COFFEE; // 1 cup of coffee.
+ } else if (make_coffee == 4) {
+ pump_time = TIME_2_COFFEE; // 2 cups of coffee.
+ } else {
+ make_coffee = 0;
+ }
+
+ user_time_counter = 0; // Reset user time counter.
+ bool escape = false; // Init escape flag.
+
+ // loop until pump time is reached or water is empty
+ while (user_time_counter < (pump_time * 1000) && water && !escape) {
+ // Check for preinfusion break.
+ if (make_coffee > 2 || (user_time_counter < 2000 || user_time_counter > 4000)) {
+ unsigned int sense = detect_zero_crossing(); // Detect zero crossing.
+ if (sense <= 100) {
+ clear_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin); // Generate trigger impulse for pump triac.
+ _delay_ms(3);
+ set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin);
+ }
+ }
+
+ water = get_water(); // Update water state.
+
+ if (button_power_counter > BUTTON_THRESHOLD) {
+ escape = true; // Check for power button counter and set escape flag.
+ }
+ }
+
+ set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin); // Pump off
+ make_coffee = 0; // Clear coffee flag.
+ sec_counter = 0; // Reset AutoOff timer.
+ }
+ } else { // Temperature too low.
+ clear_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // Boiler on.
+ if (make_coffee > 0) { // Set red/blue LED blink if coffee wish is saved.
+ led = VIOLET_BLINK;
+ } else { // Set red LED blink if no coffee wish is saved.
+ led = RED_BLINK;
+ }
+ }
+ } else { // Water too low:
+ set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // Boiler off.
+ set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin); // Pump off.
+ led = BLUE_BLINK; // Set blue LED blink.
+ }
+ }
}
-/* function: init()
- * return: void
- *
+/**
* Initializes relevant bits, timer and ADC.
*/
-void init ()
-{
- clear_bit(ZERO_CROSSING_ddr, ZERO_CROSSING_pin); // zero crossing dection pins as input
- clear_bit(ZERO_CROSSING_w, ZERO_CROSSING_pin); // no internal pull-up (for ADC)
+void init() {
+ clear_bit(ZERO_CROSSING_ddr, ZERO_CROSSING_pin); // Zero crossing dection pins as input-
+ clear_bit(ZERO_CROSSING_w, ZERO_CROSSING_pin); // No internal pull-up (for ADC).
- clear_bit(BUTTON_1_CUP_ddr, BUTTON_1_CUP_pin); // button pins as input
- set_bit(BUTTON_1_CUP_w, BUTTON_1_CUP_pin); // activate internal pull-ups
- clear_bit(BUTTON_2_CUP_ddr, BUTTON_2_CUP_pin);
- set_bit(BUTTON_2_CUP_w, BUTTON_2_CUP_pin);
- clear_bit(BUTTON_POWER_ddr, BUTTON_POWER_pin);
- set_bit(BUTTON_POWER_w, BUTTON_POWER_pin);
+ clear_bit(BUTTON_1_CUP_ddr, BUTTON_1_CUP_pin); // Button pins as input.
+ set_bit(BUTTON_1_CUP_w, BUTTON_1_CUP_pin); // Activate internal pull-ups.
+ clear_bit(BUTTON_2_CUP_ddr, BUTTON_2_CUP_pin);
+ set_bit(BUTTON_2_CUP_w, BUTTON_2_CUP_pin);
+ clear_bit(BUTTON_POWER_ddr, BUTTON_POWER_pin);
+ set_bit(BUTTON_POWER_w, BUTTON_POWER_pin);
- set_bit(LED_RED_ddr, LED_RED_pin); // LED pins as output
- clear_bit(LED_RED_w, LED_RED_pin); // clear outputs (LEDs off)
- set_bit(LED_GREEN_ddr, LED_GREEN_pin);
- clear_bit(LED_GREEN_w, LED_GREEN_pin);
- set_bit(LED_BLUE_ddr, LED_BLUE_pin);
- clear_bit(LED_BLUE_w, LED_BLUE_pin);
-
- clear_bit(SENSOR_MAGNET_ddr, SENSOR_MAGNET_pin); // sensor pins as input
- clear_bit(SENSOR_MAGNET_w, SENSOR_MAGNET_pin); // no internal pull-up (for ADC)
- clear_bit(SENSOR_TEMP_ddr, SENSOR_TEMP_pin);
- clear_bit(SENSOR_TEMP_w, SENSOR_TEMP_pin);
-
- set_bit(TRIAC_BOILER_ddr, TRIAC_BOILER_pin); // triac pins as output
- set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // set outputs high (triac off)
- set_bit(TRIAC_PUMP_ddr, TRIAC_PUMP_pin);
- set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin);
-
- ADCSR = (1 << ADEN) | (1 << ADPS1); // enable ADC, prescaler division factor 4
-
- // TIMER1
- set_bit(TCCR1B, CTC1); // set timer 1 to CTC-Mode
- clear_bit(TCCR1B, CS11); // prescaler 8
- set_bit(TCCR1B, CS12);
- clear_bit(TCCR1B, CS11);
- clear_bit(TCCR1B, CS10);
- OCR1C = 124; // period of 1 ms
-
- cli (); // disable interrupts
-
- clear_bit(GIMSK, INT0); // disable interrupt 0
-
- set_bit(TIMSK, TOIE1); // activate timer 1
-
- sei (); // enable interrupts
-}
-
-/* function: power_off()
- * return: void
- *
- * Clear bits and set controller to sleep mode.
- */
-void power_off ()
-{
- cli (); // disable interrupts
- set_bit(GIMSK, INT0); // activate interrupt 0 (for wake-up)
- clear_bit(TIMSK, TOIE1); // deactivate timer 1
- sei (); // enable interrupts
-
- clear_bit(LED_RED_w, LED_RED_pin); // clear LED outputs
- clear_bit(LED_GREEN_w, LED_GREEN_pin);
- clear_bit(LED_BLUE_w, LED_BLUE_pin);
-
- set_bit(MCUCR, SM1); // activate power-down mode
- clear_bit(MCUCR, SM0);
- set_bit(MCUCR, SE);
- asm volatile("sleep"::);
-
- // entrance after wake-up:
- time_counter = 0; // reset counter
- sec_counter = 0;
- cli (); // disable interrupts
- clear_bit(GIMSK, INT0); // disable interrupt 0
- set_bit(TIMSK, TOIE1); // enable timer 1
- sei (); // enable interrupts
-}
-
-/* function: get_water()
- * return: true water OK
- * false not enough water
- *
- * Checks hall sensor for water state.
- */
-bool get_water ()
-{
- ADMUX = SENSOR_MAGNET_adc | (1 << ADLAR); // ADLAR
- set_bit(ADCSR, ADSC);
- loop_until_bit_is_clear (ADCSR, ADSC);
- unsigned char sense = ADCH;
- if ((water && sense > WATER_LOW) || (!water && sense >= WATER_OK))
- return true;
- return false;
-}
-
-/* function: get_temperature()
- * return: true temperature OK
- * false temperature too low
- *
- * Checks NTC sensor for temperature state.
- */
-bool get_temperature ()
-{
- ADMUX = SENSOR_TEMP_adc | (1 << ADLAR); // ADLAR
- set_bit(ADCSR, ADSC);
- loop_until_bit_is_clear (ADCSR, ADSC);
- unsigned char sense = ADCH;
- if (sense >= OPERATING_TEMPERATURE)
- return true;
- return false;
-}
-
-/* function: detect_zero_crossing()
- * return: unsigned int ADC value
- *
- * Checks for zero crossing (with fixed offset)
- */
-unsigned int detect_zero_crossing ()
-{
- ADMUX = ZERO_CROSSING_adc;
- set_bit(ADCSR, ADSC);
- loop_until_bit_is_clear (ADCSR, ADSC);
- unsigned char sense_L = ADCL;
- unsigned char sense_H = ADCH;
- return (sense_H << 8) | sense_L;
-}
-
-/* interrupt function: INT0_vect
- *
- * Dummy function for wake-up.
- */
-ISR ( INT0_vect)
-{
-}
-
-/* interrupt function: TIMER1_OVF1_vect
- *
- * Timer interrupt. Increments counters and controls LED.
- */
-ISR ( TIMER1_OVF1_vect)
-{
- if (time_counter < 1000)
- time_counter++; // global milliseconds counter and seconds counter (for AutoOff)
- else
- {
- time_counter = 0;
- sec_counter++;
- }
- user_time_counter++; // universal counter (for pump time)
-
- bool leds_blink_on; // status flag for blinking LEDs with 1Hz
- if (time_counter < 499)
- leds_blink_on = true;
- else
- leds_blink_on = false;
-
- if (led & (1 << LED_RED_ON) || (led & (1 << LED_RED_BLINK) && leds_blink_on))
- set_bit(LED_RED_w, LED_RED_pin);
- else
- clear_bit(LED_RED_w, LED_RED_pin);
- if (led & (1 << LED_GREEN_ON)
- || (led & (1 << LED_GREEN_BLINK) && leds_blink_on))
- set_bit(LED_GREEN_w, LED_GREEN_pin);
- else
+ set_bit(LED_RED_ddr, LED_RED_pin); // LED pins as output.
+ clear_bit(LED_RED_w, LED_RED_pin); // Clear outputs (LEDs off).
+ set_bit(LED_GREEN_ddr, LED_GREEN_pin);
clear_bit(LED_GREEN_w, LED_GREEN_pin);
- if (led & (1 << LED_BLUE_ON)
- || (led & (1 << LED_BLUE_BLINK) && leds_blink_on))
- set_bit(LED_BLUE_w, LED_BLUE_pin);
- else
+ set_bit(LED_BLUE_ddr, LED_BLUE_pin);
clear_bit(LED_BLUE_w, LED_BLUE_pin);
- if (bit_is_clear (BUTTON_1_CUP_r, BUTTON_1_CUP_pin))
- { // left button counter
- if (button_1_cup_counter < 65535)
- button_1_cup_counter++;
- }
- else
- {
- if (button_1_cup_counter > 0)
- button_1_cup_counter--;
- }
+ clear_bit(SENSOR_MAGNET_ddr, SENSOR_MAGNET_pin); // Sensor pins as input.
+ clear_bit(SENSOR_MAGNET_w, SENSOR_MAGNET_pin); // No internal pull-up (for ADC).
+ clear_bit(SENSOR_TEMP_ddr, SENSOR_TEMP_pin);
+ clear_bit(SENSOR_TEMP_w, SENSOR_TEMP_pin);
- if (bit_is_clear (BUTTON_2_CUP_r, BUTTON_2_CUP_pin))
- { // right button counter
- if (button_2_cup_counter < 65535)
- button_2_cup_counter++;
- }
- else
- {
- if (button_2_cup_counter > 0)
- button_2_cup_counter--;
- }
+ set_bit(TRIAC_BOILER_ddr, TRIAC_BOILER_pin); // Triac pins as output.
+ set_bit(TRIAC_BOILER_w, TRIAC_BOILER_pin); // Set outputs high (triac off).
+ set_bit(TRIAC_PUMP_ddr, TRIAC_PUMP_pin);
+ set_bit(TRIAC_PUMP_w, TRIAC_PUMP_pin);
- if (bit_is_clear (BUTTON_POWER_r, BUTTON_POWER_pin))
- { // power button counter
- if (button_power_counter < 255)
- button_power_counter++;
- }
- else
- {
- if (button_power_counter > 0)
- button_power_counter--;
- }
+ ADCSR = (1 << ADEN) | (1 << ADPS1); // Enable ADC, prescaler division factor 4.
+
+ // TIMER1
+ set_bit(TCCR1B, CTC1); // Set timer 1 to CTC-Mode.
+ clear_bit(TCCR1B, CS11); // Prescaler 8.
+ set_bit(TCCR1B, CS12);
+ clear_bit(TCCR1B, CS11);
+ clear_bit(TCCR1B, CS10);
+ OCR1C = 124; // Period of 1 ms.
+
+ cli(); // Disable interrupts.
+ clear_bit(GIMSK, INT0); // Disable interrupt 0.
+ set_bit(TIMSK, TOIE1); // Activate timer 1.
+ sei(); // Enable interrupts.
+}
+
+/**
+ * Clear bits and set controller to sleep mode.
+ */
+void power_off() {
+ cli(); // Disable interrupts.
+ set_bit(GIMSK, INT0); // Activate interrupt 0 (for wake-up).
+ clear_bit(TIMSK, TOIE1); // Deactivate timer 1.
+ sei(); // Re-enable interrupts.
+
+ clear_bit(LED_RED_w, LED_RED_pin); // Clear LED outputs.
+ clear_bit(LED_GREEN_w, LED_GREEN_pin);
+ clear_bit(LED_BLUE_w, LED_BLUE_pin);
+
+ set_bit(MCUCR, SM1); // Activate power-down mode.
+ clear_bit(MCUCR, SM0);
+ set_bit(MCUCR, SE);
+ asm volatile("sleep"::);
+
+ // Entrance point after wake-up.
+ time_counter = 0; // Reset counter.
+ sec_counter = 0;
+ cli(); // Disable interrupts.
+ clear_bit(GIMSK, INT0); // Disable interrupt 0.
+ set_bit(TIMSK, TOIE1); // Enable timer 1.
+ sei(); // Re-enable interrupts.
+}
+
+/**
+ * Checks hall sensor for water level.
+ *
+ * @return @c true if water level is OK, @c false otherwise.
+ */
+bool get_water() {
+ ADMUX = SENSOR_MAGNET_adc | (1 << ADLAR);
+ set_bit(ADCSR, ADSC);
+ loop_until_bit_is_clear(ADCSR, ADSC);
+ unsigned char sense = ADCH;
+ if ((water && sense > WATER_LOW) || (!water && sense >= WATER_OK))
+ return true;
+ return false;
+}
+
+/**
+ * Checks NTC sensor for temperature state.
+ *
+ * @return @c true if temperature is OK, @c false if it is too low
+ */
+bool get_temperature() {
+ ADMUX = SENSOR_TEMP_adc | (1 << ADLAR);
+ set_bit(ADCSR, ADSC);
+ loop_until_bit_is_clear(ADCSR, ADSC);
+ unsigned char sense = ADCH;
+ if (sense >= OPERATING_TEMPERATURE)
+ return true;
+ return false;
+}
+
+/**
+ * Checks for zero crossing (with fixed offset)
+ *
+ * @return Raw ADC value.
+ */
+unsigned int detect_zero_crossing() {
+ ADMUX = ZERO_CROSSING_adc;
+ set_bit(ADCSR, ADSC);
+ loop_until_bit_is_clear(ADCSR, ADSC);
+ unsigned char sense_L = ADCL;
+ unsigned char sense_H = ADCH;
+ return (sense_H << 8) | sense_L;
+}
+
+/**
+ * Dummy function for wake-up.
+ */
+ISR ( INT0_vect) {
+ // Nothing to do here.
+}
+
+/**
+ * Timer interrupt. Increments counters and controls LED.
+ */
+ISR ( TIMER1_OVF1_vect) {
+ if (time_counter < 1000)
+ time_counter++; // Global milliseconds counter and seconds counter (for AutoOff).
+ else {
+ time_counter = 0;
+ sec_counter++;
+ }
+ user_time_counter++; // Universal counter (for pump time).
+
+ bool leds_blink_on; // Status flag for blinking LEDs with 1Hz.
+ if (time_counter < 499)
+ leds_blink_on = true;
+ else
+ leds_blink_on = false;
+
+ if (led & (1 << LED_RED_ON) || (led & (1 << LED_RED_BLINK) && leds_blink_on))
+ set_bit(LED_RED_w, LED_RED_pin);
+ else
+ clear_bit(LED_RED_w, LED_RED_pin);
+ if (led & (1 << LED_GREEN_ON)
+ || (led & (1 << LED_GREEN_BLINK) && leds_blink_on))
+ set_bit(LED_GREEN_w, LED_GREEN_pin);
+ else
+ clear_bit(LED_GREEN_w, LED_GREEN_pin);
+ if (led & (1 << LED_BLUE_ON)
+ || (led & (1 << LED_BLUE_BLINK) && leds_blink_on))
+ set_bit(LED_BLUE_w, LED_BLUE_pin);
+ else
+ clear_bit(LED_BLUE_w, LED_BLUE_pin);
+
+ if (bit_is_clear(BUTTON_1_CUP_r, BUTTON_1_CUP_pin)) { // Left button counter.
+ if (button_1_cup_counter < 65535)
+ button_1_cup_counter++;
+ } else {
+ if (button_1_cup_counter > 0)
+ button_1_cup_counter--;
+ }
+
+ if (bit_is_clear(BUTTON_2_CUP_r, BUTTON_2_CUP_pin)) { // Right button counter.
+ if (button_2_cup_counter < 65535)
+ button_2_cup_counter++;
+ } else {
+ if (button_2_cup_counter > 0)
+ button_2_cup_counter--;
+ }
+
+ if (bit_is_clear(BUTTON_POWER_r, BUTTON_POWER_pin)) { // Power button counter.
+ if (button_power_counter < 255)
+ button_power_counter++;
+ } else {
+ if (button_power_counter > 0)
+ button_power_counter--;
+ }
}
diff --git a/firmware/main.h b/firmware/main.h
index 0535ec3..547f115 100644
--- a/firmware/main.h
+++ b/firmware/main.h
@@ -1,79 +1,94 @@
-/** SenseoControl 2.0
+/*****************************************************************************
+ * SenseoControl 2.0 *
+ * Copyright (C) 2013-2018 Stefan Kalscheuer *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see . *
+ *****************************************************************************/
+
+/**
+ * SenseoControl 2.0
*
- * File: main.h
- * Author: Stefan Kalscheuer
- * Date: 22.04.2013
- *
- * License: GNU GPL v3 (see License.txt)
+ * @file main.h
+ * @author Stefan Kalscheuer
+ * @date 2013-04-22
*/
-/*******************
- * USER SETTINGS
+/********************
+ * User settings:
*/
-#define TIME_1_ESPRESSO 15 // pump times in seconds
+#define TIME_1_ESPRESSO 15 // Pump times in seconds.
#define TIME_2_ESPRESSO 28
#define TIME_1_COFFEE 26
#define TIME_2_COFFEE 52
-#define OPERATING_TEMPERATURE 125 // ADC threshold for water temperature
-#define COFFEE_WISH 0 // save coffee wish while heating up
+#define OPERATING_TEMPERATURE 125 // ADC threshold for water temperature.
+#define COFFEE_WISH 0 // Save coffee wish while heating up.
/*
- *******************
- */
+ ********************/
-// functions for setting and clearing bits
-#define set_bit(var, bit) ((var) |= (1 << (bit)))
-#define clear_bit(var, bit) ((var) &= (unsigned)~(1 << (bit)))
+// Function macros for setting and clearing bits.
+#define set_bit(var, bit) ((var) |= (1 << (bit)))
+#define clear_bit(var, bit) ((var) &= (unsigned)~(1 << (bit)))
-#define ZERO_CROSSING_w PORTA // zero crossing detection
+#define ZERO_CROSSING_w PORTA // Zero crossing detection.
#define ZERO_CROSSING_r PINA
#define ZERO_CROSSING_pin 0
#define ZERO_CROSSING_ddr DDRA
#define ZERO_CROSSING_adc 0
-#define BUTTON_1_CUP_w PORTB // left button
+#define BUTTON_1_CUP_w PORTB // Left button.
#define BUTTON_1_CUP_r PINB
#define BUTTON_1_CUP_pin 4
#define BUTTON_1_CUP_ddr DDRB
-#define BUTTON_2_CUP_w PORTB // right button
+#define BUTTON_2_CUP_w PORTB // Right button.
#define BUTTON_2_CUP_r PINB
#define BUTTON_2_CUP_pin 5
#define BUTTON_2_CUP_ddr DDRB
-#define BUTTON_POWER_w PORTB // power button
+#define BUTTON_POWER_w PORTB // Power button.
#define BUTTON_POWER_r PINB
#define BUTTON_POWER_pin 6
#define BUTTON_POWER_ddr DDRB
-#define LED_RED_w PORTA // red LED
+#define LED_RED_w PORTA // Red LED.
#define LED_RED_r PINA
#define LED_RED_pin 3
#define LED_RED_ddr DDRA
#define LED_RED_ON 0
#define LED_RED_BLINK 1
-#define LED_GREEN_w PORTA // green LED
-#define LED_GREEN_r PINA
+#define LED_GREEN_w PORTA // Green LED.
+#define LED_GREEN_r PINA
#define LED_GREEN_pin 1
#define LED_GREEN_ddr DDRA
#define LED_GREEN_ON 2
#define LED_GREEN_BLINK 3
-#define LED_BLUE_w PORTA // blue LED
+#define LED_BLUE_w PORTA // Blue LED.
#define LED_BLUE_r PINA
#define LED_BLUE_pin 2
#define LED_BLUE_ddr DDRA
#define LED_BLUE_ON 4
#define LED_BLUE_BLINK 5
-#define SENSOR_MAGNET_w PORTA // hall switch (water)
+#define SENSOR_MAGNET_w PORTA // Hall switch (water).
#define SENSOR_MAGNET_r PINA
#define SENSOR_MAGNET_pin 5
#define SENSOR_MAGNET_ddr DDRA
#define SENSOR_MAGNET_adc 4
-#define WATER_LOW 30 // ADC threshold for low water
-#define WATER_OK 100 // ADC threshold for water OK
+#define WATER_LOW 30 // ADC threshold for low water.
+#define WATER_OK 100 // ADC threshold for water OK.
#define SENSOR_TEMP_w PORTA // NTC (temperature)
#define SENSOR_TEMP_r PINA
@@ -81,20 +96,20 @@
#define SENSOR_TEMP_ddr DDRA
#define SENSOR_TEMP_adc 3
-#define TRIAC_BOILER_w PORTA // boiler triac
+#define TRIAC_BOILER_w PORTA // Boiler triac.
#define TRIAC_BOILER_r PINA
#define TRIAC_BOILER_pin 6
#define TRIAC_BOILER_ddr DDRA
-#define TRIAC_PUMP_w PORTA // pump triac
+#define TRIAC_PUMP_w PORTA // Pump triac.
#define TRIAC_PUMP_r PINA
#define TRIAC_PUMP_pin 7
#define TRIAC_PUMP_ddr DDRA
-#define AUTO_OFF_THRESHOLD 180 // AutoOff threshold (seconds)
-#define BUTTON_CLEAN_THR 30 // button threshold for cleaning mode (ms)
-#define BUTTON_THRESHOLD 100 // button threshold (ms)
-#define BUTTON_LONG_THR 1500 // button threshold for long time push (ms)
+#define AUTO_OFF_THRESHOLD 180 // AutoOff threshold (seconds).
+#define BUTTON_CLEAN_THR 30 // Button threshold for cleaning mode (ms).
+#define BUTTON_THRESHOLD 100 // Button threshold (ms).
+#define BUTTON_LONG_THR 1500 // Button threshold for long time push (ms).
#define RED 0b00000001
#define RED_BLINK 0b00000010
@@ -107,9 +122,9 @@
#define VIOLET 0b00010001
#define VIOLET_BLINK 0b00100010
- // prototypes:
-void init (); // initialization
-void power_off (); // power off to sleep mode
-bool get_water (); // update water state
-bool get_temperature (); // update tehmerature state
-unsigned int detect_zero_crossing (); // detect zero crossing
+// Prototypes:
+void init(); // Initialization.
+void power_off(); // Power off to sleep mode.
+bool get_water(); // Update water state.
+bool get_temperature(); // Update tehmerature state.
+unsigned int detect_zero_crossing(); // Detect zero crossing.