Finish coffee maker
This commit is contained in:
parent
eb487a0944
commit
6cbd3ae867
BIN
coffee.wav
Normal file
BIN
coffee.wav
Normal file
Binary file not shown.
BIN
die Geräusche der Kaffeemaschine.aac
Normal file
BIN
die Geräusche der Kaffeemaschine.aac
Normal file
Binary file not shown.
64
firmware/button.h
Normal file
64
firmware/button.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "debounce.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum class ButtonEvent : uint8_t {
|
||||||
|
NoEvent,
|
||||||
|
Press,
|
||||||
|
LongPress,
|
||||||
|
DoublePress,
|
||||||
|
};
|
||||||
|
|
||||||
|
// template wird komplett wegoptimiert (wie #define)
|
||||||
|
template<uint16_t LONGPRESS_TIMEOUT, uint16_t DOUBLEPRESS_TIMEOUT>
|
||||||
|
class Button {
|
||||||
|
public:
|
||||||
|
enum class State : uint8_t {
|
||||||
|
Idle,
|
||||||
|
Pressed,
|
||||||
|
LongPressed,
|
||||||
|
Released,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ButtonEvent event(RawButtonEvent result) {
|
||||||
|
switch(state) {
|
||||||
|
case State::Idle :
|
||||||
|
if(result == RawButtonEvent::Pressed) {
|
||||||
|
state = State::Pressed;
|
||||||
|
counter = millis();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State::Pressed :
|
||||||
|
if(result == RawButtonEvent::Released) {
|
||||||
|
state = State::Released;
|
||||||
|
counter = millis();
|
||||||
|
} else if((uint16_t) millis() - counter >= LONGPRESS_TIMEOUT) {
|
||||||
|
state = State::LongPressed;
|
||||||
|
return ButtonEvent::LongPress;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State::Released :
|
||||||
|
if(result == RawButtonEvent::Pressed) {
|
||||||
|
state= State::Idle;
|
||||||
|
return ButtonEvent::DoublePress;
|
||||||
|
} else if((uint16_t) millis() - counter >= DOUBLEPRESS_TIMEOUT) {
|
||||||
|
state = State::Idle;
|
||||||
|
return ButtonEvent::Press;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State::LongPressed :
|
||||||
|
if(result == RawButtonEvent::Released) {
|
||||||
|
state = State::Idle;
|
||||||
|
} else {
|
||||||
|
return ButtonEvent::LongPress;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ButtonEvent::NoEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
State state = State::Idle;
|
||||||
|
uint16_t counter = 0;
|
||||||
|
};
|
58
firmware/debounce.h
Normal file
58
firmware/debounce.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#ifndef _DEBOUNCE_H_
|
||||||
|
#define _DEBOUNCE_H_
|
||||||
|
|
||||||
|
|
||||||
|
enum class RawButtonEvent : uint8_t {
|
||||||
|
NoEvent,
|
||||||
|
Pressed,
|
||||||
|
Released,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<uint16_t DEBOUNCE_PRESSED, uint16_t DEBOUNCE_UNPRESSED = DEBOUNCE_PRESSED>
|
||||||
|
class Debounce {
|
||||||
|
public:
|
||||||
|
enum class State : uint8_t {
|
||||||
|
Unpressed,
|
||||||
|
UnpressedDebounced,
|
||||||
|
Pressed,
|
||||||
|
PressedDebounced,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
RawButtonEvent event(bool pressed) {
|
||||||
|
switch(state) {
|
||||||
|
case State::Unpressed :
|
||||||
|
if(pressed) {
|
||||||
|
state = State::PressedDebounced;
|
||||||
|
counter = millis();
|
||||||
|
return RawButtonEvent::Pressed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State::PressedDebounced :
|
||||||
|
if((uint16_t) millis() - counter > DEBOUNCE_PRESSED) {
|
||||||
|
state = State::Pressed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State::Pressed :
|
||||||
|
if(!pressed) {
|
||||||
|
state = State::UnpressedDebounced;
|
||||||
|
counter = millis();
|
||||||
|
return RawButtonEvent::Released;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State::UnpressedDebounced :
|
||||||
|
if((uint16_t) millis() - counter > DEBOUNCE_UNPRESSED) {
|
||||||
|
state = State::Unpressed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawButtonEvent::NoEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
State state = State::Unpressed;
|
||||||
|
uint16_t counter = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,65 +1,101 @@
|
|||||||
#include <SD.h> // need to include the SD library
|
#include <SD.h>
|
||||||
//#define SD_ChipSelectPin 53 //example uses hardware SS pin 53 on Mega2560
|
#include <TMRpcm.h>
|
||||||
#define SD_ChipSelectPin 5 //using digital pin 4 on arduino nano 328, can use other pins
|
|
||||||
#include <TMRpcm.h> // also need to include this library...
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
|
||||||
|
#include "button.h"
|
||||||
|
#include "debounce.h"
|
||||||
|
|
||||||
|
using MainButton = Button<150, 150>;
|
||||||
|
|
||||||
|
#define SD_ChipSelectPin 5
|
||||||
|
#define MainButtonPin 6
|
||||||
|
#define CoffeeLedPin 7
|
||||||
|
#define EegLedPin 8
|
||||||
|
|
||||||
|
Debounce<20> debounce;
|
||||||
|
MainButton button;
|
||||||
|
|
||||||
TMRpcm tmrpcm; // create an object for use in this sketch
|
TMRpcm tmrpcm; // create an object for use in this sketch
|
||||||
|
|
||||||
unsigned long time = 0;
|
unsigned long time = 0;
|
||||||
|
|
||||||
void setup(){
|
void setup(){
|
||||||
|
tmrpcm.speakerPin = 9;
|
||||||
tmrpcm.speakerPin = 9; //5,6,11 or 46 on Mega, 9 on Uno, Nano, etc
|
|
||||||
//Complimentary Output or Dual Speakers:
|
|
||||||
//pinMode(10,OUTPUT); Pin pairs: 9,10 Mega: 5-2,6-7,11-12,46-45
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
//pinMode(13,OUTPUT); //LED Connected to analog pin 0
|
Serial.println("Startshduhsd");
|
||||||
|
|
||||||
if (!SD.begin(SD_ChipSelectPin)) { // see if the card is present and can be initialized:
|
if (!SD.begin(SD_ChipSelectPin)) { // see if the card is present and can be initialized:
|
||||||
Serial.println("SD fail");
|
Serial.println("SD fail");
|
||||||
return; // don't do anything more if not
|
return; // don't do anything more if not
|
||||||
|
} else{
|
||||||
}
|
|
||||||
else{
|
|
||||||
Serial.println("SD ok");
|
Serial.println("SD ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pinMode(MainButtonPin, INPUT);
|
||||||
|
pinMode(CoffeeLedPin, OUTPUT);
|
||||||
|
pinMode(EegLedPin, OUTPUT);
|
||||||
|
|
||||||
|
digitalWrite(CoffeeLedPin, HIGH);
|
||||||
|
|
||||||
tmrpcm.volume(2);
|
tmrpcm.volume(2);
|
||||||
tmrpcm.play("coffee.wav"); //the sound file "music" will play each time the arduino powers up, or is reset
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class State : uint8_t {
|
||||||
|
Idle,
|
||||||
|
MakingCoffee,
|
||||||
|
Slowing
|
||||||
|
};
|
||||||
|
|
||||||
|
auto state = State::Idle;
|
||||||
|
uint16_t coffeeLedTimeout = millis();
|
||||||
|
uint16_t eegLedTimeout = millis();
|
||||||
|
|
||||||
void loop(){
|
const uint16_t minEegLedDelay = 50;
|
||||||
//blink the LED manually to demonstrate music playback is independant of main loop
|
const uint16_t maxEegLedDelay = 500;
|
||||||
if(tmrpcm.isPlaying() && millis() - time > 50 ) {
|
uint16_t eegLedDelay = maxEegLedDelay;
|
||||||
//digitalWrite(13,!digitalRead(13));
|
uint16_t eegLedDelayTimeout = millis();
|
||||||
// time = millis();
|
|
||||||
}else
|
void loop() {
|
||||||
if(millis() - time > 500){
|
bool buttonPressed = digitalRead(MainButtonPin);
|
||||||
//digitalWrite(13,!digitalRead(13));
|
auto event = button.event(debounce.event(buttonPressed));
|
||||||
//time = millis();
|
|
||||||
|
if((uint16_t) millis() - eegLedTimeout >= eegLedDelay) {
|
||||||
|
eegLedTimeout = millis();
|
||||||
|
digitalWrite(EegLedPin, !digitalRead(EegLedPin));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(state) {
|
||||||
if(Serial.available()){
|
case State::Idle:
|
||||||
switch(Serial.read()){
|
if(event == ButtonEvent::Press || event == ButtonEvent::LongPress) {
|
||||||
case 'c': tmrpcm.play("coffee.wav"); break;
|
tmrpcm.play("coffee.wav");
|
||||||
case 'p': tmrpcm.pause(); break;
|
state = State::MakingCoffee;
|
||||||
case '?': if(tmrpcm.isPlaying()){ Serial.println("A wav file is being played");} else{Serial.println("No wav file is being played");} break;
|
coffeeLedTimeout = millis();
|
||||||
case 'S': tmrpcm.stopPlayback(); break;
|
}
|
||||||
case '0': tmrpcm.volume(0); break;
|
break;
|
||||||
case '1': tmrpcm.volume(1); break;
|
case State::MakingCoffee:
|
||||||
case '2': tmrpcm.volume(2); break;
|
if(!tmrpcm.isPlaying()) {
|
||||||
case '3': tmrpcm.volume(3); break;
|
state = State::Slowing;
|
||||||
case '4': tmrpcm.volume(4); break;
|
eegLedDelay = minEegLedDelay;
|
||||||
case '5': tmrpcm.volume(5); break;
|
digitalWrite(CoffeeLedPin, HIGH);
|
||||||
case '6': tmrpcm.volume(6); break;
|
} else {
|
||||||
case '7': tmrpcm.volume(7); break;
|
if((uint16_t) millis() - coffeeLedTimeout >= 500) {
|
||||||
case '=': tmrpcm.quality(0); break;
|
coffeeLedTimeout = millis();
|
||||||
case '-': tmrpcm.quality(1); break;
|
digitalWrite(CoffeeLedPin, !digitalRead(CoffeeLedPin));
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case State::Slowing:
|
||||||
|
Serial.println(eegLedDelay);
|
||||||
|
if((uint16_t) millis() - eegLedDelayTimeout >= 300) {
|
||||||
|
eegLedDelayTimeout = millis();
|
||||||
|
if(eegLedDelay > maxEegLedDelay) {
|
||||||
|
eegLedDelay = maxEegLedDelay;
|
||||||
|
state = State::Idle;
|
||||||
|
} else {
|
||||||
|
eegLedDelay = eegLedDelay * 1.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user