Ich habe ein schönes Programm für den Nano gefunden und möchte zusätzlich einen Piepser ansteuern, wenn der Timer abgelaufen ist. Kann mir jemand helfen, das umzusetzen. Ich bin absoluter Neuling und habe nur den Code gefunden und eingespielt. Funktioniert sowie ich das brauche, nur ein Piepton nach ablauf des Timers wäre perfekt. Leider kenn ich mich noch nicht mit der Materie aus und würde mich um Eure Hilfe freuen
_________________________________________________________________
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#define SCREEN_WIDTH 128 // Breite des OLED-Displays in Pixel
#define SCREEN_HEIGHT 32 // Höhe des OLED-Displays in Pixel
#define SCREEN_ADDRESS 0x3C // Adresse siehe Datenblatt; 0x3D für 128x64, 0x3C für 128x32
#define OLED_RESET 4 // Reset-Pin # (oder -1, wenn der Arduino-Reset-Pin geteilt wird)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
/*
PIN CONNECTION
------------------------------------ ------------------------------------
| Arduino pin | Nama tombol | | Arduino pin | OLED display pin |
------------------------------------ ------------------------------------
| 2 | Left Button | | A4 | SDA |
| 3 | Right Button | | A5 | SCL |
| 4 | OK Button | ------------------------------------
------------------------------------
*/
// --------------------- VARIABLEN FÜR BOX CURSOR ---------------------------
byte page_index = 0;
byte _x, _y, _z = 0;
byte cursor_index = 1;
byte cursor_row_pos = 0;
byte max_cursor_index = 1;
// --------------------- VARIABLEN FÜR TASTEN --------------------------------
// Der Tastenstatus ist normalerweise hoch, da er auf INPUT_PULLUP gesetzt ist, bei Betätigung ist der Ausgabewert = LOW
#define left_button 2
#define right_button 3
#define ok_button 4
#define relay_pin 12
bool paused = false;
bool blinking = false;
bool showCursor = true;
bool timer_active = false;
bool last_ok_button = HIGH;
bool last_left_button = HIGH;
bool last_right_button = HIGH;
// -------------------- ANGEBEN DER TIMER-ADRESSE IM EEPROM -----------------------
const byte HOUR_ADDRESS = 10;
const byte MINUTE_ADDRESS = 12;
const byte SECOND_ADDRESS = 14;
byte jam = 0 ;
byte menit = 0;
byte detik = 0;
byte _time[3]; // Array-Variable, wenn Index = 0 -> Stunden, Index = 1 -> Minuten, Index = 2 -> Sekunden
byte temp_time = 0; // temporäre Variablen / Hilfsvariablen
unsigned long last_blink_time = 0;
unsigned long last_millis_timer = 0;
unsigned long last_time_button_release = 0;
int elapsed_time = 0; // verbleibende Verlängerung nach 1 Sekunde
void readTimeFromEEPROM() {
_time[0] = EEPROM.read(HOUR_ADDRESS);
_time[1] = EEPROM.read(MINUTE_ADDRESS);
_time[2] = EEPROM.read(SECOND_ADDRESS);
}
void setup() {
// Stellen Sie den Pin als INPUT/OUTPUT ein
pinMode(left_button, INPUT_PULLUP);
pinMode(right_button, INPUT_PULLUP);
pinMode(ok_button, INPUT_PULLUP);
pinMode(relay_pin, OUTPUT);
// Stellen Sie den Ausgang beim Hochfahren auf „Low“ ein
digitalWrite(relay_pin, LOW);
// Laden Sie die im EEPROM gespeicherten Timer-Daten und speichern Sie sie in einer Array-Variablen
readTimeFromEEPROM();
// ----------------------------------- OLED Setup ----------------------------------------
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
// Serial.println(F("SSD1306-Zuweisung fehlgeschlagen"));
for(;;); // Fahren Sie nicht fort, sondern wiederholen Sie die Schleife für immer
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.cp437(true);
display.setTextWrap(false);
}
void printText(bool clear_display, int col, int row, char *message, bool visible) {
if (clear_display) display.clearDisplay();
display.setCursor(col, row);
display.print(message);
if (visible) display.display();
}
void drawRectangleCursor(byte row_pos, byte x, byte y, byte z) {
for (byte i = 0; i < y - x; i++) {
display.drawPixel(x + i, row_pos, SSD1306_WHITE); // obere horizontale Linie
display.drawPixel(x + i, z, SSD1306_WHITE); // untere horizontale Linie
if (i < (z - row_pos)) {
display.drawPixel(x, row_pos + i, SSD1306_WHITE); // linke vertikale Linie
display.drawPixel(y, row_pos + i, SSD1306_WHITE); // rechte vertikale Linie
}
}
}
void updateCursorPos() {
if (paused || timer_active && !paused) {
cursor_row_pos = 21;
if (cursor_index == 0) { // Cursor im Lebenslaufmenü
_x = 9;
_y = 50;
_z = 31;
}
else { // Cursor im Stoppmenü
_x = 57;
_y = 86;
_z = 31;
}
}
else if (paused == false && timer_active == false) {
if (page_index == 0) {
if (cursor_index == 0) cursor_row_pos = 0; else cursor_row_pos = 18;
}
else {
cursor_row_pos = 0;
// Wenn Cursor_Index 0..2 bedeutet, dass sich der Cursor in der Timer-Position befindet (0 = Stunde, 1 = Minute, 2 = Sekunde)
switch (cursor_index) {
case 0:
_x = 2;
_y = 29;
_z = 18;
break;
case 1:
_x = 38;
_y = 65;
_z = 18;
break;
case 2:
_x = 74;
_y = 101;
_z = 18;
break;
case 3:
cursor_row_pos = 20;
_x = 10;
_y = 38;
_z = 31;
break;
default:
cursor_row_pos = 20;
_x = 57;
_y = 96;
_z = 31;
}
}
}
}
void showPageOneMenu() {
max_cursor_index = 1;
printText(true, 13, 0, "SETTING", false);
printText(false, 13, 18, "START", false);
printText(false, 0, cursor_row_pos, ">", true);
}
void setMenu(char *left_option, char *right_option) {
updateAndShowTimer();
display.setTextSize(1);
printText(false, 13, 22, left_option, false);
printText(false, 60, 22, right_option, false);
display.setTextSize(2);
}
void showPageTwoMenu() {
max_cursor_index = 4;
setMenu("save", "cancel");
}
void showPausedMenu() {
display.clearDisplay();
max_cursor_index = 1;
drawRectangleCursor(cursor_row_pos, _x, _y, _z);
setMenu("resume", "stop");
display.display();
}
void runAndShowTimer() {
display.clearDisplay();
max_cursor_index = 1;
drawRectangleCursor(cursor_row_pos, _x, _y, _z);
setMenu("pause", "stop");
display.display();
}
void readTime() {
jam = _time[0];
menit = _time[1];
detik = _time[2];
}
void updateAndShowTimer() {
char timer_char[9];
// Wenn der Timer nicht aktiv ist, werden die Stunden-, Minuten- und Sekundenwerte nur zur Anzeige geladen und nicht subtrahiert
if (!timer_active) {
readTime();
}
else {
if (millis() - last_millis_timer >= 1000) {
if (!paused) {
// Sparen Sie die verbleibende überschüssige Zeit
elapsed_time = (millis() - last_millis_timer) - 1000;
if (detik <= 0) {
detik = 60;
if (menit > 0)
menit--;
else if (menit <= 0 && jam > 0) {
jam--;
menit = 59;
}
}
detik--;
last_millis_timer = millis() - elapsed_time;
if (jam <= 0 && menit <= 0 && detik <= 0) timer_active = false;
}
}
}
sprintf_P(timer_char, PSTR("%02d:%02d:%02d"), jam, menit, detik);
printText(false, 5, 2, timer_char, false);
}
void showMenu() {
updateCursorPos();
if (timer_active) {
if (paused) {
showPausedMenu();
digitalWrite(relay_pin, HIGH);
}
else {
runAndShowTimer();
digitalWrite(relay_pin, LOW);
}
}
else {
paused = false;
digitalWrite(relay_pin, HIGH);
if (page_index == 0) {
showPageOneMenu();
blinking = false;
}
else {
display.clearDisplay(); // Reinigen Sie den Bildschirm
showPageTwoMenu(); // Menüseite 2 anzeigen
// Wenn das Blinken aktiv ist und die Blinkzeit >= 300 ms beträgt, dann wird ein Cursorfeld angezeigt, damit ein Blinkeffekt entsteht
if (blinking && millis() - last_blink_time >= 300) {
showCursor = !showCursor;
last_blink_time = millis();
}
// Wenn das Blinken nicht aktiv ist, ist kein Blinkeffekt im Cursorfeld erforderlich (Cursor immer anzeigen).
if (!blinking) showCursor = true;
if (showCursor) drawRectangleCursor(cursor_row_pos, _x, _y, _z);
display.display(); // den Text erneut auf dem Bildschirm anzeigen
}
}
}
bool checkButtonState(bool btn_name, bool &last_button_state) {
bool result = false;
// Wenn btn_name == LOW, bedeutet dies, dass die Taste gedrückt wird
if (btn_name == LOW) {
// Wenn der vorherige Tastenstatus = HIGH ist, bedeutet dies, dass die Taste zuvor nicht gedrückt wurde
if (last_button_state == HIGH)
result = true;
// Wenn der vorherige Tastenstatus = NIEDRIG ist, bedeutet dies, dass die Taste gedrückt und gehalten wird
// Funktionen zum schnelleren Einstellen des Timerwerts durch einfaches Drücken und Halten der Taste, anstatt die Tasten einzeln zu drücken
// um den Timerwert beim Einstellen des Timers zu ändern
else {
// wenn die Taste länger als 2 Sekunden gedrückt und gehalten wird und blinkt = wahr (stellt die Zeit ein)
if (millis() - last_time_button_release >= 2000 && blinking) result = true;
}
last_button_state = LOW;
}
else {
result = false;
last_button_state = HIGH;
}
return result;
}
void loop() {
showMenu();
// ---------------------- Schaltflächenstatus lesen ----------------------------
bool left_button_state = digitalRead(left_button);
bool right_button_state = digitalRead(right_button);
bool ok_button_state = digitalRead(ok_button);
bool ok_button_pressed = checkButtonState(ok_button_state, last_ok_button);
bool left_button_pressed = checkButtonState(left_button_state, last_left_button);
bool right_button_pressed = checkButtonState(right_button_state, last_right_button);
if (left_button_state == 1 && right_button_state == 1 && ok_button_state == 1) {
last_time_button_release = millis();
}
// wenn die Rechts-/Auf-Taste gedrückt wird
if (right_button_pressed) {
// Wenn Blinken = wahr ist, bedeutet dies, dass Sie den Timerwert auf Stunden, Minuten oder Sekunden einstellen
if (blinking) { // Einstellen des Timerwerts (Inkrement)
byte max_value = 99;
// Der Indexcursor bestimmt, ob die Zeit in Stunden, Minuten oder Sekunden eingestellt wird
// Wenn der Cursorindex > 0 bedeutet, dass Minuten oder Sekunden eingestellt werden, ist der Maximalwert = 59
if (cursor_index > 0) max_value = 59;
temp_time++;
if (temp_time > max_value) temp_time = 0;
_time[cursor_index] = temp_time;
}
else { // Legen Sie den Wert „cursor_index“ fest
cursor_index++;
if (cursor_index > max_cursor_index) cursor_index = 0;
}
}
// wenn linke Taste / nach unten gedrückt wird
else if (left_button_pressed) {
// Wenn Blinken = wahr ist, bedeutet dies, dass Sie den Timerwert auf Stunden, Minuten oder Sekunden einstellen
if (blinking) { // Einstellen des Timerwerts (Subtraktion)
byte max_value = 99;
if (cursor_index > 0) max_value = 59;
temp_time--;
// Überprüfen Sie erneut, ob temp_time > max_value ist, da Sie eine Variable vom Typ Byte verwenden
// und der Wert < 0, dann beträgt der Wert 255
if (temp_time > max_value) temp_time = max_value; else if (temp_time < 0) temp_time = max_value;
_time[cursor_index] = temp_time;
}
else {
cursor_index--;
if (cursor_index < 0 || cursor_index > max_cursor_index) cursor_index = max_cursor_index;
}
}
// wenn die OK-Taste gedrückt wird
else if (ok_button_pressed) {
if (timer_active) {
// Wenn Cursor_Index = 0 ist, bedeutet dies, dass der Cursor auf das Pause- oder Fortsetzungsmenü fokussiert ist
if (cursor_index == 0) {
// Gibt den Wert der angehaltenen Variablen zurück. Wenn er zuvor wahr war, wird er falsch und umgekehrt
if (paused) {
paused = false;
last_millis_timer = millis();
}
else
paused = true;
}
// Wenn Cursor_Index = 0 ist, bedeutet dies, dass der Cursor auf das Stoppmenü fokussiert ist
else
timer_active = false;
}
// wenn der Timer nicht aktiv ist
else {
if (page_index == 0) {
// Gehe zur nächsten Indexseite, wenn der Cursorindex = 0 oder im Einstellungsmenü
if (cursor_index == 0)
page_index++;
else {
// cursor index = 1 --> Der Cursor konzentriert sich auf das START-Menü und aktiviert dann den Timer
timer_active = true;
// Laden Sie den in der Array-Variablen gespeicherten Timerwert
readTime();
last_millis_timer = millis();
cursor_index = 1;
}
}
else {
// Geben Sie den Seitenindex = 1 und den Cursorindex = 3 oder 4 ein, stellen Sie die gewünschte Menüposition ein, speichern Sie sie oder brechen Sie sie ab
if (cursor_index == 3 || cursor_index == 4) {
// Wenn der Cursorindex = 3 ist, bedeutet dies, dass die Taste in der Menüposition „Speichern“ (Daten speichern) gedrückt wurde.
// Dies bedeutet, dass der Timer nicht blinkt (kein Timer aktiviert) oder dass der Timer nicht mehr im EEPROM gespeichert ist
// Die Talgdrüse ist nicht so lang, dass die Zeitdauer = 0 ist
bool valid = false;
readTime();
// Als ich aufwachte, dass ich 0 oder 10 Mal im Menü abgebrochen habe, war gültig = wahr
if (jam > 0 || menit > 0 || detik > 0 || cursor_index == 4) valid = true;
if (valid) {
if (cursor_index == 3) {
EEPROM.write(HOUR_ADDRESS, jam);
EEPROM.write(MINUTE_ADDRESS, menit);
EEPROM.write(SECOND_ADDRESS, detik);
}
// Wenn Sie den Vorgang abbrechen, wird der Timer nicht mehr angezeigt
else
readTimeFromEEPROM();
// Der Seitenindex wird angezeigt und der Cursorindex wird auf 0 gesetzt
page_index--;
cursor_index = 0;
}
}
else {
// Wenn Sie den Timer-Marmelade-Kurs wählen, müssen Sie sich die Zeit nehmen und die Timer-Funktion nutzen
if (!blinking) {
temp_time = _time[cursor_index]; // Laden Sie die Variable Array k und temp_time
blinking = true;
}
// Dies bedeutet, dass blinkend = wahr ist, aber Sie werden nicht wissen, was passiert ist
else
blinking = false;
}
}
} // else jika timer tidak aktif
}
}