Code:
#include<EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> ; // NewLiquidCrystal_1.5.1
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
const uint8_t LED_PINS[] = {2, 3, 4, 5, 6, 7, 8 }; // an D2...D8 sind die LEDs angeschlossen (max. 8 LEDs)
const uint8_t LED_COUNT = sizeof(LED_PINS); // die Anzahl der LEDs ermitteln
const uint8_t POTI_PIN = A0; // am Pin A4 liegt der Mittelanschluss des Potis (10kOhm), aussen +5V und GND
const uint8_t DIR_PIN = 10; // am Pin D10 ist ein Taster nach GND angeschlossen (fuer die Laufrichtung)
const uint8_t PROG_PIN = 9; // am Pin A5 ist ein Taster nach GND angeschlossen (fuer die Programmauswahl)
const uint8_t ADDRESS_PROG = 0; // die Adresse im EEPROM fuer die Programmauswahl
const uint8_t ADDRESS_DIR = 1; // die Adresse im EEPROM fuer die Richtung
// die maximale Anzahl der Schritte pro Programm
const byte MAX_COUNT = 30;
// Ein 2D-Array fuer die LED-Programme im Binaerformat (1 Byte pro Schritt)
// Beispiel: "B10000000" entspricht der linken LED, "B00000001" entspricht der rechten LED
// PROGRAM[x][0] = Anzahl der Schritte/Bytes fuer das Programm
const uint8_t PROGRAM[][MAX_COUNT + 1] = {
{ // Programm 0
9,
B10000000, B01000000, B00100000, B00010000, B00001000, B00000100, B00000010, B00000001, B00000000
},
{ // Programm 1
11,
B10000000, B11000000, B11100000, B01110000, B00111000, B00011100, B00001110, B00000111, B00000011, B00000001,
B00000000
},
{ // Programm 2
23,
B10000000, B01000000, B00100000, B00010000, B00001000, B00000100, B00000010, B00000001, B00000011, B00000111,
B00001111, B00011111, B00111111, B01111111, B11111111, B11111110, B11111100, B11111000, B11110000, B11100000,
B11000000, B10000000, B00000000
},
{ // Programm 3
20,
B10000000, B11000000, B11100000, B01110000, B00111000, B00011100, B00001110, B00000111, B00000011, B00000001,
B00000001, B00000011, B00000111, B00001110, B00011100, B00111000, B01110000, B11100000, B11000000, B10000000
},
{ // Programm 4
15,
B10000000, B01000000, B10100000, B01010000, B10101000, B01010100, B10101010, B01010101, B00101010, B00010101,
B00001010, B00000101, B00000010, B00000001, B00000000
},
{ // Programm 5
16,
B10000000, B11000000, B11100000, B11110000, B11111000, B11111100, B11111110, B11111111, B01111111, B00111111,
B00011111, B00001111, B00000111, B00000011, B00000001, B00000000
},
{ // Programm 6
15,
B10000000, B11000000, B11100000, B11110000, B01110000, B00110000, B00010000, B00001000, B00001100, B00001110,
B00001111, B00000111, B00000011, B00000001, B00000000
},
{ // Programm 7
8,
B10000001, B11000011, B11100111, B11111111, B11100111, B11000011, B10000001, B00000000
},
{ // Programm 8
2,
B10101010, B01010101
},
{ // Programm 9
8,
B10001000, B11001100, B01100110, B00110011, B00010001, B00110011, B01100110, B11001100
}
};
const uint8_t PROG_COUNT = 10; // die Anzahl der Programme festlegen
uint8_t progNr = 0; // zum merken der ausgewaehlten Programmnummer
uint8_t index = 1; // index dient zum durchzaehlen der Programmschritte
int8_t direction = 1; // direction wird fuer die Laufrichtung verwendet (1 = vorwaerts, -1 = rueckwaerts)
uint16_t speed = 0; // speed wird vom Poti ausgelesen (0...1023) und entspricht dann den Millisekunden zwischen den Schritten
uint32_t nowMillis, stepMillis, dirMillis, progMillis;
bool dirState = HIGH, dirOldState = HIGH;
bool progState = HIGH, progOldState = HIGH;
void setLEDs(const uint8_t bits) {
for (uint8_t i = 0; i < LED_COUNT; i++) {
digitalWrite(LED_PINS[i], (bits << i) & 0x80);
}
}
void setup() {
progNr = EEPROM.read(ADDRESS_PROG);
direction = EEPROM.read(ADDRESS_DIR);
// LCD Übertragung starten
lcd.begin(20, 4); // LCD Start Zeichen 20 4 Zeilen
lcd.clear(); // LCD Löschen
Serial.begin(115200);
for (uint8_t i = 0; i < LED_COUNT; i++) {
pinMode(LED_PINS[i], OUTPUT);
}
pinMode(POTI_PIN, INPUT);
pinMode(DIR_PIN, INPUT_PULLUP);
pinMode(PROG_PIN, INPUT_PULLUP);
setLEDs(PROGRAM[progNr][index]);
stepMillis = millis();
lcd.setCursor(0, 0);
lcd.print(F("Programm: "));
lcd.setCursor(10, 0);
lcd.print(progNr);
lcd.setCursor(0, 2);
lcd.print(F("Richtung: "));
lcd.setCursor(10, 2);
lcd.print(direction == 1 ? F("vor ") : F("zurueck "));
}
void loop() {
nowMillis = millis(); // die aktuellen Millisekunden holen
// jeder Taster prellt beim betaetigen (Mehrfachausloesung). Hier werden dafuer 30ms beruecksichtigt.
dirState = digitalRead(DIR_PIN); // den Zustand des Tasters auslesen (HIGH = nicht gedrueckt, wegen INPUT_PULLUP)
if (dirState != dirOldState && nowMillis - dirMillis > 30) { // nur wenn sich der Zustand geaendert hat und die Prellzeit um ist
dirMillis = nowMillis; // die Millisekunden seit dem Tastendruck in dirMillis merken
if (!dirState) { // wenn Taste == LOW (gedrueckt)
direction = -direction; // dann die Laufrichtung umdrehen (1 oder -1)
lcd.setCursor(0, 2);
lcd.print(F("Richtung: "));
lcd.setCursor(10, 2);
lcd.print(direction == 1 ? F("vor ") : F("zurueck "));
}
dirOldState = dirState; // den letzten Tastenzustand in dirOldState merken
EEPROM.update(ADDRESS_DIR, direction);
}
progState = digitalRead(PROG_PIN); // den Zustand des Tasters auslesen (HIGH = nicht gedrueckt, wegen INPUT_PULLUP)
if (progState != progOldState && nowMillis - progMillis > 30) { // nur wenn sich der Zustand geaendert hat und die Prellzeit um ist
progMillis = nowMillis; // die Millisekunden seit dem Tastendruck in progMillis merken
if (!progState) { // wenn Taste == LOW (gedrueckt)
progNr++; // dann die Programmnummer um eins erhoehen
if (progNr > PROG_COUNT - 1) progNr = 0; // wenn die Programmnummer groesser als die Anzahl der Programme ist, bei Null weitermachen
lcd.setCursor(0, 0);
lcd.print(F("Programm: "));
lcd.setCursor(10, 0);
lcd.print(progNr);
lcd.setCursor(0, 2);
}
progOldState = progState; // den letzten Tastenzustand in progOldState merken
EEPROM.update(ADDRESS_PROG, progNr);
}
speed = analogRead(POTI_PIN); // den Wert vom Poti auslesen (10 Bit = 0...1023)
if (nowMillis - stepMillis > speed) { // wenn die Zeit, seit dem letzten erhoehen des Index, groesser als der Wert vom Poti
stepMillis = nowMillis; // die Millisekunden in stepMillis merken
index += direction; // index um eins erhoehen bzw. erniedrigen (je nach Wert von direction)
// im ersten Element des 2D-Arrays "PROGRAM[progNr][0]" steht die Anzahl der Schritte
if (index > PROGRAM[progNr][0]) index = 1; // wenn index groesser als die Anzahl der Schritte, dann wieder bei Eins beginnen
if (index < 1) index = PROGRAM[progNr][0]; // wenn index kleiner als Eins, dann wieder mit dem hoechsten Wert beginnen
setLEDs(PROGRAM[progNr][index]); // die LEDs entsprechend der Bits fuer diesen Schritt ein-/ausschalten
lcd.setCursor(0, 3);
lcd.print(F("Speed: "));
lcd.setCursor(7, 3);
lcd.print(speed);
}
}