Als Geschenk an Deine Frau könntest Du mit diesem Programm und einem Servo eine Blume öffnen lassen:
const byte cols = 20; // columns/characters per row
const byte rows = 4; // how many rows
const byte addr = 0x27; // set the LCD address to 0x3F or 0x27
#include <Wire.h> // needed for the I2C interface
#include <NoiascaLiquidCrystal.h> // download library from https://werner.rothschopf.net/202009_arduino_liquid_crystal_intro.htm
#include <NoiascaHW/lcd_PCF8574.h> // include the proper IO interface
LiquidCrystal_PCF8574 lcd(Wire, addr, cols, rows); // create lcd object - with support of special characters
#include <MobaTools.h>
MoToTimer blumenZeitgeber; // erzeuge Zeitgeberobjekt
MoToServo blumenServo; // erzeuge Servoobjekt
const byte servoWinkelOffen = 160; // Winkel der geöffneten Blume
const byte servoWinkelGeschlossen = 20; // Winkel der geschlossenen Blume
const uint32_t zeitWinkelOffen = 4000; // Zeit in ms, wie lange die Blume geöffnet bleibt
const byte blumenTasterPin = 7; // Taster zum Starten der Bewegung
const byte servoPin = 8; // Anschluß für den Servo
void setup()
{
Wire.begin(); // start I2C library
lcd.begin(); // initialize the LCD
lcd.backlight(); // turn on backlight
pinMode(LED_BUILTIN, OUTPUT); // eingebaute LED
pinMode(blumenTasterPin, INPUT_PULLUP); // schaltet nach GND, so ist kein externer pullup Widerstand am Taster erforderlich
blumenServo.attach(servoPin); // verwendeter Pin
blumenServo.setSpeed( 5 ); // Verfahrgeschwindigkeit in 0,5μs Einheiten einstellen
blumenServo.write(servoWinkelGeschlossen); // Startposition
}
void herzschlag() // ein gleichmäßiges Blinken zeigt eine blockadearme Programmierung
{
static uint32_t vorhin = 0; // Zeitmerker
if (millis() - vorhin >= 111) // Zeitintervall in ms abgelaufen?
{
vorhin = millis(); // Zeitmerker mit der aktuellen Zeit stellen
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // eingebaute LED blinkt als "Herzschlag"
}
}
void anzeige(const byte zeile, const char * txt) // übergebener Text wird in der gewünschten LCD-Zeile angezeigt
{
lcd.setCursor(0, zeile); // Schreibposition wählen
lcd.print( F(" ") ); // Zeile löschen
lcd.setCursor(0, zeile); // Schreibposition wählen
lcd.print( txt ); // Text anzeigen
}
void loop() {
static byte schritt = 0; // Schritt der Schrittkette
switch (schritt) // gehe zum aktuellen Schritt
{
case 0: // Starttext ausgeben
if ( !blumenServo.moving() ) // wenn die Servobewegung beendet ist
{
anzeige(0, "Blume geschlossen");
anzeige(1, "Tastendruck erwartet");
schritt++; // zum nächsten Schritt
}
break;
case 1: // nach Tastendruck Bewegung starten
if ( !digitalRead(blumenTasterPin) ) // Taste gedrückt?
{
anzeige(0, "Taste gedrückt");
anzeige(1, "Blume öffnet");
blumenServo.write(servoWinkelOffen); // Blume öffnet langsam
schritt++; // zum nächsten Schritt
}
break;
case 2: // nach Bewegungsende Öffnungszeit starten
if ( !blumenServo.moving() ) // Bewegung beendet?
{
anzeige(0, "Blume geöffnet");
anzeige(1, "");
blumenZeitgeber.setTime( zeitWinkelOffen ); // Öffnungszeit starten
schritt++; // zum nächsten Schritt
}
break;
case 3: // nach Öffnungszeitende Blume schließen
if ( !blumenZeitgeber.running() ) // Öffnungszeit abgelaufen
{
anzeige(0, "Zeit abgelaufen");
anzeige(1, "Blume schließt");
blumenServo.write(servoWinkelGeschlossen); // Blume schließt langsam
schritt = 0; // zurück zum ersten Schritt
}
break;
default: // unerlaubter Schritt, sollte nie erreicht werden
schritt = 0; // zurück zum ersten Schritt
break;
}
herzschlag();
}
@MicroBahner: getestet mit MobaTools-Development2.5.0 ohne Probleme!