#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSans9pt7b.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Anschlüsse Encoder
#define ENCODER_CLK 10
#define ENCODER_DT 9
#define ENCODER_SW 5
//Encoder Variablen
long int modeLastChanged = 0;
int prevClk = HIGH;
// Countdown state
#define COUNTDOWN_SETUP 0
#define COUNTDOWN_ACTIVE 1
#define COUNTDOWN_PAUSED 2
#define COUNTDOWN_MOTOR 3
#define COUNTDOWN_END 4
//Variablen Countdown
int countdownState = COUNTDOWN_SETUP; // begin with us ready to set a countdown time
long lastCountdownChange = 0;
long lastWaitingTimeChange = 0;
long lastLedChangeTime = 0;
//Anschlüsse Motor und Grüne LED
const int MOTOR = 3;
const int LED_gr = 7;
int i = 0;
// Timer button
#define BUT_PIN 8 // where is our button connected (other end to ground)
long butLastChange = 0; // when did we last register a state change?
int butLastState = HIGH; // what was the last state of the button?
unsigned long startTime = millis();
//Werte auf Display hier ändern
long startzeit = 15; //15
int wartezeit = 15; //15
int zustellung = 1;
int hoehe = 40; //40
int counter;
unsigned long currentMillis;
unsigned long previousMillis = 0;
unsigned long previousTime = 0;
unsigned long remainingTime;
//Werte anpassen (*60 etc.)
long startzeit1 = 2; //900
long zustellung1 = 100;
long wartezeit1 = 3000; //300000
int ledState = 1;
static int motorState = HIGH;
int pwmValue = 5; // PWM-Wert für den Motor
typedef enum {
SET_STARTZEIT,
SET_WARTEZEIT,
SET_ZUSTELLUNG,
SET_HOEHE,
prog_GO,
} Mode;
Mode mode = SET_STARTZEIT;
//Auswählen der vier einstellbaren Variablen
void nextMode() {
switch (mode) {
case SET_STARTZEIT:
mode = SET_WARTEZEIT;
break;
case SET_WARTEZEIT:
mode = SET_ZUSTELLUNG;
break;
case SET_ZUSTELLUNG:
mode = SET_HOEHE;
break;
case SET_HOEHE:
mode = SET_STARTZEIT;
break;
}
}
//Variable einstellen
void updateValue(int delta) {
switch (mode) {
case SET_STARTZEIT:
startzeit = constrain(startzeit + delta, 0, 100);
// startzeit1 = startzeit * 6; in *60 ändern
startzeit1 = startzeit * 60 ;
Serial.print("Startzeit ");
Serial.println(startzeit1);
break;
case SET_WARTEZEIT:
wartezeit = constrain(wartezeit + delta, 0, 100);
wartezeit1 = wartezeit * 60000;
Serial.print("Wartezeit ");
Serial.println(wartezeit1);
break;
case SET_ZUSTELLUNG:
zustellung = constrain(zustellung + delta, 0, 1000);
zustellung1 = zustellung * 100;
break;
case SET_HOEHE:
hoehe = constrain(hoehe + (delta*5), 0, 1000);
break;
}
}
//Display Update
void updateDisplay() {
//display.setFont(&FreeMono9pt7b);
display.clearDisplay();
//display.setTextSize(2);
display.setTextColor(WHITE);
//Startzeit
display.setCursor(8, 2);
display.print("Startzeit");
display.setCursor(72, 2);
display.print(startzeit);
display.setCursor (85, 2);
display.print("Min.");
if (mode == SET_STARTZEIT) {
display.setCursor(2, 2);
display.print("-");
}
//Wartezeit zwischen Schritten
display.setCursor(8, 18);
display.print("Wartezeit");
display.setCursor(72, 18);
display.print(wartezeit);
display.setCursor (85, 18);
display.print("Min.");
if (mode == SET_WARTEZEIT) {
display.setCursor(2, 18);
display.print("-");
}
//Schrittweite
display.setCursor(8, 34);
display.print("Zustellung");
display.setCursor(72, 34);
display.print(zustellung);
display.setCursor (85, 34);
display.print("Mikrom.");
if (mode == SET_ZUSTELLUNG) {
display.setCursor(2, 34);
display.print("-");
}
//Höhe
display.setCursor(8, 50);
display.print("Hoehe");
display.setCursor(72, 50);
display.print(hoehe);
display.setCursor (85, 50);
display.print("Mikrom.");
if (mode == SET_HOEHE) {
display.setCursor(2, 50);
display.print("-");
}
display.display();
return;
}
void encoder () {
if (digitalRead(ENCODER_SW) == LOW && millis() - modeLastChanged > 300)
{
modeLastChanged = millis();
nextMode();
updateDisplay();
}
int clk = digitalRead(ENCODER_CLK);
if (clk != prevClk && clk == LOW) {
int dt = digitalRead(ENCODER_DT);
int delta = dt == HIGH ? 1 : -1;
updateValue(delta);
updateDisplay();
}
prevClk = clk;
}
void setupBut() {
digitalWrite(BUT_PIN, HIGH);
pinMode(BUT_PIN, INPUT_PULLUP); // Input with a pull-up resistor (so high when not connected to ground physically by the button)
//Serial.println("SetupButton: Check!");
return;
}
void updateBut() {
// This is my simple debouncing code, that will ensure 50ms have passed before
// allowing further state changes
if(millis() - butLastChange > 50)
{
if(digitalRead(BUT_PIN) == LOW)
{
if(butLastState == HIGH)
{
butLastChange = millis();
butLastState = LOW;
butPressed(); // run the function for a button press
}
}
else
{
butLastState = HIGH;
}
}
return;
}
void butPressed(){
// This adjusts the state of our device, which uses a finite state machine with 4 different possible states
if(countdownState == COUNTDOWN_SETUP)
{
// If we are in the setup mode, then set our mode to active so the countdown can begin
countdownState = COUNTDOWN_ACTIVE;
}
else if(countdownState == COUNTDOWN_ACTIVE)
{
// If we are currently in the active countdown mode - move us to the paused state
countdownState = COUNTDOWN_PAUSED;
}
else if(countdownState == COUNTDOWN_PAUSED)
{
// If we are currently in the paused countdown mode - move us back to the active state
countdownState = COUNTDOWN_ACTIVE;
}
else if(countdownState == COUNTDOWN_END)
{
// If our countdown is already over, then move us back to the setup stage
countdownState = COUNTDOWN_SETUP; // reset values ready for the setup state again
}
return;
}
void updateCountdown(){
if(millis() - lastCountdownChange >= 1000)
{
lastCountdownChange = millis(); // Record when we made this change
startzeit1--; // Reduce seconds by 1
if(startzeit1 < 1) // If seconds are now -1, then we have to reduce mins
{
countdownState = COUNTDOWN_MOTOR;
analogWrite(MOTOR, pwmValue);
currentMillis = millis();
}
}
display.clearDisplay();
display.setCursor(42, 2);
display.setTextSize(1.5);
display.print("Wartezeit");
display.setCursor(50, 20);
printTimeInMinutesSeconds(startzeit1);
display.display();
previousMillis = millis();
return;
}
void motoran() {
//Serial.println(motorState);
counter = ((hoehe / zustellung));
remainingTime = (wartezeit1-(currentMillis-previousMillis))/1000;
//Serial.println(counter);
display.clearDisplay();
display.setTextSize(1.8);
display.setCursor(2, 35);
display.print("Verbl. Schritte");
display.setCursor(2, 45);
display.print(counter-i);
display.setCursor(2, 2);
display.print("Restzeit");
display.setCursor(2, 15);
printTimeInMinutesSeconds(remainingTime);
display.display();
if(i<counter) {
currentMillis = millis(); // Aktuelle Zeit in Millisekunden
if (motorState == HIGH) { // Motor ist ausgeschaltet
if (currentMillis - previousMillis >= zustellung1) { // Wartezeit nach dem letzten Ausschalten des Motors ist abgelaufen
motorState = LOW; // Motor einschalten
analogWrite(MOTOR, 0); // Stelle die PWM-Geschwindigkeit für den Motor ein
previousMillis = currentMillis; // speichere den Zeitpunkt des Einschaltens des Motors
}
}
else if(currentMillis - previousMillis >= wartezeit1) { // Motor ist eingeschaltet
// Zeit, in der der Motor eingeschaltet ist, ist abgelaufen
motorState = HIGH; // Motor ausschalten
analogWrite(MOTOR, pwmValue); // Stelle die PWM-Geschwindigkeit auf 0 ein
previousMillis = currentMillis; // speichere den Zeitpunkt des Ausschaltens des Motors
i++;
}
}
else {
digitalWrite(MOTOR, LOW);
countdownState = COUNTDOWN_END;
}
}
void printTimeInMinutesSeconds(long milliseconds) {
int seconds = (milliseconds % 60);
int minutes = (milliseconds /60);
if(minutes < 10) display.print("0");
display.print(minutes);
display.print(":");
if(seconds < 10) display.print("0");
display.print(seconds);
display.display();
}
void fertig() {
analogWrite(MOTOR, 0);
while (millis() < startTime + wartezeit1); {
Serial.println("Warten");
}
digitalWrite(LED_gr, HIGH);
display.clearDisplay();
display.setCursor(42, 10);
display.print("Fertig");
display.display();
}
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
pinMode(ENCODER_CLK, INPUT);
pinMode(ENCODER_DT, INPUT);
pinMode(ENCODER_SW, INPUT_PULLUP);
pinMode(MOTOR, OUTPUT);
pinMode(LED_gr, OUTPUT);
Serial.begin(9600);
setupBut();
updateDisplay();
}
void loop() {
if (countdownState == COUNTDOWN_SETUP) encoder(); updateBut();
if(countdownState == COUNTDOWN_ACTIVE) updateCountdown();
if(countdownState == COUNTDOWN_MOTOR) motoran();
if(countdownState == COUNTDOWN_END) fertig();
}