zurück

Mystery-Box I.

06.06.2019
Mystery-Box

Zu diesem kleinen Projekt inspirierte mich eine Bastelarbeit im Internet. Die "Mystery-Box I." ist ein Behälter, indem kleine Überraschungen (z.B. für Kinder) platziert werden können, die jedoch nur mit einem speziellen Code zugänglich sind.

POV-Ray Code für obiges Bild [2 kB]

Verwendete Bauteile

Beschreibung

Bedienung

Die Mystery-Box öffnet eine Tür (hinter dieser z.B. eine kleine Überraschung versteckt ist) mit einem 4-stelligem Code, welcher mittels vier Tastern eingegeben wird. Stimmt die Reihenfolge der Eingabe, so geht die Tür der Mystery-Box auf. Ein beliebiger Druck auf einen Taster schließt die Tür wieder. Soll der Zugangscode geändert werden, so müssen seitlich gleichzeitig zwei kleine Magneten am Gehäuse platziert werden. Ein kurzes Aufleuchten der Code-LEDs zeigt an, das nun der neue Code eingegeben werden kann. Man muss nun in einer beliebigen Reihenfolge die Taster drücken. Sind alle Taster verwendet worden (entsprechende LED leuchtet), so ist der neue Code eingestellt.

Fehlersuche

Der Mikro-USB-Anschluss kann mit einem PC verbunden werden (voher das Gerät mit dem Hauptschalter von der Batterie trennen). Mit einer seriellen Konsole (z.B. PuTTY oder Arduino IDE) mit einer Übertragungsrate von 9600 Baud können Debug-Meldungen des Sketches empfangen werden und können der Fehlersuche dienen.

Aufbau

Der Aufbau an sich ist relative einfach, denn es müssen nur LEDs, Mikrotaster, Reed-Kontakte und ein Servo-Motor angeschlossem werden. Zusätzlich wird noch eine Stromversorgung mit einer aufladbaren Batterie benötigt.

Schaltplan der Mystery-Box I. (ohne Batterie-Anschluss)
Abb.: Schaltplan der Mystery-Box I. (ohne Batterie-Anschluss)

Sketch

#define PIN_LED_1       A0
#define PIN_LED_2       A1
#define PIN_LED_3       A2
#define PIN_LED_4       A3
#define PIN_BUTTON_1     4
#define PIN_BUTTON_2     5
#define PIN_BUTTON_3     6
#define PIN_BUTTON_4     7
#define PIN_LED_SUCCESS  9
#define PIN_SERVO       10
#define PIN_REED_1      11
#define PIN_REED_2      12

#include <Servo.h>
#include <EEPROM.h>

bool isDoorOpen, openDoor, buttonPressed[4];
byte buttons[4] = {PIN_BUTTON_1, PIN_BUTTON_2, PIN_BUTTON_3, PIN_BUTTON_4};
byte leds[4] = {PIN_LED_1, PIN_LED_2, PIN_LED_3, PIN_LED_4}, doorCode[4];
Servo servoMotor;

void setup()
{
  Serial.begin(9600);
  Serial.print("Init...");
  pinMode(PIN_REED_1, INPUT_PULLUP);
  pinMode(PIN_REED_2, INPUT_PULLUP);

  pinMode(PIN_LED_SUCCESS, OUTPUT);
  digitalWrite(PIN_LED_SUCCESS, LOW);

  for (byte i = 0; i < sizeof(leds); i++) {
    pinMode(leds[i], OUTPUT);
    pinMode(buttons[i], INPUT_PULLUP);
    buttonPressed[i] = false;
  }

  blinkLEDs();
  servoMotor.attach(PIN_SERVO);
  servoMotor.write(0);
  isDoorOpen = false;

  EEPROM.get(0, doorCode);
  Serial.println("ok");

  printDoorCode();
}

void loop()
{
  checkCode();
  if (digitalRead(PIN_REED_1) == HIGH && digitalRead(PIN_REED_2) == HIGH) {
    resetCode();
  }
  checkDoor();
}

void checkCode()
{
  static byte foundOffset = 0, pressOffset = 0, currentState;
  openDoor = false;

  for (byte i = 0; i < sizeof(buttons); i++) {
    currentState = digitalRead(buttons[i]);
    if (!buttonPressed[i] && currentState == LOW) {
      digitalWrite(leds[i], HIGH);
      buttonPressed[i] = true;
      pressOffset++;
      if (doorCode[foundOffset] == i) {
        foundOffset++;
      }
    }
  }

  if (foundOffset >= 4) {
    openDoor = true;
    pressOffset = 0;
    foundOffset = 0;
    delay(200);
  } else {
    if (pressOffset >= 4) {
      pressOffset = 0;
      foundOffset = 0;
      for (byte i = 0; i < sizeof(buttons); i++) {
        delay(200);
        buttonPressed[i] = false;
        digitalWrite(leds[i], LOW);
      }
    }
  }
}

void checkDoor()
{
  if (!isDoorOpen) {
    if (openDoor) {
      digitalWrite(PIN_LED_SUCCESS, HIGH);
      for (byte i = 0; i < sizeof(leds); i++) {
        digitalWrite(leds[i], LOW);
      }
      delay(500);
      servoMotor.write(90);
      isDoorOpen = true;

      delay(1000);
      while (openDoor == true) {
        for (byte i = 0; i < sizeof(buttons); i++) {
          if (digitalRead(buttons[i]) == LOW) {
            openDoor = false;
            break;
          }
        }
      }
    }
  } else {
    if (!openDoor) {
      digitalWrite(PIN_LED_SUCCESS, LOW);
      for (byte i = 0; i < sizeof(leds); i++) {
        buttonPressed[i] = false;
        digitalWrite(leds[i], LOW);
      }
      servoMotor.write(0);
      isDoorOpen = false;
      delay(2000);
    }
  }
}

void resetCode()
{
  servoMotor.write(90);
  for (byte i = 0; i < sizeof(doorCode); i++) {
    doorCode[i] = 255;
  }
  blinkLEDs();
  openDoor = false;
  isDoorOpen = false;
  bool isExisting = false;
  byte offset = 0;
  do {
    for (byte i = 0; i < sizeof(buttons); i++) {
      isExisting = false;
      if (digitalRead(buttons[i]) == LOW && doorCode[offset] == 255) {
        for (byte j = 0; j < sizeof(doorCode); j++) {
          if (doorCode[j] == i) {
            isExisting = true;
          }
        }
        if (!isExisting) {
          digitalWrite(leds[i], HIGH);
          doorCode[offset] = i;
          offset++;
        }
      }
    }
  } while (offset < 4);

  printDoorCode();
  EEPROM.put(0, doorCode); // writing code to EEPROM
  servoMotor.write(0);
  blinkLEDs();
}

void blinkLEDs()
{
  for (byte j = 0; j < 9; j++) {
    for (byte i = 0; i < sizeof(leds); i++) {
      digitalWrite(leds[i], j % 2);
      delay(40);
    }
  }
}

void printDoorCode()
{
  Serial.print("Code:");
  for (byte i = 0; i < sizeof(doorCode); i++) {
    Serial.print(" ");
    Serial.print(doorCode[i]);
  }
  Serial.println("");
}

Prototyp

Zunächst habe ich einen Prototypen auf dem Breadboard aufgebaut und die obige Schaltung mit dem Sketch getestet.

Video: Demo des Prototypen der Mystery-Box I.

Bau der Mystery-Box

- noch nicht vorhanden -