3.3 Bäromat

Ein Bär erzählt Geschichten und Kinder hören zu. Audio kommt von DFPlayer mini und steuert Bewegung der Sprache-Servos.

Ablauf (vereinfacht)
- Nach Münzeinwurf wird zufällig ein Stück vorgeschlagen.
- Das Stück kann mit Taste Ja angenommen oder mit Taste Nein abgelehnt werden, dabei wird ein neues Stück vorgeschlagen.
- Wird nach 8 Sekunden keine Entscheidung getroffen, wird das vorgeschlagene Stück gespielt.
- Im mp3-Verzeichnis der SD-Karte sind die Stücke 1..ANZ_STUECKE als Beschreibung und ANZ_STUECKE+1..2*ANZ_STUECKE die abzuspielenden Stücke, Beispiel für 30 Stücke:
- 1..30 Ansagen
- 31..60 Spielstücke
Automat wurde deutlich komplexer und mit Arduino Mega realisiert. Ist ein Einzelstück…
SETUP-Taster | Münzeinwurf | Kooper-Info | START-Taste | JA-Taste | NEIN-Taste | Relais-Servos | Relais-Opt | |
---|---|---|---|---|---|---|---|---|
Eingang | P_SETUP 3 | P_MUENZE A3 | P_KO_INFO 4 | P_START 5 | P_JA A4 | P_NEIN A5 | – | – |
Ausgang / LED | – | P_MUENZE_L 22 | – | P_START_L 23 | P_JA_L 24 | P_NEIN_L 25 | P_REL_SER 26 | P_REL_OPT 27 |
Zufall erzeugen, den Samen setzen?
Synopsis: Arduino random()🔗 Arduino randomSeed()🔗
Damit der Pseudo-Zufallsgenerator nach dem Reset nicht immer genau die gleiche Zahlenfolge ausgibt soll mit einer zufälligen Zahl, dem Samen (unsigned long) andere Zufallsfolge ermöglicht werden. Dieser Samen wird im Doku-Beispiel mit analogRead(0) erzeugt, dies ergibt bei meinem Test hier 0, ist also wirkungslos ☹️. Ein Test mit freiem Eingang A8 ergab 1023, den Maximalwert, also auch immer die selbe Zahl..
Programm
Hinweis zu analogReference(INTERNAL) Zeile 51: Beim UNO ist die Referenzspannung mit INTERNAL und beim Mega mit INTERNAL1V1 einzutragen.
Siehe docs.arduino.cc/language-reference/en/functions/analog-io/analogReference/🔗
Automaten Software
// Bäromat V1.0 © 9.03.25 Oliver Mezger MezMedia.de CC BY-SA 4.0
#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>
#include "SchwaetzoLib.h"
//#define DEBUG_ME 1 // Zum Messen der Ausführungsdauer von Schwaetzo:go()
#define ANZ_STUECKE 11 // 1..20 Frage 31..60 Stück
#define SPIEL_STUECKE 20 // Beginn der Spielstücke
#define EXTRA_STUECKE 40 // Beginn der Extrastücke
// Pin Definitionen
#define P_BUSY 2 // MP3-Player: Busy-Pin, low aktiv
#define P_POTI A2 // Pin des Potentiometers
#define P_SETUP 3 // Taster gegen GND zu Justieren
#define P_MUENZE A3 // Muenzpruefer prellend low aktiv
#define P_MUENZE_L 22 // LED high aktiv
#define P_KO_INFO 4 // Kooperationsinfo der anderen Automaten high aktiv
#define P_START 5 // START-Taste prellend low aktiv
#define P_START_L 23 // LED high aktiv
#define P_JA A4 // Ja-Taste prellend low aktiv
#define P_JA_L 24 // LED high aktiv
#define P_NEIN A5 // Nein-Taste prellend low aktiv
#define P_NEIN_L 25 // LED high aktiv
#define P_REL_SER 26 // Relais für Servos low aktiv
#define P_REL_OPT 27 // Optionales Relais
#define P_SERVO_R 7 // Zusätzlicher Servo für Bewegung
#define P_SERVO_L 6 // Zusätzlicher Servo für Bewegung
// Abfrage Definitionen
#define T_JA !digitalRead(P_JA)
#define PLAYER_FERTIG digitalRead(P_BUSY)
#define KO_INFO digitalRead(P_KO_INFO)
SoftwareSerial mySerial(10, 11); // RX, TX, fuer DF-Player
DFPlayerMini_Fast myMP3;
// Endpositionen der Servos für mundZu und mundAuf kennen z.B. 1800µs -> 180 eintragen
Schwaetzo schwaetzoL(A1,9,180,140); // AudioIn, ServoOut, mundZu, mundOffen
Schwaetzo schwaetzoR(A0,8,170,130);
//Schwaetzo schwaetzoL(A1,9); // AudioIn, ServoOut, noch unjustiert
//Schwaetzo schwaetzoR(A0,8);
Servo papaServo;
Servo kidsServo;
Taster t_muenz(P_MUENZE,false); // Taster MUENZE entprellt low active
//Taster t_ja(P_JA,false); // Taster JA entprellt low active
Taster t_nein(P_NEIN,false); // Taster NEIN entprellt low active
Taster t_setup(P_SETUP,false); // Taster SETUP entprellt low active
Taster t_start(P_START,false); // Taster START entprellt low active
Wecker weck1; // Wecker1
enum zustandstyp {RUHE_ENTRY,RUHE,WERBUNG_ENTRY,WERBUNG,PROLOG_ENTRY,PROLOG,NEIN_ENTRY,NEIN,OPTION_ENTRY,OPTION,JA,SPIELEN_ENTRY,SPIELEN,EPILOG,ENDE}; // definiere Aufzählungstyp
enum zustandstyp zustand = RUHE_ENTRY; // Definiere und initialisiere Variable
byte lautstaerke = 20; // 0..30
byte stueck=1; // das zu spielende Stueck
bool sprechen = false; // wenn true werden die Mundservos in der loop belebt
int servoPapa = 1500;
int servoKids = 1500;
void einstellenLautstaerke(){ // Poti einlesen und MP3 Lautstärke einstellen
unsigned int l = 15+analogRead(P_POTI)/100; // POTI einlesen und 0..1023 auf 20..30 umsetzen
if (l>30) l=30;
if (l!=lautstaerke){
lautstaerke=l;
Serial.print(F("Neue Lautstaerke: "));
Serial.println(l);
myMP3.volume(l);
delay(200); // Zeit zum Verarbeiten
}
}
void setup() {
Serial.begin(9600); // Ausgabe ueber serieller Monitor
mySerial.begin(9600); // Anbindung des DF-Player
myMP3.begin(mySerial); // gibt immer true aus
analogReference(INTERNAL1V1); // A/D Referenzspannung https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/
einstellenLautstaerke();
delay(1000);
//myMP3.stopDAC(); // Player ausschalten?
pinMode(P_BUSY,INPUT); // Abfragen ob MP3-Player spielt
pinMode(P_SETUP,INPUT_PULLUP);
//pinMode(P_MUENZE,INPUT_PULLUP);
pinMode(P_JA,INPUT_PULLUP);
//pinMode(P_NEIN,INPUT_PULLUP);
pinMode(P_MUENZE_L,OUTPUT);
pinMode(P_KO_INFO,INPUT);
pinMode(P_START_L,OUTPUT);
pinMode(P_JA_L,OUTPUT);
pinMode(P_NEIN_L,OUTPUT);
pinMode(P_REL_SER,OUTPUT);
digitalWrite(P_REL_SER,HIGH);
pinMode(P_REL_OPT,OUTPUT);
digitalWrite(P_REL_OPT,HIGH);
selbsttest();
//Serial.print(F("Anzahl Ordner auf SD-Karte: "));
//Serial.println(myMP3.numFolders());
}
#ifdef DEBUG_ME
unsigned long maxSchwaetzoTime = 0;
unsigned long tmp=0;
#endif
byte zufallStueck(){ // wählt aus der Anzahl ein zufälliges Stück aus
static byte anzReststuecke=0;
static byte stueckliste[ANZ_STUECKE]; // Permutationsliste der Stücke
if(anzReststuecke==0){ // keine Stücke mehr in der Liste, neue Liste erstellen
for(byte i=0;i<ANZ_STUECKE;i++){ // Auffüllen
stueckliste[i]=i+1;
}
for (byte i = ANZ_STUECKE - 1; i > 0; i--) { // Permutation
byte j = random(0, i + 1); // Zufälliger Index zwischen 0 und i
// Elemente tauschen
byte temp = stueckliste[i];
stueckliste[i] = stueckliste[j];
stueckliste[j] = temp;
}
anzReststuecke=ANZ_STUECKE; // wieder genug da
Serial.print(F("Neue Stückliste erstellt: "));
for(byte i=0;i<ANZ_STUECKE;i++){
Serial.print(stueckliste[i]);
Serial.print(F(" "));
}
Serial.println();
}
return stueckliste[--anzReststuecke];
}
void spieleStueck(byte s){
Serial.print(F("Spiele Stueck: "));
Serial.println(s);
digitalWrite(P_REL_SER,LOW); // Servos kriegen Strom
schwaetzoL.an(); // Servosignal anschalten
schwaetzoR.an();
sprechen = true; // Mundservos beleben
myMP3.playFromMP3Folder(s);
delay(700); // warten bis Player spielt
}
void einschaltenServos(){ // Hier Code zum Einschalten
papaServo.attach(P_SERVO_R,1000,2000);
kidsServo.attach(P_SERVO_L,1000,2000);
}
Wecker weckers; // Wecker für Servosteuerung
void bewegeBaer(){ // Hier während des Spielens Servobewegungen
static int ziel = 1500;
static int schritt = 3;
if(weckers.fertig()){
weckers.stellen(100); // 0,1s
int diff = servoPapa-ziel;
if(abs(diff)<=schritt+2){ // am Ziel, neues Ziel
weckers.stellen(random(500,1200)); // Innehalten
ziel = random(1100,1900); // Endpunkte festlegen
schritt = random(4,10);
Serial.print(F("Ziel: "));
Serial.print(ziel);
Serial.print(F(" Schritt: "));
Serial.println(schritt);
} else {
servoPapa += ((diff>0)?-schritt:schritt);
//if(servoPapa>1800||servoPapa<1200)return; // Sicherung
papaServo.writeMicroseconds(servoPapa);
}
}
}
void baerZurRuhe(){ // Hier Code zum Ruheposition einnehmen und ausschalten
bool r = 1500>servoPapa;
while(abs(servoPapa-1500)>10){
servoPapa+=(r?8:-8);
papaServo.writeMicroseconds(servoPapa); // in die Mitte
delay(100);
}
}
void ausRelais(){
digitalWrite(P_REL_SER,HIGH);
digitalWrite(P_REL_OPT,HIGH);
}
byte werbung = 41;
int wziel=1500; // wohin der Bär bei Werbung schaut
void spieleWerbung(){
spieleStueck(werbung);
switch(werbung){
case 41: wziel=1500; break;
case 42: wziel=1000; break;
case 43: wziel=2000; break;
case 44: wziel=1500; break;
}
if(werbung<44)werbung++;
else werbung=41;
weck1.stellen(30000); // 30 s
}
void baerWerbung(){
static int schritt = 10;
if(weckers.fertig()){
weckers.stellen(100); // 0,1s
int diff = servoPapa-wziel;
if(abs(diff)<=schritt+2);
else {
servoPapa += ((diff>0)?-schritt:schritt);
papaServo.writeMicroseconds(servoPapa);
}
}
}
void jaNeinLed(){ // Wechselblinken
static bool ja = false;
if(millis()%600==0){ // alle 600 ms
if(ja){
digitalWrite(P_JA_L,HIGH);
digitalWrite(P_NEIN_L,LOW);
} else {
digitalWrite(P_JA_L,LOW);
digitalWrite(P_NEIN_L,HIGH);
}
ja = !ja;
}
}
void dreheKids(){ // für das Nein-sagen die Kinderbären drehen lassen
if(weckers.fertig()){
weckers.stellen(300);
if(servoKids>1500) servoKids=1400;
else servoKids=1600;
kidsServo.writeMicroseconds(servoKids);
}
}
void loop() {
if(sprechen){
schwaetzoL.go(); // Audio messen und auf Servo ausgeben
schwaetzoR.go();
}
digitalWrite(P_START_L,KO_INFO); // LED zeigt Zustand der KO_INFO an
if(t_setup.enter())zustand=ENDE;
switch (zustand){
case RUHE_ENTRY: // alles zurücksetzen
Serial.println(F("RUHE_ENTRY "));
sprechen = false;
schwaetzoL.aus();
schwaetzoR.aus();
ausRelais();
myMP3.pause();
digitalWrite(P_MUENZE_L,HIGH); // Bereit für Münzeinwurf
zustand=RUHE;
break;
case RUHE: // Warten auf Münzeinwurf
if (t_muenz.enter()) zustand=PROLOG_ENTRY;
else if(t_start.enter()){
if (KO_INFO) zustand=PROLOG_ENTRY;
else if(weck1.fertig()) zustand=WERBUNG_ENTRY;
}
break;
case WERBUNG_ENTRY:
Serial.println(F("WERBUNG_ENTRY "));
spieleWerbung();
einschaltenServos();
zustand = WERBUNG;
break;
case WERBUNG:
baerWerbung();
if (t_muenz.enter()) zustand=PROLOG_ENTRY;
else if(PLAYER_FERTIG) zustand=RUHE_ENTRY;
break;
case PROLOG_ENTRY:
Serial.println(F("PROLOG_ENTRY "));
digitalWrite(P_MUENZE_L,LOW); // Münzer LED aus
randomSeed(millis()); // Guten Zufall erzeugen
stueck=zufallStueck(); // zufälliges Stück
einstellenLautstaerke();
spieleStueck(stueck);
zustand = PROLOG;
break;
case PROLOG:
jaNeinLed();
if(T_JA) {
spieleStueck(45);
zustand = JA;
}
else if(PLAYER_FERTIG) zustand = OPTION_ENTRY;
else if(t_nein.enter()) zustand = NEIN_ENTRY;
break;
case NEIN_ENTRY:
Serial.println(F("NEIN_ENTRY "));
spieleStueck(46);
einschaltenServos();
zustand = NEIN;
break;
case NEIN:
if(PLAYER_FERTIG) zustand=PROLOG_ENTRY;
dreheKids();
break;
case OPTION_ENTRY:
Serial.println(F("OPTION_ENTRY "));
weck1.stellen(5000); // 5 Sekunden
zustand = OPTION;
break;
case OPTION:
jaNeinLed();
if(T_JA){
spieleStueck(45);
zustand = JA;
}
else if(weck1.fertig()) zustand = SPIELEN_ENTRY;
else if(t_nein.enter()) zustand = NEIN_ENTRY;
break;
case JA:
if(PLAYER_FERTIG) zustand=SPIELEN_ENTRY;
break;
case SPIELEN_ENTRY:
Serial.println(F("SPIELEN_ENTRY "));
digitalWrite(P_JA_L,LOW);
digitalWrite(P_NEIN_L,LOW);
einschaltenServos();
spieleStueck(stueck+SPIEL_STUECKE);
weck1.stellen(10000); // 10s Totzeit
zustand = SPIELEN;
break;
case SPIELEN:
bewegeBaer();
if(PLAYER_FERTIG){ // MP3 spielt? Low aktiv
zustand=EPILOG;
spieleStueck(47);
}
else if(t_nein.enter() && weck1.fertig()){
zustand=EPILOG;
spieleStueck(48); // vorzeitiges Ende
}
else if(t_muenz.enter()) zustand = PROLOG_ENTRY;
break;
case EPILOG:
if(PLAYER_FERTIG || t_nein.enter()){ // MP3 spielt? Low aktiv
zustand = ENDE;
}
else if(t_muenz.enter()) zustand = PROLOG_ENTRY;
break;
case ENDE:
baerZurRuhe();
//papaServo.detach(); // Signal abschalten
//kidsServo.detach();
zustand=RUHE_ENTRY;
break;
}
}
void selbsttest(){
Serial.println(F("Selbsttest"));
if (!digitalRead(P_SETUP)){Serial.println(F("SETUP gedrückt"));return;} // SETUP-Taste
digitalWrite(P_MUENZE_L,HIGH);
if (t_muenz.active()) return;
delay(500);
digitalWrite(P_MUENZE_L,LOW);
if (digitalRead(P_KO_INFO)) {Serial.println(F("Kooper Info aktiv"));return;}
digitalWrite(P_START_L,HIGH);
if (t_start.active()) return;
delay(500);
digitalWrite(P_START_L,LOW);
digitalWrite(P_JA_L,HIGH);
if (T_JA) return;
delay(500);
digitalWrite(P_JA_L,LOW);
digitalWrite(P_NEIN_L,HIGH);
if (t_nein.active()) return;
delay(500);
digitalWrite(P_NEIN_L,LOW);
digitalWrite(P_REL_SER,LOW);
delay(500);
digitalWrite(P_REL_SER,HIGH);
digitalWrite(P_REL_OPT,LOW);
delay(500);
digitalWrite(P_REL_OPT,HIGH);
Serial.println(F("Selbsttest fertig"));
}
Schwätzomat-Library
// SchwaetzoLib.h V1.5 © 19.02.2025 Oliver Mezger MezMedia.de CC BY-SA 4.0
#ifndef SchwaetzoLib_h
#define SchwaetzoLib_h
#endif
#include "Arduino.h"
#include <Servo.h>
#define DEFAULT_MIN_AUDIO 20 // Voreinstellung Minimaler Audiolevel bei rauschenden Aufnahmen
#define DEFAULT_MAX_AUDIO 60 // Voreinstellung Maximaler Audiolevel
#define STILL_SCHWELLE 3 // Schwelle 1/4 Maximum (nicht verwendet)
class Schwaetzo{
public:
Schwaetzo(byte ein,byte aus); // AudioEingang ServoAusgang
Schwaetzo(byte ein,byte aus,byte mzu, byte moffen); // AudioEingang ServoAusgang Servopositionen
void setMundZu(byte zu); // Servoposition für mundZu einstellen
void setMundOffen(byte auf); // Servoposition für mundAuf einstellen
void go(); // periodisch aufrufen um Analog einzulesen und Servo zu steueren
void an(); // Servo wird angeschlossen
void aus();// Servo wird deaktiviert
byte getMaxAudio(); // Audio Maximalwert
byte getLastAudio(); // letzer ermittelter Audiowert für Servo
void moveServo(byte n); // Servo an Position n bewegen zur Justage
void schreibeEEPROM(); // Servodaten ins EEPROM schreiben
void leseEEPROM(); // Servodaten aus EEPROM lesen
private:
static byte instanzen; // Klassenvariable
byte instanzNummer; // die Schwaetzoinstanzen werden durchnummeriert für EEPROM Adressen
Servo servo; // Servo-Instanz
byte audioEingang; // AnalogPin fuer Sound
byte servoAusgang; // Servoanschluss
byte mundZu = 150; // Servoposition wenn Mund zu {100..200}
byte mundOffen = 150; // Servoposition wenn Mund offen {100..200}
byte servoWeg = 0; // mundOffen-nunZu
byte soundSampels = 0 ; // Zaehler fuer Messungen in einer Epoche
byte minAudio = DEFAULT_MIN_AUDIO; // leisester Wert eines Stueckes (Rauschen)
byte maxAudio = DEFAULT_MAX_AUDIO; // lautester Wert eines Stueckes
uint16_t audio = 0; // lautester Wert von n Messungen
byte audioShift = 1; // analogReadWert >> 1 wird bei lautem Audio erhöht um innerhalb 8 Bit zu bleiben
byte lastAudio = 0; // für Ausgabe auf Seriellem Plotter
};
class Taster{ // Klasse zum Entprellen von Tastern
public:
Taster(byte p, bool ha); // Pin, highactive
bool enter(); // Taste gedrückt
bool exit(); // Taste losgelassen
bool active(); // Taste aktiv
private:
byte pin;
bool highactive;
bool old;
};
class Wecker{ // Klasse für Wecker
public:
Wecker();
void stellen(unsigned int n);
bool fertig();
private:
unsigned long weckzeit;
};
// SchwaetzoLib.cpp V1.5 © 19.02.2025 Oliver Mezger MezMedia.de CC BY-SA 4.0
#include "Arduino.h"
#include "SchwaetzoLib.h"
#include <EEPROM.h>
byte Schwaetzo::instanzen = 0; // Klassenvariable für Instanznummer
Schwaetzo::Schwaetzo(byte ein,byte aus){ // AudioEingang ServoAusgang für Verfahren Servo-Justage mit Automat
instanzNummer = instanzen++; // die Instanzen nummerieren wegen EEPROM
audioEingang = ein;
servoAusgang = aus;
pinMode(aus, OUTPUT); // Servosignal = 0
digitalWrite(aus,LOW); // einstellen
}
Schwaetzo::Schwaetzo(byte ein,byte aus,byte mzu, byte moffen):Schwaetzo(ein,aus){ // AudioEingang ServoAusgang MundZu MundOffen
setMundZu(mzu);
setMundOffen(moffen);
}
void Schwaetzo::setMundZu(byte zu){ // Servoposition für mundZu einstellen
if (zu>=100 && zu<= 200) mundZu=zu;
else{
Serial.print(F("setMundZu: Wert passt nicht: "));
Serial.println(zu);
}
servoWeg = abs(mundOffen-mundZu);
}
void Schwaetzo::setMundOffen(byte auf){ // Servoposition für mundOffen einstellen
if (auf>=100 && auf<= 200) mundOffen = auf;
else{
Serial.print(F("setMundOffen: Wert passt nicht: "));
Serial.println(auf);
}
servoWeg = abs(mundOffen-mundZu);
}
void Schwaetzo::go(){ // Sample aufnehmen braucht 130µs somit bei 2 Kanälen 3,846 kHz Abtastfrequenz
static uint16_t n;
if (soundSampels >=100){ // wurden genug Sampels in Epoche aufgenommen 3846Hz/50Hz=77
soundSampels = 0;
if (audio > 255){ // wenn es zu laut ist Messungen abschwächen
audio = 255;
audioShift++; // mehr Vorteilen, Messwert halbieren
minAudio = DEFAULT_MIN_AUDIO;
maxAudio = DEFAULT_MAX_AUDIO;
} else {
if (audio > maxAudio) maxAudio = audio; // Maximallautstärke des Stückes merken
if (audio < minAudio) minAudio = audio; // Minimallautstärke des Stückes merken
if(audio>=minAudio) audio -= minAudio; // Rauschen abziehen
if (audio < maxAudio/2){ // leise Stellen verstärken
n = audio * servoWeg * 2 / maxAudio; // Servoausschlag berechnen
} else {
n = audio * servoWeg / maxAudio; // Servoausschlag berechnen
}
if(n>servoWeg) n = servoWeg; // Servoausschlag begrenzen
if(mundOffen>mundZu) n = mundZu + n;
else n = mundZu - n;
servo.writeMicroseconds(n*10); // Servo Pulsweite ausgeben
}
/*if (audio > (maxAudio>>stillSchwelle)){ // Schwelle 1/8 Maximum
//sprachSituation |= 1;
//ausTimer =0;
}*/
lastAudio = audio; // letzten Wert merken
audio=0;
}
else{ // Audio-Messung
n = analogRead(audioEingang)>>audioShift; // Audiosignal lesen
if(n>audio) audio=n; // Maximum finden
soundSampels++;
lastAudio=0;
}
}
void Schwaetzo::an(){ // Servo wird angeschlossen, bekommt Signal
minAudio = DEFAULT_MIN_AUDIO; // neues Stück neues Glück
maxAudio = DEFAULT_MAX_AUDIO;
audio = 0;
soundSampels = 0;
lastAudio = 0;
audioShift = 1; // Abschwächen von analogRead
if(!servo.attached())servo.attach(servoAusgang,1000,2000); // Servo anschließen
Serial.print(F("Servo angeschlossen "));
Serial.println(servoAusgang);
}
void Schwaetzo::aus(){ // Servosignal wird abgeschaltet
servo.writeMicroseconds(mundZu*10); // Mund schließen
delay(100); // warten bis ausgeführt
servo.detach(); // Servosignal abschalten
Serial.print(F("Servo aus, audioShift: ")); // Infos über das Stück ausgeben
Serial.print(audioShift);
Serial.print(F(" MinLevel: "));
Serial.print(minAudio);
Serial.print(F(" MaxLevel: "));
Serial.println(maxAudio);
}
byte Schwaetzo::getMaxAudio(){ // maximaler Audiowert
return maxAudio;
}
byte Schwaetzo::getLastAudio(){ // letzter Audiowert, 0 während Messung
return lastAudio;
}
void Schwaetzo::moveServo(byte n){ // Servo einstellen während Justage
servo.writeMicroseconds(n*10);
}
void Schwaetzo::schreibeEEPROM(){ // Servodaten ins EEPROM schreiben
EEPROM.update((instanzNummer+1)*2, mundZu);
EEPROM.update((instanzNummer+1)*2+1, mundOffen);
}
void Schwaetzo::leseEEPROM(){ // Servodaten aus EEPROM lesen
byte i;
i = EEPROM.read((instanzNummer+1)*2);
setMundZu(i);
i = EEPROM.read((instanzNummer+1)*2+1);
setMundOffen(i);
}
Taster::Taster(byte p, bool ha){ // Pin, highactive
old=false; // Taste nicht gedrückt
pin=p;
highactive=ha;
pinMode(p,INPUT);
}
bool Taster::enter(){ // Taste gedrückt
bool ausgabe = false;
bool test = digitalRead(pin);
if (old != test){ // hat sich was getan?
delay(10); // 10 ms warten
test=digitalRead(pin); // noch mal einlesen
if (old != test){ // immer noch anders?
ausgabe = highactive?(!old & test):(old & !test); // steigende:fallende Flanke
old = test;
}
}
return ausgabe;
}
bool Taster::exit(){ // Taste losgelassen
bool ausgabe = false;
bool test = digitalRead(pin);
if (old != test){ // hat sich was getan?
delay(10); // 10 ms warten
test=digitalRead(pin); // noch mal einlesen
if (old != test){ // immer noch anders?
ausgabe = highactive?(old & !test):(!old & test); // fallende:steigende Flanke
old = test;
}
}
return ausgabe;
}
bool Taster::active(){
return digitalRead(pin)==highactive;
}
Wecker::Wecker(){
weckzeit = millis();
}
void Wecker::stellen(unsigned int n){
weckzeit = millis()+n;
}
bool Wecker::fertig(){
return millis()>=weckzeit;
}