2016 Tage zuvor: Arduino-Senso

Als ich im letzten Jahr endlich den Open Camera Controller fertiggestellt hatte, stellte sich die Frage: Was mache ich jetzt mit meinem Arduino Eine Antwort war schnell gefunden: Einen Senso-Klon) bauen! Leider sich das Projekt dann doch wesentlich lÀnger hingezogen als gedacht. Einen nicht unwesentlichen Teil haben meine eher rostigen Elektronik-Kenntnisse dazu beigetragen. Aber nichts desto trotz ist es nun endlich vollbracht! Auch wenn es sicherlich nicht schönsten Lösung ist, hier eine simplifizierte Version meines Schaltplans.

Zum 1:1 Nachbau möchte ich so allerdings nicht raten – Pin 13 des Arduino eignet sich nicht sonderlich gut als Input (wegen der Standard Notification-LED). Und auch sollte man fĂŒr blaue LEDs einen höheren Widerstand als fĂŒr die anderen LEDs (rot, gelb und grĂŒn in meinem Fall) benutzen – sie sind schlichtweg viel zu hell!

Die Software zur Hardware war wiederum erstaunlich schnell geschrieben – lediglich wenige Stunden (intensives Testen inklusive) hat es gedauert. Ganz in Anlehnung an das Hardware-Layout ist auch der Code nicht sonderlich ansehnlich. Dennoch sei er hier vorgestellt:

/* Arduino-Senso; v1.1
   (c)2012 by Kai Boenke
   Published under CC BY-NC-SA 3.0
 */

// Define Pins
#define ledGrn 6
#define ledRed 7
#define ledBlu 8
#define ledYel 9
#define btnGrn 10
#define btnRed 11
#define btnBlu 12
#define btnYel 13

// Customizations
#define maxWait 100000
#define maxMoves 30
#define inputDelay 500

// Declare Program-internal Vars
boolean waiting; //Defines Status for loop()
int waitCounter; //Used to determine Timeouts in loop()
int moveCounter; //Defines current Move in Sequence (Sequence-Replay)
int nextCounter; //Defines curent move to be made (next move to be made)
int rndSequence[maxMoves]; //Holds complete Sequence
int ledPinMin; //Define lowest Pin
int ledPinMax; //Define highest Pin


// Intial Setup
void setup() {
  // Pinmodes
  pinMode(ledGrn, OUTPUT);
  pinMode(ledRed, OUTPUT);
  pinMode(ledBlu, INPUT); //Exploits reduced voltage to dim LED
  pinMode(ledYel, OUTPUT);
  pinMode(btnGrn, INPUT);
  pinMode(btnRed, INPUT);
  pinMode(btnBlu, INPUT);
  pinMode(btnYel, INPUT);
  
  // Determine lowest/highest LED-Pins
  ledPinMin = min(min(min(ledGrn, ledRed), ledYel), ledBlu);
  ledPinMax = max(max(max(ledGrn, ledRed), ledYel), ledBlu);
  
  // Randomness
  Serial.begin(9600);
  randomSeed(analogRead(0));
  
  // Start first Game
  initGame();
}

// Main Loop
void loop() {
  // Check for Timeout
  if(waitCounter > maxWait){
    initGame();
  }else{
    waitCounter++;
  }
  
  // Show Sequence for new Move?
  if((!waiting) && (moveCounter == 0)){
    showSequence();
  }
  
  // Read Input
  int valGrn = digitalRead(btnGrn);
  int valRed = digitalRead(btnRed);
  int valBlu = digitalRead(btnBlu);
  int valYel = digitalRead(btnYel);
  
  // Evaluate Input
  if((valGrn == HIGH) || (valRed == HIGH) || (valBlu == HIGH) || (valYel == HIGH)){
    switch(rndSequence[moveCounter]){
      case ledGrn:
        if(valGrn == HIGH){
          blink(ledGrn);
          nextTry();
        }else{
          youLoose();
        }
        break;
      case ledRed:
        if(valRed == HIGH){
          blink(ledRed);
          nextTry();
        }else{
          youLoose();
        }
        break;
      case ledBlu:
        if(valBlu == HIGH){
          blink(ledBlu);
          nextTry();
        }else{
          youLoose();
        }
        break;
      case ledYel:
        if(digitalRead(btnYel) == HIGH){
          blink(ledYel);
          nextTry();
        }else{
          youLoose();
        }
        break;
    }
  }
}


/*
   Game-Logic
 */

// Setup a new Game
void initGame(){
  // Re-Initialize
  nextCounter = 0;
  moveCounter = 0;
  waiting = false;
  waitCounter = 0;
  
  // Visualize beginning of new Game
  roundBlink(5);
  
  // Generate new Sequence
  for(int i = 0; i < maxMoves; i++){
    rndSequence[i] = random(ledPinMin, ledPinMax+1);
    delay(20); //Try to increase Randomness even more
  }
}

// Visualize Sequence
void showSequence() {
  // Customize
  int blinkDelay = 500;
  int waitDelay = 100;
  
  // Show Sequence
  resetLeds();
  for(int i=0; i<=nextCounter; i++){
    blink(rndSequence[i], blinkDelay);
    delay(waitDelay);
  }
  
  // Reset Status
  waiting = true;
}

// Advance Try after successful Move
void nextTry(){
  // Next Move in Sequence or Replay?
  if(moveCounter >= nextCounter){
    delay(inputDelay);
    blinkAll(1, 10);
    nextCounter++;
    moveCounter = 0;
  }else{
    moveCounter++;
  }
  
  // Base-Case
  if(nextCounter >= maxMoves){
    // We have a Winner!
    blinkAll(10, 10);
    initGame();
  }else{
    // Move on!
    delay(inputDelay);
    waiting = false;
  }
}

// Wrong Move
void youLoose(){
  // Visualize
  blinkAll(1, 500);
  
  // New Game
  initGame();
}


/*
   LED-Controls
 */

// Single Blink
void blink(int led){
  blink(led, 100);
}
void blink(int led, int blinkDelay){
  resetLeds();
  digitalWrite(led, HIGH);
  delay(blinkDelay);
  digitalWrite(led, LOW);
}

// Random Blink
void blinkRandom(){
  blinkRandom(1, 100, 0);
}
void blinkRandom(int loops){
  blinkRandom(loops, 100, 0);
}
void blinkRandom(int loops, int blinkDelay){
  blinkRandom(loops, blinkDelay, 0);
}
void blinkRandom(int loops, int blinkDelay, int wait) {
  resetLeds();
  for(int i = 0; i

Insgesamt hat mich dieses Projekt wesentlich mehr Nerven als Geld gekostet. Wenn man bereits ein Arduino zur Hand hat, benötigt man lediglich eine Platine, ein paar LEDs, WiderstĂ€nde sowie vier Schalter – den Rest kann man wiederverwenden. Stellt sich nur die Frage was ich jetzt mit dem Arduino anfange…

2262 Tage zuvor: Genugtuung

Projekte fertigstellen macht Spaß. Es gibt einem Genugtuung. Das GefĂŒhl, etwas vollbracht zu haben. Vor allem, wenn man schon gar nicht mehr weiß wie lange man eigentlich daran gebastelt hat. Nicht, weil es so lange dauern wĂŒrde – vielmehr weil man in ein Problem gerannt ist und die Lösung immer wieder vor sich her geschoben hat.

Doch zurĂŒck zum wesentlichen: Dem fertigen Produkt. Ich habe es also endlich geschafft mir meinen Open Camera Controller funktionsfĂ€hig zusammen zu löten. Zwischen mir und dem direkten Erfolg standen (wie ich heute herausgefunden habe) eine kalte Lötstelle, ein falsch eingebauter Sockel sowie ein komplett falsch gepoltes Kabel. RĂŒckblickend frage ich mich nun schon, warum mir das nicht von vornherein aufgefallen ist. Aber wie dem auch sei…

Letztendlich ausschlaggebend bei der Fehlersuche war das leichte adaptieren des Mikrocontroller-Codes. Nachdem ich die LED bei der Initialisierung leuchten ließ viel mir auf, dass der Mikrocontroller nicht bootet – was mich auf den Sockel brachte. Nachdem diese HĂŒrde erst einmal genommen war, stellte das falsch gepolte Kabel denn auch keine Herausforderung dar. Hurra!

#define FullPressPin 13   //Pin assignments
#define HalfPressPin 5
#define LEDPin 7

void CloseShutter() {
  digitalWrite(FullPressPin, LOW);
  digitalWrite(HalfPressPin, LOW);
  digitalWrite(LEDPin, LOW);
}

void OpenShutter() {
  digitalWrite(HalfPressPin, HIGH);
  digitalWrite(LEDPin, HIGH);
  digitalWrite(FullPressPin, HIGH);
}


void setup() {
  pinMode(HalfPressPin, OUTPUT);    
  pinMode(FullPressPin, OUTPUT);
  pinMode(LEDPin, OUTPUT);
  digitalWrite(LEDPin, HIGH);
  delay(3000);
  digitalWrite(LEDPin, LOW);
  attachInterrupt(0, CloseShutter, RISING);
  attachInterrupt(1, OpenShutter, FALLING);
}


void loop() {} 

Heute also ist einer dieser fantastischen Tage an denen nahezu alles klappt. Und ich genieße ihn – wohl wissend, dass noch weitere halbfertige Projekte anstehen.

2267 Tage zuvor: Löten nach macht Spaß!

Programmieren ist ja im Grunde genommen nichts anderes als Löten mit der Tastatur: Kreatives kombinieren bekannter Zutaten zu etwas Neuen. Oder, wie manch einer sagen mag, Legos fĂŒr Erwachsene. Auch wenn das in meinen Augen den Legos nicht gerecht wird. Um den heranwachsenden Lego-Fans den Übergang zu vereinfachen, gibt es nun jedenfalls zwei gelungene Anleitungen. Passender Weise im Comic-Format.

Das eine beschĂ€ftigt sich nicht nur mit den Grundlagen des Lötens. Es möchte auch den Spaß vermitteln, den man dabei haben kann. Ob nun beim Basteln nach Anleitung oder eigenen Gehversuchen (allen VĂ€tern sei empfohlen mit einem roten Schalter zu einer bunten Lampe anzufangen – es lohnt sich). Soldering is easy ist im ĂŒbrigen auch bereits in etliche Sprachen ĂŒbersetzt worden.

Das zweite Werk, das mir in dieser Woche untergekommen ist, beschĂ€ftigt sich mit Arduino – und auch hier stehen wieder die Grundlagen im Mittelpunkt. Wenn auch mehr Sinn und Zweck des Open-Source Baukastens denn handwerkliches Know-How. Introduction to Arduino sollte dennoch jedem Bastler einen Blick wert sein – denn die Möglichkeiten des Arduino sind schier endlos (wenn man weiß wie man einen Lötkolben zu bedienen hat).