Arduino-Programmierung zur Steuerung von LEDs
Im Netz gibt es viele Beispiele dafür, wie man einen Arduino so programmieren kann, dass ein Gebäude "belebt" erscheint, d.h. dass unterschiedliche Räume inerhalb des Gebäudes separat beleuchtet werden und die Beleuchtung mit Hilfe eines kleinen Arduino-Programms gesteuert werden. Daher möchte ich hier nicht auf die Grundlagen der Arduino-Programmieurng eingehen, sondern Euch zeigen, was ich damit realisiert habe und auch die entsprechenden Programme zur Verfügung stellen. Selbstverständlich kann ich keine Garantie für die korrekte Funktion der Codes geben.
Anforderungen an die Beleuchtungssteuerung
Zunächst möchte ich hier die Anforderungen zusammenstellen, die in einem Programm zur Beleuchtung meines Bahnhofsgebäudes umzusetzen wären:
- Unterschiedliche "Klassen" von Lampen, z.B. Büro, Geschäfte, öffentliche Beleuchtung. In Büroräumen können die Lampen zufällig an- und ausgeschaltet werden, während in Geschäften die Lampen zu den üblichen Öffnungszeiten dauerhaft an sind, und auch die öffentliche Beleuchtung (z.B. die Bahnhofshalle) ist dauerhaft eingeschaltet.
- Unterschiedliche "Arten" von Lampen, z.B. Neonröhren, die beim Einschalten flackern, Gasentladungslampen (Natriumdampflampen), die beim Einschalten langsam heller werden und natürlich auch "normale" Lampen, die einfach nur ein- und ausgeschaltet werden.
- Einschalten der Lampen nur zu bestimmten Zeiten, z.B. die Bürobeleuchtung nur zu Büroarbeitszeiten usw.
- Evtl. für später: Einschalten der Lampen nur wenn es dunkel ist - dazu müsste der Arduino mit einem Helligkeitssensor verbunden werden.
- Evtl. für später: Zufällige Simulation von defekten Lampen, z.B. blinkende Leuchtstoffröhren
Und natürlich soll das alles simultan für alle Lampen gleichzeitig ablaufen. Das habe ich so realisiert, dass das Programm zunächst für jede Lampe die Ein- und Ausschaltzeiten zufällig (natürlich innerhalb der vorgegebenen Regeln) bestimmt und dann in einer Endlosschleife alle Lampen immer wieder prüft, ob sie umgeschaltet werden müssen. Im folgenden findet Ihr ein Video und einen Code dazu. Wenn ich einmal Zeit habe, werde ich den Code kommentieren, und Ideen für eine Erweiterung habe ich auch schon...
byte LEDs[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54};
byte n_LEDs = sizeof(LEDs);
enum class Type {NORMAL, NEON, GAS, N_A};
enum class Type2 {HOME, OFFICE, COMMERCIAL, PUBLIC, N_A};
enum class State {ON, OFF, START_ON, START_OFF};
unsigned long normal_on_min = 500;
unsigned long normal_on_max = 3000;
unsigned long normal_off_min = 200;
unsigned long normal_off_max = 6000;
unsigned long neon_on_min = 70;
unsigned long neon_on_max = 320;
unsigned long neon_off_min = 350;
unsigned long neon_off_max = 850;
unsigned neon_flicker[sizeof(LEDs)];
unsigned neon_flicker_max = 4;
unsigned long gas_on_min[sizeof(LEDs)];
unsigned long gas_on_max[sizeof(LEDs)];
unsigned long gas_off_min[sizeof(LEDs)];
unsigned long gas_off_max[sizeof(LEDs)];
unsigned long gas_on_min_init = 1;
unsigned long gas_on_max_init = 2;
unsigned long gas_off_min_init = 2;
unsigned long gas_off_max_init = 4;
unsigned gas_switch_states = 50;
unsigned gas_switch_state[sizeof(LEDs)];
unsigned long gas_switch_period = 200;
Type LED_type[sizeof(LEDs)]; //{Type::NORMAL, Type::NORMAL};
State LED_state[sizeof(LEDs)]; // {State::OFF, State::OFF};
unsigned long LED_on[sizeof(LEDs)];
unsigned long LED_off[sizeof(LEDs)];
unsigned long LED_init_delay[sizeof(LEDs)];
long LED_temp_millis[sizeof(LEDs)];
long LED_gas_temp_millis[sizeof(LEDs)];
void setup()
{
long start_millis = millis();
randomSeed(analogRead(0));
for (int i=0; i<n_LEDs; i++)
{
LED_state[i] = State::OFF;
pinMode(LEDs[i], OUTPUT);
digitalWrite(LEDs[i], LOW);
LED_temp_millis[i] = start_millis;
if ((LEDs[i]==1)||(LEDs[i]==2)||(LEDs[i]==3)||(LEDs[i]==4)) // right hall
{
LED_type[i] = Type::NEON;
LED_init_delay[i] = 16000;
neon_flicker[i] = random(1,neon_flicker_max);
LED_on[i] = random(neon_on_min,neon_on_max);
LED_off[i] = LED_init_delay[i] + random(neon_off_min,neon_off_max);
}
else if ((LEDs[i]==11)||(LEDs[i]==12))
{
LED_type[i] = Type::GAS;
LED_init_delay[i] = 19000;
LED_on[i] = 5;
LED_off[i] = LED_init_delay[i] + 5;
gas_on_min[i] = gas_on_min_init;
gas_on_max[i] = gas_on_max_init;
gas_off_min[i] = gas_off_min_init;
gas_off_max[i] = gas_off_max_init;
gas_switch_state[i] = 0;
}
else if ((LEDs[i]==13)||(LEDs[i]==14))
{
LED_type[i] = Type::GAS;
LED_init_delay[i] = 19000;
LED_on[i] = 5;
LED_off[i] = LED_init_delay[i] + 5;
gas_on_min[i] = gas_on_min_init;
gas_on_max[i] = gas_on_max_init;
gas_off_min[i] = gas_off_min_init;
gas_off_max[i] = gas_off_max_init;
gas_switch_state[i] = 0;
}
else if ((LEDs[i]==15)||(LEDs[i]==16)||(LEDs[i]==17)||(LEDs[i]==18)||(LEDs[i]==19)||(LEDs[i]==21)) // right intermediate hall
{
LED_type[i] = Type::NEON;
LED_init_delay[i] = 12000;
neon_flicker[i] = random(1,neon_flicker_max);
LED_on[i] = random(neon_on_min,neon_on_max);
LED_off[i] = LED_init_delay[i] + random(neon_off_min,neon_off_max);
}
else if ((LEDs[i]==23)||(LEDs[i]==24))
{
LED_type[i] = Type::GAS;
LED_init_delay[i] = 18000;
LED_on[i] = 5;
LED_off[i] = LED_init_delay[i] + 5;
gas_on_min[i] = gas_on_min_init;
gas_on_max[i] = gas_on_max_init;
gas_off_min[i] = gas_off_min_init;
gas_off_max[i] = gas_off_max_init;
gas_switch_state[i] = 0;
}
else if (LEDs[i]==25) // kiosk in main hall
{
LED_type[i] = Type::NEON;
LED_init_delay[i] = 4000;
neon_flicker[i] = random(1,neon_flicker_max);
LED_on[i] = random(neon_on_min,neon_on_max);
LED_off[i] = LED_init_delay[i] + random(neon_off_min,neon_off_max);
}
else if (LEDs[i]==26) // ticket office in main hall
{
LED_type[i] = Type::NORMAL;
LED_init_delay[i] = 5000;
LED_on[i] = random(normal_on_min,normal_on_max);
LED_off[i] = LED_init_delay[i] + random(normal_off_min,normal_off_max);
}
else if ((LEDs[i]==27)||(LEDs[i]==28)||(LEDs[i]==29)||(LEDs[i]==31)) // main hall
{
LED_type[i] = Type::NEON;
LED_init_delay[i] = 8000;
neon_flicker[i] = random(1,neon_flicker_max);
LED_on[i] = random(neon_on_min,neon_on_max);
LED_off[i] = LED_init_delay[i] + random(neon_off_min,neon_off_max);
}
else if ((LEDs[i]==32)||(LEDs[i]==33)||(LEDs[i]==34)||(LEDs[i]==35)||(LEDs[i]==36)||(LEDs[i]==37)) // left intermediate hall
{
LED_type[i] = Type::NEON;
LED_init_delay[i] = 12000;
neon_flicker[i] = random(1,neon_flicker_max);
LED_on[i] = random(neon_on_min,neon_on_max);
LED_off[i] = LED_init_delay[i] + random(neon_off_min,neon_off_max);
}
else if ((LEDs[i]==38)||(LEDs[i]==39))
{
LED_type[i] = Type::GAS;
LED_init_delay[i] = 18000;
LED_on[i] = 5;
LED_off[i] = LED_init_delay[i] + 5;
gas_on_min[i] = gas_on_min_init;
gas_on_max[i] = gas_on_max_init;
gas_off_min[i] = gas_off_min_init;
gas_off_max[i] = gas_off_max_init;
gas_switch_state[i] = 0;
}
else if ((LEDs[i]==40)||(LEDs[i]==41)||(LEDs[i]==42)||(LEDs[i]==43)) // left hall
{
LED_type[i] = Type::NEON;
LED_init_delay[i] = 16000;
neon_flicker[i] = random(1,neon_flicker_max);
LED_on[i] = random(neon_on_min,neon_on_max);
LED_off[i] = LED_init_delay[i] + random(neon_off_min,neon_off_max);
}
else if ((LEDs[i]==51)||(LEDs[i]==52))
{
LED_type[i] = Type::GAS;
LED_init_delay[i] = 19000;
LED_on[i] = 5;
LED_off[i] = LED_init_delay[i] + 5;
gas_on_min[i] = gas_on_min_init;
gas_on_max[i] = gas_on_max_init;
gas_off_min[i] = gas_off_min_init;
gas_off_max[i] = gas_off_max_init;
gas_switch_state[i] = 0;
}
else if ((LEDs[i]==53)||(LEDs[i]==54))
{
LED_type[i] = Type::GAS;
LED_init_delay[i] = 19000;
LED_on[i] = 5;
LED_off[i] = LED_init_delay[i] + 5;
gas_on_min[i] = gas_on_min_init;
gas_on_max[i] = gas_on_max_init;
gas_off_min[i] = gas_off_min_init;
gas_off_max[i] = gas_off_max_init;
gas_switch_state[i] = 0;
}
else
{
LED_type[i] = Type::NORMAL;
//LED_type[i] = Type::N_A;
LED_init_delay[i] = 20000;
if (LED_type[i] == Type::NORMAL)
{
LED_on[i] = random(normal_on_min,normal_on_max);
LED_off[i] = LED_init_delay[i] + random(normal_off_min,normal_off_max);
}
}
}
}
boolean millis_clock (int duration, long &last_event) {
// duration: duration of current on/off state in ms
// last_event: clock time of last swiitching event
// return value: true if duration to next switching event has passed
if (millis() - last_event < duration)
return false;
while (millis() - last_event >= duration)
last_event += duration;
return true;
}
void runLEDs() {
for (int i=0;i<sizeof(LEDs);i++)
{
if (LED_type[i] == Type::NORMAL)
{
if (LED_state[i] == State::OFF)
if (millis_clock(LED_off[i],LED_temp_millis[i]))
{
digitalWrite(LEDs[i],!digitalRead(LEDs[i]));
LED_state[i] = State::ON;
LED_off[i] = random(normal_off_min,normal_off_max);
}
if (LED_state[i] == State::ON)
if (millis_clock(LED_on[i],LED_temp_millis[i]))
{
digitalWrite(LEDs[i],!digitalRead(LEDs[i]));
LED_state[i] = State::OFF;
LED_on[i] = random(normal_on_min,normal_on_max);
}
}
if (LED_type[i] == Type::NEON)
{
if (neon_flicker[i]>0)
if (LED_state[i] == State::OFF)
if (millis_clock(LED_off[i],LED_temp_millis[i]))
{
digitalWrite(LEDs[i],!digitalRead(LEDs[i]));
LED_state[i] = State::ON;
LED_off[i] = random(neon_off_min,neon_off_max);
neon_flicker[i] -= 1;
}
if (neon_flicker[i]>0)
if (LED_state[i] == State::ON)
if (millis_clock(LED_on[i],LED_temp_millis[i]))
{
digitalWrite(LEDs[i],!digitalRead(LEDs[i]));
LED_state[i] = State::OFF;
LED_on[i] = random(neon_on_min,neon_on_max);
}
}
if (LED_type[i] == Type::GAS)
{
if (LED_state[i] == State::OFF)
if (millis_clock(LED_off[i],LED_temp_millis[i]))
{
digitalWrite(LEDs[i],!digitalRead(LEDs[i]));
LED_state[i] = State::ON;
LED_off[i] = random(gas_off_min[i],gas_off_max[i]);
}
if ((LED_state[i] == State::ON) && (gas_switch_state[i] < gas_switch_states))
{
if (millis_clock(LED_on[i],LED_temp_millis[i]))
{
digitalWrite(LEDs[i],!digitalRead(LEDs[i]));
LED_state[i] = State::OFF;
LED_on[i] = random(gas_on_min[i],gas_on_max[i]);
}
if (millis_clock(gas_switch_period, LED_gas_temp_millis[i]))
{
//gas_switch_state += 1;
if (gas_switch_state[i] < gas_switch_states)
{
gas_switch_state[i] += 1;
if ((gas_switch_state[i]==5)||(gas_switch_state[i]==10))
{
gas_on_min[i] += 1;
gas_on_max[i] += 2;
gas_off_max[i] += 1;
}
if ((gas_switch_state[i]==15)||(gas_switch_state[i]==20)||(gas_switch_state[i]==25)||(gas_switch_state[i]==30)||(gas_switch_state[i]==35)||(gas_switch_state[i]==40))
{
gas_on_min[i] += 1;
gas_on_max[i] += 2;
gas_off_max[i] -= 1;
}
}
}
}
}
}
}
void loop()
{
runLEDs();
}
Hier geht es zurück zu Ausprobiert... und zur Startseite.