Initial version of firmware
This commit is contained in:
		
						commit
						695aa4b3c2
					
				
							
								
								
									
										1
									
								
								barista/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								barista/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | build/ | ||||||
							
								
								
									
										17
									
								
								barista/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								barista/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | PORT=/dev/ttyUSB0 | ||||||
|  | FQBN=arduino:avr:atmega328bb | ||||||
|  | OPTS=--no-color --log-level=info -v | ||||||
|  | PROJ=barista | ||||||
|  | BUILD=build/$(subst :,.,$(FQBN)) | ||||||
|  | HEX=$(BUILD)/$(PROJ).ino.hex | ||||||
|  | 
 | ||||||
|  | all: $(HEX) | ||||||
|  | 
 | ||||||
|  | $(HEX): barista.ino | ||||||
|  | 	arduino-cli compile $(OPTS) -e --fqbn $(FQBN) | ||||||
|  | 
 | ||||||
|  | upload: $(HEX) | ||||||
|  | 	avrdude -vv -p atmega328p -c arduino -P $(PORT) -b 9600 -D -U flash:w:$(HEX):i | ||||||
|  | 
 | ||||||
|  | serial: | ||||||
|  | 	picocom -b 115200 --lower-rts --lower-dtr /dev/ttyUSB0 --imap lfcrlf | ||||||
							
								
								
									
										351
									
								
								barista/barista.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										351
									
								
								barista/barista.ino
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,351 @@ | |||||||
|  | /* Copyright (c) 2025 Rodrigo Arias Mallo <rodarima@gmail.com>
 | ||||||
|  |  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *                             ATmega328p | ||||||
|  |  *                            +---------+ | ||||||
|  |  *  (PCINT14/RESET)      PC6 -|1  \_/ 28|- PC5 (ADC5/SCL/PCINT13) | ||||||
|  |  *  (PCINT16/RXD)        PD0 -|2      27|- PC4 (ADC4/SDA/PCINT12) | ||||||
|  |  *  (PCINT17/TXD)        PD1 -|3      26|- PC3 (ADC3/PCINT11) | ||||||
|  |  *  (PCINT18/INT0)       PD2 -|4      25|- PC2 (ADC2/PCINT10) | ||||||
|  |  *  (PCINT19/OC2B/INT1)  PD3 -|5      24|- PC1 (ADC1/PCINT9) | ||||||
|  |  *  (PCINT20/XCK/T0)     PD4 -|6      23|- PC0 (ADC0/PCINT8) | ||||||
|  |  *  VCC                      -|7      22|-     GND | ||||||
|  |  *  GND                      -|8      21|-     AREF | ||||||
|  |  *  (PCINT6/XTAL1/TOSC1) PB6 -|9      20|-     AVCC | ||||||
|  |  *  (PCINT7/XTAL2/TOSC2) PB7 -|10     19|- PB5 (SCK/PCINT5) | ||||||
|  |  *  (PCINT21/OC0B/T1)    PD5 -|11     18|- PB4 (MISO/PCINT4) | ||||||
|  |  *  (PCINT22/OC0A/AIN0)  PD6 -|12     17|- PB3 (MOSI/OC2A/PCINT3) | ||||||
|  |  *  (PCINT23/AIN1)       PD7 -|13     16|- PB2 (SS/OC1B/PCINT2) | ||||||
|  |  *  (PCINT0/CLKO/ICP1)   PB0 -|14     15|- PB1 (OC1A/PCINT1) | ||||||
|  |  *                            +---------+ | ||||||
|  |  * | ||||||
|  |  *  | ||||||
|  |  *         ATMEL ATMEGA8 & 168 / ARDUINO | ||||||
|  |  * | ||||||
|  |  *                          +-\/-+ | ||||||
|  |  *                    PC6  1|    |28  PC5 (AI 5) | ||||||
|  |  *              (D 0) PD0  2|    |27  PC4 (AI 4) | ||||||
|  |  *              (D 1) PD1  3|    |26  PC3 (AI 3) | ||||||
|  |  *              (D 2) PD2  4|    |25  PC2 (AI 2) | ||||||
|  |  *         PWM+ (D 3) PD3  5|    |24  PC1 (AI 1) | ||||||
|  |  *              (D 4) PD4  6|    |23  PC0 (AI 0) | ||||||
|  |  *                    VCC  7|    |22  GND | ||||||
|  |  *                    GND  8|    |21  AREF | ||||||
|  |  *                    PB6  9|    |20  AVCC | ||||||
|  |  *                    PB7 10|    |19  PB5 (D 13) | ||||||
|  |  *         PWM+ (D 5) PD5 11|    |18  PB4 (D 12) | ||||||
|  |  *         PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM | ||||||
|  |  *              (D 7) PD7 13|    |16  PB2 (D 10) PWM | ||||||
|  |  *              (D 8) PB0 14|    |15  PB1 (D 9) PWM | ||||||
|  |  *                          +----+ | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | enum pinout { | ||||||
|  | 	/* Inputs */ | ||||||
|  | 	PIN_POWER_ON  = 8, | ||||||
|  | 	PIN_HOT       = 9, | ||||||
|  | 	//PIN_FLOW      = PIN_D5,
 | ||||||
|  | 
 | ||||||
|  | 	/* Outputs */ | ||||||
|  | 	PIN_LED_GREEN = 5, | ||||||
|  | 	PIN_LED_RED   = 6, | ||||||
|  | 	PIN_HEAT      = 7, | ||||||
|  | 	PIN_PUMP      = 12, | ||||||
|  | 	PIN_BUZZ      = 10, | ||||||
|  | 
 | ||||||
|  | 	/* Analog */ | ||||||
|  | 	PIN_NTC       = PIN_A0, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum logic { | ||||||
|  | 	ON = 1, | ||||||
|  | 	OFF = 0, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define DEBOUNCE_TIME 20L /* ms */ | ||||||
|  | #define TEMP_MIN 600 | ||||||
|  | #define TEMP_MAX 700 | ||||||
|  | 
 | ||||||
|  | #define LED_MIN_VALUE 0 | ||||||
|  | 
 | ||||||
|  | enum state { | ||||||
|  | 	SLEEPING, | ||||||
|  | 	DEBOUNCE, | ||||||
|  | 	HEATING, | ||||||
|  | 	HOT, | ||||||
|  | 	BREWING, | ||||||
|  | 	COOLING, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | long debounce_t0 = 0; | ||||||
|  | int state = SLEEPING; | ||||||
|  | 
 | ||||||
|  | enum button { | ||||||
|  | 	BUTTON_ON = 0, | ||||||
|  | 	BUTTON_HOT, | ||||||
|  | 	MAX_BUTTON, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum button_state { | ||||||
|  | 	RESTING = 0, | ||||||
|  | 	PRESSING, | ||||||
|  | 	PRESSED, | ||||||
|  | 	RELEASING, | ||||||
|  | 	RELEASED, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum buzz_state { | ||||||
|  |   BUZZ_OFF = 0, | ||||||
|  |   BUZZ_HEY, | ||||||
|  |   BUZZ_STOP, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | int buzz_state; | ||||||
|  | 
 | ||||||
|  | int button_pin[MAX_BUTTON] = { | ||||||
|  | 	[BUTTON_ON] = PIN_POWER_ON, | ||||||
|  | 	[BUTTON_HOT] = PIN_HOT, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | int button_state[MAX_BUTTON]; | ||||||
|  | unsigned long button_press_t0[MAX_BUTTON]; | ||||||
|  | unsigned long button_release_t0[MAX_BUTTON]; | ||||||
|  | 
 | ||||||
|  | int read_input(int pin) | ||||||
|  | { | ||||||
|  | 	return !digitalRead(pin); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void relay(int pin, enum logic st) | ||||||
|  | { | ||||||
|  |   /* Relays are active low */ | ||||||
|  |   if (st == ON) | ||||||
|  |     digitalWrite(pin, 0); | ||||||
|  |   else | ||||||
|  |     digitalWrite(pin, 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void setled(int pin, enum logic st) | ||||||
|  | { | ||||||
|  |   /* LEDs are active high */ | ||||||
|  |   if (st == ON) | ||||||
|  |     digitalWrite(pin, 1); | ||||||
|  |   else | ||||||
|  |     digitalWrite(pin, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void update_buttons() | ||||||
|  | { | ||||||
|  | 	for (int i = 0; i < MAX_BUTTON; i++) { | ||||||
|  | 		int st = button_state[i]; | ||||||
|  | 		int pin = button_pin[i]; | ||||||
|  | 		if (st == RESTING) { | ||||||
|  | 			if (read_input(pin) == ON) { | ||||||
|  | 				button_state[i] = PRESSING; | ||||||
|  | 				button_press_t0[i] = millis(); | ||||||
|  | 			} | ||||||
|  | 		} else if (st == PRESSING) { | ||||||
|  | 			if (read_input(pin) != ON) { | ||||||
|  | 				button_state[i] = RESTING; | ||||||
|  | 			} else if (millis() - button_press_t0[i] > DEBOUNCE_TIME) { | ||||||
|  | 				button_state[i] = PRESSED; | ||||||
|  | 			} | ||||||
|  | 		} else if (st == PRESSED) { | ||||||
|  | 			if (read_input(pin) != ON) { | ||||||
|  | 				button_state[i] = RELEASING; | ||||||
|  | 				button_release_t0[i] = millis(); | ||||||
|  | 			} | ||||||
|  | 		} else if (st == RELEASING) { | ||||||
|  | 			if (read_input(pin) == ON) { | ||||||
|  | 				button_state[i] = PRESSED; | ||||||
|  | 			} else if (millis() - button_release_t0[i] > DEBOUNCE_TIME) { | ||||||
|  | 				button_state[i] = RELEASED; | ||||||
|  | 			} | ||||||
|  | 		} else if (st == RELEASED) { | ||||||
|  | 			button_state[i] = RESTING; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int red_min = 50; | ||||||
|  | int red_state = red_min; | ||||||
|  | unsigned long brewing_time     = 3000UL; /* 3 seconds */ | ||||||
|  | unsigned long cooling_time     = 3000UL; /* 3 seconds */ | ||||||
|  | unsigned long max_heating_time = 10000UL; /* 10 seconds */ | ||||||
|  | unsigned long max_idle_time    = 10000UL; /* 10 seconds */ | ||||||
|  | 
 | ||||||
|  | void progress() | ||||||
|  | { | ||||||
|  | 	int temp = analogRead(PIN_NTC); | ||||||
|  | 	int on = (button_state[BUTTON_ON] == RELEASED); | ||||||
|  | 	int hot = (button_state[BUTTON_HOT] == PRESSED); | ||||||
|  | 
 | ||||||
|  |   static unsigned long brewing_t0 = 0; | ||||||
|  |   static unsigned long cooling_t0 = 0; | ||||||
|  |   static unsigned long heating_t0 = 0; | ||||||
|  |   static unsigned long hot_t0 = 0; | ||||||
|  | 
 | ||||||
|  | 	Serial.print("state="); | ||||||
|  | 	Serial.print(state); | ||||||
|  | 	Serial.print(" on="); | ||||||
|  | 	Serial.print(on); | ||||||
|  | 	Serial.print(" temp="); | ||||||
|  | 	Serial.println(temp); | ||||||
|  | 
 | ||||||
|  |   /* Pressing ON cancels any operation */ | ||||||
|  | 	if (state != SLEEPING && on) { | ||||||
|  | 			state = SLEEPING; | ||||||
|  |       return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 	if (state == SLEEPING) { | ||||||
|  | 		if (on) { | ||||||
|  | 			state = HEATING; | ||||||
|  |       heating_t0 = millis(); | ||||||
|  | 			Serial.println("heating"); | ||||||
|  | 		} | ||||||
|  | 	} else if (state == HEATING) { | ||||||
|  |     if (temp > TEMP_MAX) { | ||||||
|  |       state = HOT; | ||||||
|  |       hot_t0 = millis(); | ||||||
|  |       buzz_state = BUZZ_HEY; | ||||||
|  |       Serial.println("hot"); | ||||||
|  |     } else if (millis() - heating_t0 > max_heating_time) { | ||||||
|  |       /* TODO: Add alarm state */ | ||||||
|  |       state = SLEEPING; | ||||||
|  |       Serial.println("cannot heat, going to sleep"); | ||||||
|  |     } | ||||||
|  | 	} else if (state == HOT) { | ||||||
|  | 		if (hot) { | ||||||
|  | 			state = BREWING; | ||||||
|  |       brewing_t0 = millis(); | ||||||
|  |       Serial.println("brewing"); | ||||||
|  |     } else if (millis() - hot_t0 > max_idle_time) { | ||||||
|  |       state = SLEEPING; | ||||||
|  |       Serial.println("idle timeout, going to sleep"); | ||||||
|  |     } | ||||||
|  | 	} else if (state == BREWING) { | ||||||
|  |     if (millis() - brewing_t0 > brewing_time) { | ||||||
|  |       state = COOLING; | ||||||
|  |       cooling_t0 = millis(); | ||||||
|  |       Serial.println("cooling"); | ||||||
|  |     } | ||||||
|  |   } else if (state == COOLING) { | ||||||
|  |     /* TODO: Wait a bit and go back to heating */ | ||||||
|  |     if (millis() - cooling_t0 > cooling_time) { | ||||||
|  |       state = HEATING; | ||||||
|  |       heating_t0 = millis(); | ||||||
|  |       Serial.println("heating"); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | update_leds() | ||||||
|  | { | ||||||
|  |   static int r = 0; | ||||||
|  |   static int g = 0; | ||||||
|  | 
 | ||||||
|  |   if (state == HEATING || state == COOLING) { | ||||||
|  |       analogWrite(PIN_LED_RED, r); | ||||||
|  |       setled(PIN_LED_GREEN, 0); | ||||||
|  |       if (r >= 255) | ||||||
|  |         r = 0; | ||||||
|  |       else | ||||||
|  |         r += 3; | ||||||
|  |   } else if (state == HOT) { | ||||||
|  |       setled(PIN_LED_RED, 0); | ||||||
|  |       setled(PIN_LED_GREEN, 1); | ||||||
|  |       r = 0; | ||||||
|  |   } else if (state == BREWING) { | ||||||
|  |       setled(PIN_LED_RED, 0); | ||||||
|  |       analogWrite(PIN_LED_GREEN, g); | ||||||
|  |       if (g >= 255) | ||||||
|  |         g = 0; | ||||||
|  |       else | ||||||
|  |         g += 3; | ||||||
|  |   } else { | ||||||
|  |       setled(PIN_LED_RED, 0); | ||||||
|  |       setled(PIN_LED_GREEN, 0); | ||||||
|  |       r = 0; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | update_heater() | ||||||
|  | { | ||||||
|  |   if (state == HEATING || state == HOT || state == BREWING) { | ||||||
|  |     int temp = analogRead(PIN_NTC); | ||||||
|  |     if (temp < TEMP_MIN) | ||||||
|  |       relay(PIN_HEAT, ON); | ||||||
|  |     else if (temp > TEMP_MAX) | ||||||
|  |       relay(PIN_HEAT, OFF); | ||||||
|  |   } else { | ||||||
|  |       relay(PIN_HEAT, OFF); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | update_pump() | ||||||
|  | { | ||||||
|  | 	if (state == BREWING) { | ||||||
|  | 		relay(PIN_PUMP, ON); | ||||||
|  |   } else { | ||||||
|  | 		relay(PIN_PUMP, OFF); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | update_buzz() | ||||||
|  | { | ||||||
|  |   static unsigned long started = 0; | ||||||
|  | 
 | ||||||
|  |   if (buzz_state == BUZZ_HEY) { | ||||||
|  |     tone(PIN_BUZZ, 1500); | ||||||
|  |     if (started == 0) | ||||||
|  |       started = millis(); | ||||||
|  |     else if (millis() - started > 20) { | ||||||
|  |       buzz_state = BUZZ_OFF; | ||||||
|  |     } | ||||||
|  |   } else if (buzz_state == BUZZ_STOP) { | ||||||
|  |     tone(PIN_BUZZ, 220); | ||||||
|  |   } else if (buzz_state == BUZZ_OFF) { | ||||||
|  |     noTone(PIN_BUZZ); | ||||||
|  |     started = 0; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void setup() | ||||||
|  | { | ||||||
|  | 	Serial.begin(9600); | ||||||
|  | 	Serial.println("Booting"); | ||||||
|  | 
 | ||||||
|  | 	pinMode(PIN_POWER_ON, INPUT); | ||||||
|  | 	pinMode(PIN_HOT, INPUT); | ||||||
|  | 
 | ||||||
|  | 	pinMode(PIN_LED_RED, OUTPUT); | ||||||
|  | 	pinMode(PIN_LED_GREEN, OUTPUT); | ||||||
|  | 	pinMode(PIN_HEAT, OUTPUT); | ||||||
|  | 	pinMode(PIN_PUMP, OUTPUT); | ||||||
|  | 
 | ||||||
|  |   /* Turn all relays off */ | ||||||
|  |   relay(PIN_HEAT, OFF); | ||||||
|  |   relay(PIN_PUMP, OFF); | ||||||
|  | 
 | ||||||
|  | 	Serial.println("Ready"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void loop() | ||||||
|  | { | ||||||
|  | 	//Serial.println("Looping...");
 | ||||||
|  | 	update_buttons(); | ||||||
|  | 	progress(); | ||||||
|  |   update_leds(); | ||||||
|  |   update_heater(); | ||||||
|  |   update_pump(); | ||||||
|  |   update_buzz(); | ||||||
|  |   delay(5); | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Rodrigo Arias Mallo
						Rodrigo Arias Mallo