Arduino Mega Projekt: Ansteuerung der besuchten Urlaubsorte auf einer Weltkarte mit Arduino Mega mit LEDs

Wollte lange schon mal, zur Erinnerung an schöne Urlaube eine Markierung auf der Weltkarte anbringen wo wir waren. Als IT-Berater muss es dann aber schon eine Micro-Computer gesteuerte Version sein. Ein roter Punkt reicht da nicht.

Also hier das Ergebnis als Video, und weiter unten dann die Details:

Also so sieht die Weltkarte von vorne aus:

Die Weltkarte in einem Bilderrahmen
Die Weltkarte in einem Bilderrahmen

Hier die Rückseite. Ein Arduino Mega wurde verwendet, weil der bis zu 60 Ausgänge hat, die einzeln angesteuert werden können.

Die ganze Rückseite, es fehlen noch die analogen Eingänge die als digitale Ausgänge geschaltet werden
Die ganze Rückseite, es fehlen noch die analogen Eingänge die als digitale Ausgänge geschaltet werden

An jedem besuchten Urlaubsort wurde ein 3 mm Loch gebohrt und eine LED reingesteckt. An einen Pin der LED wurde jeweils noch ein 220 Ohm Widerstand angelötet. Ja, es sieht etwas wild aus:

An jede LED kommt noch ein Widerstand
An jede LED kommt noch ein Widerstand

Eine Nahaufnahme des Arduino Mega.

Weltkarte5

Ein Reed-Kontakt habe ich noch an einem Interrupt-Eingang des Arduino geschaltet, so kann man von vorne mit einem Magnet über den Null-Meridian fahren, und schon leuchten unsere TOP 3 Urlaubsorte (Hawaii, Tokio, Seychellen) permanent.

Reed-Kontakt für die TOP 3 Urlaubsorte
Reed-Kontakt für die TOP 3 Urlaubsorte

Hier das C-Programm, welches in den Arduino geflasht wird und die Ansteuerung durchführt.

Das ist die 1. Version, da werde ich noch einiges ergänzen.


/*
 TWWeltkarte 1.0 steuert die LED einer Urlaubsweltkarte an.
 
 Copyright (C) 2013 Thomas Wenzlaff 
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see {http://www.gnu.org/licenses/}. 
 */

// Reihenvolge so verdrahtet:
// PWM Ports an Pin 2-13
//1 Portugal 
//2 Polen
//3 Balearen
//4 Bulgarien
//5 Zypern
//6 Kreta
//7 Madrid
//8 Athen
//9 Dänemark
//10 Kanaren
//11 Irland
//12 London
// Digitale Ports an Pin 22-53
//13 Deutschland
//14 St. Lucia
//15 Thailand
//16 Domrep
//17 Singapur
//18 St. Martin
//19 Bali
//20 New York
//21 Hong Kong
//22 Hawaii
//23 Malediven
//24 Syschellen
//25 Sri Lanka
//26 Japan
//27 Estland, Talliin
//28 Mauritius
//29 St.Petersburg
//30 Orlando
//31 Stockholm, Schweden
//32 Curasao
//33 Israel
//34 St. Lucia
//35 Dubai
//36 San Francisko
//37 Ras El Kaiman
//38 Los Agelos
//39 Tunesien
//40 Aruba
//41 Malta
//42 Antigua
//43 Ägypen, Assuan
//44 Miami
// Analoge Ausgänge
//45 Paris
//46 Rom
//47 Danzig
//48 Posen
//49 Amsterdam

int pins[54]; // für digitale Ausgänge
int pinsPwd[12]; // für die 12 PDW Ausgänge

volatile int status = 0;

int WARTE = 200;

void setup() {
  Serial.begin(9600);
  attachInterrupt(2, reed, CHANGE); // Interrupt 2 an Pin 2

  for (int i = 0; i < 54; i++) {
    pins[i] =i; // array ini
  }

  for (int i = 22; i < 54; i++) {
    pinMode(pins[i], OUTPUT);
  }

  for (int i = 0; i < 13; i++) {
    pinsPwd[i] =i; // array ini
  }
  for (int i = 2; i < 15; i++) {
    pinMode(pinsPwd[i], OUTPUT);
  }

  // 5 Analogen Eingänge als Ausgang setzen
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
}

void loop() {

  blinkDeutschland();
  delay(1000);

  lauflichtSchnell();
  delay(1000);

  lauflicht();
  delay(1000);

  for (int w =0; w < 100; w++){
    alleLaenderLauflicht();
  }

  delay(500);

  for (int w =0; w < 50; w++){
    alleLaenderBlinken();
  }

  delay(1000);
}

void lauflicht(){
  for (int i =1; i< MAX_LAENDER; i++){
    setKanalAn(i);
    delay(500);
    setKanalAus(i);  
  }       
}

void lauflichtSchnell(){
  for (int i =1; i< MAX_LAENDER; i++){
    setKanalAn(i);
    delay(100);
    setKanalAus(i);  
  }       
}

void blinkDeutschland(){
  for (int i=0; i< 50; i++){
    digitalWrite(22, HIGH);
    delay(WARTE);
    digitalWrite(22, LOW);
    delay(WARTE);
  }  
}

// diese Methode wird beim Interrupt aufgerufen, wenn das Reedrelais betätigt wird
void reed(){
  setKanalAn(Japan);
  setKanalAn(Hawaii);
  setKanalAn(Seychellen);
}

// schaltet Kanal 1-49 AN
void setKanalAn(const int i){
  int kanal = getKanal(i);
  if (i <= 12){
    analogWrite(kanal,255);
  }
  else if (i >= 13 && i <= 44) {
    digitalWrite(kanal, HIGH);
  }
  else if (i == 45){
    digitalWrite(A0, HIGH);
  }
  else if (i == 46){
    digitalWrite(A1, HIGH);
  }
  else if (i == 47){
    digitalWrite(A2, HIGH);
  }
  else if (i == 48){
    digitalWrite(A3, HIGH);
  }
  else if (i == 49){
    digitalWrite(A4, HIGH);
  }
}

// schaltet Kanal 1-49 AUS
void setKanalAus(const int i){
  int kanal = getKanal(i);
  if (i <= 12){
    analogWrite(kanal,0);
  }
  else if (i >= 13 && i <= 44) {
    digitalWrite(kanal, LOW);
  }
  else if (i == 45){
    digitalWrite(A0, LOW);
  }
  else if (i == 46){
    digitalWrite(A1, LOW);
  }
  else if (i == 47){
    digitalWrite(A2, LOW);
  }
  else if (i == 48){
    digitalWrite(A3, LOW);
  }
  else if (i == 49){
    digitalWrite(A4, LOW);
  }
}

// Mapping von 1-49 auf die jeweiligen Kanäle 1-12 PWN und 22-53 Digital, und 5 Analoge A0-A4
int getKanal(const int i) {

  // Umsetzung auf: 1-49
  // Eingang: | 1-12 - 13-44 | 45-49
  // | 12 | | 32 | 5
  // | 1-12 | | 22-53 | 0-4

  int kanal = 0;

  if (i <= 12) {
    kanal = i + 1; // PWM Kanäle 1-12
  } 
  else if (i >= 13 && i <= 44) {
    kanal = i + 9; // Digitale Kanäle 22-53
  } 
  else if (i > 44){
    kanal = i - 45; // Analoge Kanäle A0-A4
  }
  return kanal;
}

void alleLaenderLauflicht(){
  for (int i =1; i<=MAX_LAENDER; i++){
    setKanalAn(i);
    delay(1);
    setKanalAus(i);
  }
}

void alleLaenderBlinken(){
  for (int i =1; i<=MAX_LAENDER; i++){
    setKanalAn(i);
    delay(2);
    setKanalAus(i);
  }
}

Verbesserungsvorschläge: Ich hätte von Anfang an, low current LEDs (2mA) kaufen müssen, dann hätte ich auch alle gleichzeitig ansteuern könnne. Die Kosten heute auch nicht mehr viel mehr.
Oder aber über Treiber die LEDs ansteuern. Da die Ausgänge des Arduino in Summe nicht mehr als 150 mA ziehen dürfen. Da meine LEDs 20 mA das Stück ziehen, kann ich nur ca. 6 gleichzeitig anschalten.
Deshalb schalte ich, wenn alle LEDs an sein sollen, jede nur für eine ms nacheinander an und dann wieder aus.
Werde das aber nicht mehr ändern.

TODO:
Da das Netzkabel noch stört, werde ich wohl noch ein Batterie-Pack einbauen. Evl. auch noch einen Bewegungssensor, der die Karte automatisch anschaltet, wenn man davor steht.
In der Zwischenzeit brauche ich auch eine Lösung mit mehr als 60 LEDs, da wir doch noch einige Länder mehr besucht haben.