Finish coffee maker
This commit is contained in:
parent
eb487a0944
commit
6cbd3ae867
Binary file not shown.
Binary file not shown.
|
@ -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;
|
||||||
|
};
|
|
@ -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
|
Serial.begin(9600);
|
||||||
//Complimentary Output or Dual Speakers:
|
Serial.println("Startshduhsd");
|
||||||
//pinMode(10,OUTPUT); Pin pairs: 9,10 Mega: 5-2,6-7,11-12,46-45
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
|
||||||
//pinMode(13,OUTPUT); //LED Connected to analog pin 0
|
|
||||||
if (!SD.begin(SD_ChipSelectPin)) { // see if the card is present and can be initialized:
|
|
||||||
Serial.println("SD fail");
|
|
||||||
return; // don't do anything more if not
|
|
||||||
|
|
||||||
}
|
if (!SD.begin(SD_ChipSelectPin)) { // see if the card is present and can be initialized:
|
||||||
else{
|
Serial.println("SD fail");
|
||||||
Serial.println("SD ok");
|
return; // don't do anything more if not
|
||||||
}
|
} else{
|
||||||
tmrpcm.volume(2);
|
Serial.println("SD ok");
|
||||||
tmrpcm.play("coffee.wav"); //the sound file "music" will play each time the arduino powers up, or is reset
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void loop(){
|
|
||||||
//blink the LED manually to demonstrate music playback is independant of main loop
|
|
||||||
if(tmrpcm.isPlaying() && millis() - time > 50 ) {
|
|
||||||
//digitalWrite(13,!digitalRead(13));
|
|
||||||
// time = millis();
|
|
||||||
}else
|
|
||||||
if(millis() - time > 500){
|
|
||||||
//digitalWrite(13,!digitalRead(13));
|
|
||||||
//time = millis();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(Serial.available()){
|
|
||||||
switch(Serial.read()){
|
|
||||||
case 'c': tmrpcm.play("coffee.wav"); break;
|
|
||||||
case 'p': tmrpcm.pause(); break;
|
|
||||||
case '?': if(tmrpcm.isPlaying()){ Serial.println("A wav file is being played");} else{Serial.println("No wav file is being played");} break;
|
|
||||||
case 'S': tmrpcm.stopPlayback(); break;
|
|
||||||
case '0': tmrpcm.volume(0); break;
|
|
||||||
case '1': tmrpcm.volume(1); break;
|
|
||||||
case '2': tmrpcm.volume(2); break;
|
|
||||||
case '3': tmrpcm.volume(3); break;
|
|
||||||
case '4': tmrpcm.volume(4); break;
|
|
||||||
case '5': tmrpcm.volume(5); break;
|
|
||||||
case '6': tmrpcm.volume(6); break;
|
|
||||||
case '7': tmrpcm.volume(7); break;
|
|
||||||
case '=': tmrpcm.quality(0); break;
|
|
||||||
case '-': tmrpcm.quality(1); break;
|
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
pinMode(MainButtonPin, INPUT);
|
||||||
|
pinMode(CoffeeLedPin, OUTPUT);
|
||||||
|
pinMode(EegLedPin, OUTPUT);
|
||||||
|
|
||||||
|
digitalWrite(CoffeeLedPin, HIGH);
|
||||||
|
|
||||||
|
tmrpcm.volume(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class State : uint8_t {
|
||||||
|
Idle,
|
||||||
|
MakingCoffee,
|
||||||
|
Slowing
|
||||||
|
};
|
||||||
|
|
||||||
|
auto state = State::Idle;
|
||||||
|
uint16_t coffeeLedTimeout = millis();
|
||||||
|
uint16_t eegLedTimeout = millis();
|
||||||
|
|
||||||
|
const uint16_t minEegLedDelay = 50;
|
||||||
|
const uint16_t maxEegLedDelay = 500;
|
||||||
|
uint16_t eegLedDelay = maxEegLedDelay;
|
||||||
|
uint16_t eegLedDelayTimeout = millis();
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
bool buttonPressed = digitalRead(MainButtonPin);
|
||||||
|
auto event = button.event(debounce.event(buttonPressed));
|
||||||
|
|
||||||
|
if((uint16_t) millis() - eegLedTimeout >= eegLedDelay) {
|
||||||
|
eegLedTimeout = millis();
|
||||||
|
digitalWrite(EegLedPin, !digitalRead(EegLedPin));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(state) {
|
||||||
|
case State::Idle:
|
||||||
|
if(event == ButtonEvent::Press || event == ButtonEvent::LongPress) {
|
||||||
|
tmrpcm.play("coffee.wav");
|
||||||
|
state = State::MakingCoffee;
|
||||||
|
coffeeLedTimeout = millis();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State::MakingCoffee:
|
||||||
|
if(!tmrpcm.isPlaying()) {
|
||||||
|
state = State::Slowing;
|
||||||
|
eegLedDelay = minEegLedDelay;
|
||||||
|
digitalWrite(CoffeeLedPin, HIGH);
|
||||||
|
} else {
|
||||||
|
if((uint16_t) millis() - coffeeLedTimeout >= 500) {
|
||||||
|
coffeeLedTimeout = millis();
|
||||||
|
digitalWrite(CoffeeLedPin, !digitalRead(CoffeeLedPin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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