Arduino Projekte – Pollux Labs https://polluxlabs.net Arduino, ESP32 & ESP8266 | Projekte & Tutorials Wed, 03 Jan 2024 21:31:09 +0000 de-DE hourly 1 https://wordpress.org/?v=6.4.4 https://polluxlabs.net/wp-content/uploads/2020/05/cropped-pollux-labs-p-32x32.png Arduino Projekte – Pollux Labs https://polluxlabs.net 32 32 Automatische Pflanzenbewässerung https://polluxlabs.net/arduino-projekte/automatische-pflanzenbewaesserung/ Wed, 20 Dec 2023 14:13:03 +0000 https://polluxlabs.net/?p=15540 Automatische Pflanzenbewässerung Weiterlesen »

]]>
Wenn du deinem Arduino mehr vertraust als deinem grünen Daumen, ist dieses Projekt das richtige für dich. Ein Sensor kontrolliert die Feuchtigkeit im Boden – sobald ein bestimmter Wert unterschritten wird, springt eine Wasserpumpe an und gießt deine Pflanze. Ist der Boden wieder feucht genug, stoppt dein Arduino die Pumpe.

Für dieses Projekt benötigst du folgende Bauteile (jeweils eins):

Bei Amazon findest du auch vollständige Sets, wie z.B. dieses hier:

Aufbau des Projekts mit dem Arduino UNO

Für deine automatische Pflanzenbewässerung benötigst du neben einem Arduino einen Feuchtigkeitssensor, eine Wasserpumpe, ein 5V-Relais und eine Box für vier Batterien mit 1,5 V. Das können wie auf dem Bild unten AAA-Batterien sein, ich selbst habe den gängigen Typ AA verwendet. Die Extra-Batterien benötigst du, weil dein Arduino nicht genug Strom für die Wasserpumpe liefert.

___STEADY_PAYWALL___

Das Breadboard benötigst du nur, um die Erde und die 5V vom Arduino an den Sensor und das Relais weiterzuleiten – du kannst dir hierfür natürlich auch eine andere Lösung überlegen.

Arduino Automatische Pflanzenbewässerung

Orientiere dich beim Aufbau des Projekts an obiger Skizze. Ein Hinweis zum Relais: Die Belegung der Pins kann bei deinem Modell variieren – achte darauf den richtigen Pin für das Signal mit deinem Arduino zu verbinden.

So funktioniert das Projekt

Bevor wir uns dem Sketch zuwenden, zunächst ein paar Worte zur Funktionsweise: Der Feuchtigkeitssensor steckt natürlich in der Erde der Pflanze, die du automatisch gießen lassen möchtest. Am Analogpin (blaues Kabel) liest dein Arduino den aktuellen Feuchtigkeitswert aus. Sobald ein von dir festgelegter Wert überschritten wird, sendet der Arduino ein Signal an das Relais (grünes Kabel).

Nun öffnet das Relais die Verbindung zwischen den Pins NO (Normally Open) und COM (Common Pin). Somit kann also der Strom von den Batterien zur Wasserpumpe fließen. Noch ein Hinweis zur Sicherheit: Ich rate dringend davon ab, Haushaltsgeräte, die nicht für Experimentieren mit Arduino & Co gedacht sind, über ein Relais zu steuern.

Die Pumpe selbst liegt im Wasser und beginnt nun selbiges über einen Schlauch in die Pflanzenerde zu pumpen. Hierdurch verringert sich der Feuchtigkeitswert (obwohl die Feuchtigkeit natürlich steigt). Sobald ein bestimmter Wert unterschritten wurde, die Erde also feucht genug ist, sendet dein Arduino das Signal an das Relais, die Verbindung zwischen Wasserpumpe und Batterien zu schließen.

Der Sketch für die PflanzenBewässerung

Um dein Projekt in Betrieb zu nehmen, sind nur wenige Zeilen Code nötig. Kopiere den folgenden Sketch und lade ihn auf deinen Arduino:

int humidity = 0;
const int humidityPin = A0;
const int pumpPin = 7;

void setup() {
  Serial.begin(9600);
  pinMode(humidityPin, INPUT);
  pinMode(pumpPin, OUTPUT);
}

void loop() {
  humidity = analogRead(humidityPin);
  Serial.print("Feuchtigkeit: ");
  Serial.println(humidity);
  delay(200);

  if(humidity > 900) {
    digitalWrite(pumpPin, HIGH);
    delay(1000);
  }
  else {
    digitalWrite(pumpPin, LOW);
  }
}

Zunächst benötigst du eine Variable für den Feuchtigkeitswert, hier humidity. Anschließend legst du die beiden Pins für den Feuchtigkeitssensor und das Relais fest.

Im Setup startest du nur den Seriellen Monitor und legst du den jeweiligen pinMode fest: Am Pin A0 trifft ein Signal ein (also INPUT), über den Digitalpin 7 gibst du ein Signal aus (also OUTPUT).

Im Loop passiert folgendes: Über den Befehl analogRead() liest du den aktuellen Feuchtigkeitswert aus und zeigst ihn im Seriellen Monitor an – je trockener die Erde, desto höher der Wert. Hier könnte man sich überlegen, ob der Wert eher “Trockenheitswert” heißen sollte. 😉

Falls ein von dir festgelegter Wert (im obigen Sketch ist das der Wert 900) überschritten wird, sendet dein Arduino das Signal HIGH an das Relais. Dort wird dann dafür gesorgt, dass die Wasserpumpe Strom von den Batterien erhält. Falls der Wert nicht überschritten wird, springt der Code wieder zum Anfang des Loops.

So ermittelst du den richtigen Wert: Warte bis die Pflanzenerde so trocken geworden ist, dass du sie eigentlich gießen würdest. Stecke nun den Feuchtigkeitssensor hinein und lies den Wert aus. Diese Zahl kannst du dann in deiner If-Anweisung verwenden.

Ein weiterer Pflanzenwächter

Ist dir dieses Projekt zu groß für die Fensterbank? Auf Pollux Labs findest du noch das Projekt Pflanzenwächter, das einen ATtiny85 verwendet und mit dem Strom einer 1,5V Knopfbatterie auskommt. Allerdings kann dich dieses Projekt nur mit einer LED über zu trockene Erde informieren und nicht selbst gießen.

]]>
Arduino Schnarchstopper mit Künstlicher Intelligenz https://polluxlabs.net/arduino-projekte/arduino-schnarchstopper-mit-kuenstlicher-intelligenz/ Fri, 13 Oct 2023 11:19:01 +0000 https://polluxlabs.net/?p=14697 Arduino Schnarchstopper mit Künstlicher Intelligenz Weiterlesen »

]]>
Schnarchen ist ärgerlich, klar. Dagegen gibt es Geräte, Kissen, Apps und viele andere Mittelchen – aber die meisten davon dürften kaum halten, was sie versprechen. Falls du schnarchst und versprochen hast, dich darum zu kümmern, kannst du mit diesem Tutorial dein Leiden mit deinem Hobby verbinden: Du baust einen Arduino Schnarchstopper mit künstlicher Intelligenz.

Zum Einsatz kommt ein Arduino Nano 33 BLE Sense und ein Vibrationsmotor*. Auf dem Microcontroller läuft ein KI-Modell, das über das Mikrofon des Arduinos erkennt, ob du schnarchst. Ist das der Fall, springt der Motor an und weckt dich (hoffentlich).

Aufbau des Schnarchstoppers

Neben dem Arduino Nano 33 BLE Sense benötigst du nur einen Vibrationsmotor und ein Verbindungskabel für eine 9V-Batterie. Der Motor sollte stark genug sein, um dich wecken zu können – wobei es natürlich auch darauf ankommt, wo du den Schnarchstopper platzierst. Wenn du eine Armbinde verwendest, kann der Vibrationsmotor beispielsweise direkt auf deinem Oberarm oder auch oberhalb des Handgelenks direkt auf deiner Haut aufliegen. Hierfür eignet sich zum Beispiel das Band, das dem Spiel Ring Fit für die Nintendo Switch* beiliegt.

Statt Vibration kannst du natürlich auch zu anderen Mitteln greifen. Ein Piezo-Summer dürfte dich wohl mit Sicherheit aus dem Schlaf reißen – leider aber auch deine Bettgenossin oder deinen Bettgenossen. Im Folgenden bleibst du beim Vibrationsmotor. Der Aufbau sieht dann so aus:

Schnarchstopper Hardware

Falls du einen Arduino mit Header-Pins hast, kannst du die Kabel der beiden Bauteile entsprechend anpassen. Löte hierfür jeweils zwei Kabel mit einer Buchse an, die du dann am Arduino aufstecken kannst. Hier der Aufbau als Skizze:

Skizze des Aufbaus der Hardware

Das passende KI-Modell und der Sketch

Damit der Schnarchstopper dein Schnarchen erkennt, benötigst du ein KI-Modell, das du in deinem Arduino Sketch verwendest.

___STEADY_PAYWALL___

Dieses Tutorial ist angelehnt an diesem Projekt auf GitHub – mit ein paar Anpassungen. Der Maker metanav hat dort schon viel Vorarbeit geleistet, die du weiterverwenden kannst. Lade dir auf GitHub oder direkt hier das Projekt als ZIP-Datei herunter:

Download KI-Modell

Entpacke anschließend die ZIP-Datei und öffne den Sketch tflite_micro_snoring_detection.ino, den du im Ordner Snoring-Guardian-main > snoring_detection_inferencing > examples >tflite_micro_snoring_detection findest.

Anschließend bindest du die mitgelieferte Bibliothek ein. Darin enthalten ist das KI-Modell, das du verwenden wirst. Öffne in der Arduino IDE den Menüpunkt Sketch > Bibliothek einbinden > ZIP-Bibliothek hinzufügen und wähle die Datei Snoring_detection_inferencing.zip

Den Arduino NANO und eine weitere Bibliothek installieren

Falls du du den Arduino Nano 33 BLE Sense in der Arduino IDE noch nicht verfügbar gemacht hast, hole das schnell nach. Öffne hierfür den Boardverwalter im Menü links, suche nach Arduino Nano BLE Sense und installiere die aktuelle Version von Arduino Mbed OS Nano Boards.

Installation des Arduino Nano 33 BLE Sense

Außerdem benötigst du noch die Bibliothek RingBuf, die du über den Bibliotheksverwalter installieren kannst. Aber Achtung: Die gleichnamige Bibliothek funktioniert nicht auf dem Arduino Nano. Installiere stattdessen die Bibliothek RingBuffer von Jean-Luc – Locoduino:

Installation der Bibliothek RingBuffer

Für einen Test wähle in der Arduino IDE dein Board aus und klicke oben links auf den Haken für die Überprüfung des Sketchs. Die Kompilierung nimmt einige Zeit in Anspruch, aber wenn die richtigen Bibliotheken installiert bzw. eingebunden wurden und die Verbindung zum Arduino Nano steht, sollte sie erfolgreich abgeschlossen werden:

Ausgabe nach Upload des Sketchs

Anpassungen im Sketch

Du kannst den Sketch für den Schnarchstopper direkt auf deinen Arduino hochladen und verwenden, aber je nachdem, welchen Vibrationsmotor (oder welches andere Bauteil) du verwendest, musst du ein paar Kleinigkeiten anpassen.

Im Sketch kümmert sich die Funktion void run_vibration() um den Start des Motors. Im Beispiel-Sketch sieht sie wie folgt aus:

void run_vibration()
{
  if (alert)
  {
    is_motor_running = true;

    for (int i = 0; i < 2; i++)
    {
      analogWrite(vibratorPin, 30);
      delay(1000);
      analogWrite(vibratorPin, 0);
      delay(1500);
    }
    
    is_motor_running = false;
  } else {
    if (is_motor_running)
    {
      analogWrite(vibratorPin, 0);
    }
  }
  yield();
}

Hier wird der Motor 3 Mal jeweils für eine Sekunde gestartet, mit einer Pause von 1,5 Sekunden dazwischen. Hierfür wird analogWrite() mit einem Wert von 30 verwendet. Der Vibrationsmotor, den ich verwende, versteht allerdings nur Ein und Aus. Falls das bei dir auch der Fall ist, ändere die betreffende Stelle folgendermaßen:

for (int i = 0; i < 2; i++) {
  digitalWrite(vibratorPin, HIGH);
  delay(5000);
  digitalWrite(vibratorPin, LOW);
  delay(1000);
}

Hier verwendest du digitalWrite() und sendest damit entweder ein HIGH oder LOW an den Motor. Ebenfalls sind dort die Lauf- und Pausenzeiten geändert – die fünf Sekunden zielen hier eher auf Schnarcher mit einem tiefen Schlaf.

Und noch eine Anpassung: Wenn du deinen Vibrationsmotor wie in der Skizze oben an den Pin D2 angecshlossen hast, ändere noch die entsprechende Zeile im Sketch:

int vibratorPin = 2;

Lade nun den Sketch auf deinen Arduino Nano hoch – du findest ihn ganz am Ende dieses Tutorials.

Den Schnarchstopper testen

Jetzt ist es so weit – sobald der Sketch erfolgreich auf deinem Arduino gelandet ist, öffne den Seriellen Monitor in der IDE. Dort siehst du die Vorhersagen, die das KI-Modell macht auf Basis der Geräusche, die es über das eingebaute Mikrofon des Arduinos erhält:

Ausgabe des Schnarchstoppers im seriellen Monitor

Im oben rot markierten Fall war das ein normales Hintergrundgeräusch (noise) mit einer Wahrscheinlichkeit von 99,219 %. Das hier jemand geschnarcht hat, war hingegen nur zu 0,781 % wahrscheinlich.

Es ist vermutlich etwas peinlich, aber imitiere nun mehrmals hintereinander typische Schnarchlaute. Du wirst sehen, dass die interne LED des Arduinos aufleuchtet und sich die Ausgabe im Seriellen Monitor entsprechend verändert. Sobald mehrmals ein Schnarchen erkannt wurde, springt auch der Vibrationsmotor an und vibriert im von dir in der Funktion run_vibration() definierten Rhythmus.

Als nächstes wird es Zeit für ein paar “echte” Tests in der Nacht. Da du deinen Arduino Nano auch mit einer 9V-Batterie versorgen kannst, steht deinen Versuchen im Bett nichts im Wege. Vermutlich musst du mehrere Möglichkeiten der Positionierung des Motors ausprobieren, um von seinen Vibrationen aufzuwachen bzw. um dem Mikrofon des Arduinos zu ermöglichen, dich einwandfrei beim Schnarchen aufzunehmen. Sollte letzteres nicht der Fall sein, kann es zu Fehlalarmen kommen.

Und natürlich gibt es keine Garantie, dass dein neuer Schnarchstopper überhaupt zu ruhigen Nächten führt…

Entwickle dein eigenes KI-Modell

Da du bisher ein vorgefertigtes Modell verwendet hast, ist es möglich, dass es für dich nicht bestmöglich funktioniert. Jeder schnarcht schließlich anders – und die Schnarchgeräusche, die für das Training des Modells verwendet wurden, können stark von deinen eigenen abweichen.

Falls du also einen Schritt weitergehen möchtest, ist das kein Problem – nur etwas Arbeit. Auf Pollux Labs findest du Tutorials, wie du den Service Edge Impulse verwenden kannst, um ein persönliches KI-Modell zu entwickeln. Dort erfährst du, wie du deinen Arduino Nano 33 BLE Sense mit Edge Impulse verbindest, damit Daten sammelst und dein eigenes Modell trainierst. Im letztgenannten Tutorial geht es zwar um Bewegungsdaten, aber ähnlich funktioniert auch das Training mit Audio.

Apropos Audio, um ausreichend Schnarchtöne zu sammeln, eignet sich bereits dein Smartphone. Starte einfach eine Tonaufnahme und lass das Smartphone die Nacht über neben dir liegen. Die entsprechenden Passagen in der Audiodatei kannst du dann in Edge Impulse weiterverarbeiten.

Und nun viel Spaß und Erfolg beim Experimentieren mit deinem Schnarchstopper!

Der vollständige Sketch

Hier nun der gesamte Sketch mit den genannten Anpassungen:

// If your target is limited in memory remove this macro to save 10K RAM
#define EIDSP_QUANTIZE_FILTERBANK   0

/**
   Define the number of slices per model window. E.g. a model window of 1000 ms
   with slices per model window set to 4. Results in a slice size of 250 ms.
   For more info: https://docs.edgeimpulse.com/docs/continuous-audio-sampling
*/
#define EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW 3

/* Includes ---------------------------------------------------------------- */
#include <PDM.h>
#include <Scheduler.h>
#include <RingBuf.h>
#include <snore_detection_inferencing.h>

/** Audio buffers, pointers and selectors */
typedef struct {
  signed short *buffers[2];
  unsigned char buf_select;
  unsigned char buf_ready;
  unsigned int buf_count;
  unsigned int n_samples;
} inference_t;

static inference_t inference;
static bool record_ready = false;
static signed short *sampleBuffer;
static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal
static int print_results = -(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW);

bool alert = false;

RingBuf<uint8_t, 10> last_ten_predictions;
int greenLED = 23;
int vibratorPin = D2;   // Vibration motor connected to D2 PWM pin
bool is_motor_running = false;

void run_vibration() {
  if (alert) {
    is_motor_running = true;

    for (int i = 0; i < 2; i++) {
      digitalWrite(vibratorPin, HIGH);
      delay(5000);
      digitalWrite(vibratorPin, LOW);
      delay(1000);
    }

    is_motor_running = false;
  } else {
    if (is_motor_running) {
      analogWrite(vibratorPin, LOW);
    }
  }
  yield();
}



/**
   @brief      Printf function uses vsnprintf and output using Arduino Serial

   @param[in]  format     Variable argument list
*/
void ei_printf(const char *format, ...) {
  static char print_buf[1024] = { 0 };

  va_list args;
  va_start(args, format);
  int r = vsnprintf(print_buf, sizeof(print_buf), format, args);
  va_end(args);

  if (r > 0) {
    Serial.write(print_buf);
  }
}

/**
   @brief      PDM buffer full callback
               Get data and call audio thread callback
*/
static void pdm_data_ready_inference_callback(void)
{
  int bytesAvailable = PDM.available();

  // read into the sample buffer
  int bytesRead = PDM.read((char *)&sampleBuffer[0], bytesAvailable);

  if (record_ready == true) {
    for (int i = 0; i<bytesRead >> 1; i++) {
      inference.buffers[inference.buf_select][inference.buf_count++] = sampleBuffer[i];

      if (inference.buf_count >= inference.n_samples) {
        inference.buf_select ^= 1;
        inference.buf_count = 0;
        inference.buf_ready = 1;
      }
    }
  }
}

/**
   @brief      Init inferencing struct and setup/start PDM

   @param[in]  n_samples  The n samples

   @return     { description_of_the_return_value }
*/
static bool microphone_inference_start(uint32_t n_samples)
{
  inference.buffers[0] = (signed short *)malloc(n_samples * sizeof(signed short));

  if (inference.buffers[0] == NULL) {
    return false;
  }

  inference.buffers[1] = (signed short *)malloc(n_samples * sizeof(signed short));

  if (inference.buffers[0] == NULL) {
    free(inference.buffers[0]);
    return false;
  }

  sampleBuffer = (signed short *)malloc((n_samples >> 1) * sizeof(signed short));

  if (sampleBuffer == NULL) {
    free(inference.buffers[0]);
    free(inference.buffers[1]);
    return false;
  }

  inference.buf_select = 0;
  inference.buf_count = 0;
  inference.n_samples = n_samples;
  inference.buf_ready = 0;

  // configure the data receive callback
  PDM.onReceive(&pdm_data_ready_inference_callback);

  PDM.setBufferSize((n_samples >> 1) * sizeof(int16_t));

  // initialize PDM with:
  // - one channel (mono mode)
  // - a 16 kHz sample rate
  if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) {
    ei_printf("Failed to start PDM!");
  }

  // set the gain, defaults to 20
  PDM.setGain(127);

  record_ready = true;

  return true;
}

/**
   @brief      Wait on new data

   @return     True when finished
*/
static bool microphone_inference_record(void)
{
  bool ret = true;

  if (inference.buf_ready == 1) {
    ei_printf(
      "Error sample buffer overrun. Decrease the number of slices per model window "
      "(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)\n");
    ret = false;
  }

  while (inference.buf_ready == 0) {
    delay(1);
  }

  inference.buf_ready = 0;

  return ret;
}

/**
   Get raw audio signal data
*/
static int microphone_audio_signal_get_data(size_t offset, size_t length, float * out_ptr)
{
  numpy::int16_to_float(&inference.buffers[inference.buf_select ^ 1][offset], out_ptr, length);

  return 0;
}

/**
   @brief      Stop PDM and release buffers
*/
static void microphone_inference_end(void)
{
  PDM.end();
  free(inference.buffers[0]);
  free(inference.buffers[1]);
  free(sampleBuffer);
}


void setup()
{
  Serial.begin(115200);

  pinMode(greenLED, OUTPUT);
  pinMode(greenLED, LOW); 
  pinMode(vibratorPin, OUTPUT);  // sets the pin as output

  // summary of inferencing settings (from model_metadata.h)
  ei_printf("Inferencing settings:\n");
  ei_printf("\tInterval: %.2f ms.\n", (float)EI_CLASSIFIER_INTERVAL_MS);
  ei_printf("\tFrame size: %d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE);
  ei_printf("\tSample length: %d ms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16);
  ei_printf("\tNo. of classes: %d\n", sizeof(ei_classifier_inferencing_categories) /
            sizeof(ei_classifier_inferencing_categories[0]));

  run_classifier_init();
  if (microphone_inference_start(EI_CLASSIFIER_SLICE_SIZE) == false) {
    ei_printf("ERR: Failed to setup audio sampling\r\n");
    return;
  }

  Scheduler.startLoop(run_vibration);
}

void loop()
{

  bool m = microphone_inference_record();

  if (!m) {
    ei_printf("ERR: Failed to record audio...\n");
    return;
  }

  signal_t signal;
  signal.total_length = EI_CLASSIFIER_SLICE_SIZE;
  signal.get_data = &microphone_audio_signal_get_data;
  ei_impulse_result_t result = {0};

  EI_IMPULSE_ERROR r = run_classifier_continuous(&signal, &result, debug_nn);
  if (r != EI_IMPULSE_OK) {
    ei_printf("ERR: Failed to run classifier (%d)\n", r);
    return;
  }

  if (++print_results >= (EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)) {
    // print the predictions
    ei_printf("Predictions ");
    ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)",
              result.timing.dsp, result.timing.classification, result.timing.anomaly);
    ei_printf(": \n");

    for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
      ei_printf("    %s: %.5f\n", result.classification[ix].label,
                result.classification[ix].value);

      if (ix == 1 && !is_motor_running && result.classification[ix].value > 0.9) {
        if (last_ten_predictions.isFull()) {
          uint8_t k;
          last_ten_predictions.pop(k);
        }

        last_ten_predictions.push(ix);

        uint8_t count = 0;

        for (uint8_t j = 0; j < last_ten_predictions.size(); j++) {
          count += last_ten_predictions[j];
          //ei_printf("%d, ", last_ten_predictions[j]);
        }
        //ei_printf("\n");
        ei_printf("Snoring\n");
        pinMode(greenLED, HIGH); 
        if (count >= 5) {
          ei_printf("Trigger vibration motor\n");
          alert = true;
        }
      }  else {
        ei_printf("Noise\n");
        pinMode(greenLED, LOW); 
        alert = false;
      }

      print_results = 0;
    }
  }
}


#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_MICROPHONE
#error "Invalid model for current sensor."
#endif
]]>
Code-Schloss mit Tastatur und Servo-Motor https://polluxlabs.net/arduino-projekte/code-schloss-mit-tastatur-und-servo-motor/ Mon, 09 Oct 2023 08:46:52 +0000 https://polluxlabs.net/?p=14658 Code-Schloss mit Tastatur und Servo-Motor Weiterlesen »

]]>
In diesem Projekt baust du dir ein Code-Schloss mit einer Folientastatur und einem Servo-Motor. Nur per Eingabe der richtigen Kombination wird sich der Servo-Motor in Bewegung setzen und damit eine mögliche Verriegelung lösen.

DIE FOLIENTASTATUR ANSCHLIESSEN

Für ein Code-Schloss braucht es natürlich ein Gerät, über das man den Code eingeben kann. Hierfür eignet sich die 4×4 Folientastatur perfekt. 

Zunächst installierst du die Verbindung zum Arduino. Die Tastatur besitzt 8 Buchsen; stecke hier ebenso viele Kabel hinein und verbinde diese der Reihe nach mit den Digitalpins 9 bis 2 an deinem Arduino:

Anschluss Folientastatur

DIE PASSENDE BIBLIOTHEK

Um dir die Steuerung der Tastatur so einfach wie möglich zu machen, gibt es eine Bibliothek. Diesmal nutzt du hierfür jedoch nicht den Bibliotheksverwalter, sondern bindest die Bibliothek manuell ein. Lade sie dir zunächst hier herunter.

Wähle nun im Menü der Arduino IDE den Punkt Sketch -> Bibliothek einbinden -> .ZIP Bibliothek hinzufügen

___STEADY_PAYWALL___

Für einen ersten Test der Tastatur verwendest du nun den Beispiel-Sketch, der in der Bibliothek mitgeliefert wird. Öffne diesen unter Datei -> Beispiele -> Keypad -> CustomKeypad

Bevor wir einen Blick auf den Code werfen, lade den Sketch zunächst auf deinen Arduino. Öffne nun den Seriellen Monitor und drücke eine der Tasten auf der Tastatur. Erscheint das entsprechende Zeichen in der Ausgabe? Wenn ja, perfekt.

DER BEISPIEL-SKETCH

Lass uns einen ganz kurzen Blick auf diesen Sketch werfen. Der meiste Code sind Funktionen der Bibliothek Keypad, aber zwei Dinge sind besonders interessant. Zunächst siehst du im Code die Anzahl der Tasten je Reihe und Spalte sowie eine Matrix, die die Werte bzw. Zeichen der Tastatur bestimmt:

const byte ROWS = 4;
const byte COLS = 4;

char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

Das sind die Zeichen, die du auch auf der Tastatur selbst findest. Solltest du einmal andere Zeichen verarbeiten wollen, könntest du diese hier eintragen und damit einer Taste auf der Folientastatur zuweisen.

Der Anschluss der Tastatur am Arduino verbirgt sich in diesen beiden Variablen:

byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};

Das sind die Pins, die du auch im Anschlussplan oben findest. Wenn du einmal einen dieser Pins unbedingt für ein anderes Bauteil verwenden musst, kannst du hier der Tastatur einen abweichenden Digitalpin zuweisen.

Außerdem wird mit diesen Parametern das Objekt customKeypad erzeugt:

Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

Und weiter geht’s – als nächstes installierst du zwei LEDs sowie den Servo-Motor und sorgst dafür, dass dieser sich nur nach der Eingabe des richtigen Codes bewegt.

DAS SCHLOSS AUFBAUEN UND PROGRAMMIEREN

Verbinde als erstes deinen Servo-Motor mit dem Arduino. Du kannst ihn entweder auf deinem Breadboard installieren und von dort aus verbinden – oder du steckst die Kabel des Servos direkt in die Pins GND, 5V und 11, so wie auf dieser Skizze.

Aufbau Code-Schloss

Die Reihenfolge der Anschlüsse GND, VCC und Signal können sich je nach Fabrikat des Motors unterscheiden. Bitte achte hierauf beim Anschluss.

Hinzu kommen noch zwei LEDs samt zwei Vorwiderständen mit je 220Ω. Schließe diese an die Digitalpins 12 und 13 an. Mit diesen zeigst du später an, ob der Code richtig oder falsch eingegeben wurde.

DER SKETCH FÜR DEIN CODE-SCHLOSS

Damit kommen wir schon zum Kern des Projekts. Der Servo soll sich nur bewegen, wenn jemand den richtigen Code per Tastatur eingibt. Dann dreht sich der Zeiger zur Seite und gibt z.B. den Deckel einer Box frei. Wie du das Gehäuse der Box gestaltest, ist natürlich dir überlassen.

Zu Beginn des Sketchs bindest du wie gewohnt zunächst die benötigten Bibliotheken ein:

#include <Keypad.h>
#include <Servo.h>

Anschließend folgen die Informationen für das Keypad, die du schon kennst:

const byte ROWS = 4;
const byte COLS = 4;

char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

Nun benötigst du drei Variablen bzw. Konstanten, die die gedrückte Taste key, den gesamten eigegebenen Code inputCode sowie das von dir hinterlegte Passwort code beinhalten. Gegen letzteres wirst du später die Eingabe prüfen. Wenn du später deinen eigenen Code hinterlegen möchtest, kannst du das hier tun.

char key;
String inputCode;
const String code = "1103A"; //Der von dir festgelegte Code

Zuletzt fehlen noch ein Objekt für den Servo-Motor und die beiden Variablen für die Anschlüsse der LEDs.

Servo servo;
int redLED = 12;
int greenLED = 13;

DIE SETUP-FUNKTION

Hier gibt es sicherlich nichts Neues für dich. Du startest den Seriellen Monitor, legst die pinMode für die LEDs fest und den Anschluss-Pin des Servo-Motors.

void setup() {
 
  Serial.begin(9600);
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  servo.attach(11);
}

DER LOOP

Als erstes benötigst du eine Variable, in der du den Wert der Taste speicherst, die gerade gedrückt wurde. Das ist hier die Variable key mit dem Typ char für Character. Den Wert speicherst du mithilfe der Funktion customKeypad.getKey().

char key = customKeypad.getKey();

Nun folgt eine Reihe von bedingten Anweisungen. Das Code-Schloss verwendet zwei Tasten, um das Schloss zu verriegeln (mit der Taste *) oder die Eingabe zu prüfen (mit #). Diese Tasten darfst du also nicht in deinem hinterlegten Code verwenden. Die erste If-Abfrage “horcht” auf die Taste * und verriegelt das Schloss, indem sie den Servo auf einen Winkel von 90° stellt. Natürlich kannst du diesen Winkel nach deinen Bedürfnissen ändern.

Zusätzlich schaltet sie die rote LED an (und die grüne aus) und leert die Variable inputCode, damit hier für die nächste Eingabe keine “alten” Zeichen mehr zu finden sind.

if (key == '*') {
  inputCode = "";
  Serial.println("Schloss verriegelt.");
  delay(1000);
  servo.write(90);
  digitalWrite(greenLED, LOW);
  digitalWrite(redLED, HIGH);

Die zweite Abfrage folgt gleich darauf mit einem else if und wird angesteuert, wenn die Taste # gedrückt wurde. In diesem Fall folgen wiederum zwei weitere Abfragen – eine, die ausgeführt wird, wenn der Code korrekt eingegeben wurde und die andere, falls dem nicht so ist.

} else if (key == '#') {
  if (inputCode == code) {
    Serial.println("Der Code ist korrekt. Öffne das Schloss...");
    digitalWrite(greenLED, HIGH);
    digitalWrite(redLED, LOW);
    servo.write(0);
  } else {
    Serial.println("Der Code ist falsch!");
    digitalWrite(greenLED, LOW);
    digitalWrite(redLED, HIGH);
  }

Falls der Code stimmt, also inputCode == code zutrifft, leuchtet die grüne LED und der Servo steuert auf 0°. Bei einer inkorrekten Eingabe, leuchtet entsprechend die rote LED – und nichts bewegt sich. In beiden Fällen wird die Variable für den eingegebenen Code wieder geleert:

inputCode = "";

Jetzt hast du alles, um das Schloss auf Tastendruck zu verriegeln. Außerdem um zu prüfen, ob der Code richtig oder falsch ist und entsprechend zu reagieren. Aber wie wird die Variable inputCode eigentlich befüllt?

Das geschieht in einem letzten else – die Anweisung, die bei allen Tasten außer * und # ausgeführt wird. Hier fügst du der Variablen inputCode einfach das zuletzt gedrückte Zeichen hinzu:

} else {
  inputCode += key;
  Serial.println(inputCode);
}

Hier nun der gesamte Sketch – viel Spaß mit deinem neuen Code-Schloss! :=

#include <Keypad.h>
#include <Servo.h>

const byte ROWS = 4;
const byte COLS = 4;

char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

char key;
String inputCode;
const String code = "1103A"; //Der von dir festgelegte Code

Servo servo;
int redLED = 12;
int greenLED = 13;


void setup() {

  Serial.begin(9600);
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  servo.attach(11);
}

void loop() {

  char key = customKeypad.getKey();

  if (key) {

    if (key == '*') {
      inputCode = "";
      Serial.println("Schloss verriegelt.");
      delay(1000);
      servo.write(90);
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, HIGH);

    } else if (key == '#') {
      if (inputCode == code) {
        Serial.println("Der Code ist korrekt. Öffne das Schloss...");
        digitalWrite(greenLED, HIGH);
        digitalWrite(redLED, LOW);
        servo.write(0);

      } else {
        Serial.println("Der Code ist falsch!");
        digitalWrite(greenLED, LOW);
        digitalWrite(redLED, HIGH);
      }

      inputCode = "";

    } else {
      inputCode += key;
      Serial.println(inputCode);
    }
  }
}
]]>
Eine Arduino Alarmanlage mit Geräuschsensor https://polluxlabs.net/arduino-projekte/eine-arduino-alarmanlage-mit-geraeuschsensor/ Fri, 01 Sep 2023 13:05:07 +0000 https://polluxlabs.net/?p=14348 Eine Arduino Alarmanlage mit Geräuschsensor Weiterlesen »

]]>
In diesem Projekt baust du dir deine eigene Arduino Alarmanlage. Diese besteht aus drei Komponenten: einem Geräuschsensor, einem aktiven Piezo-Summer und einer RGB-LED.

Mit dem Geräuschsensor misst du die Umgebungslautstärke. Sobald von dir bestimmte Schwellenwerte unter- bzw. überschritten werden, leuchtet die RGB-LED Grün oder Gelb. Sobald die Lautstärke ein festgelegtes Maß überschreitet, leuchtet die LED in Rot und aus dem Piezo ertönt ein schriller Alarmton.

In den folgenden Abschnitten lernst du, wie du den Geräuschsensor, den Piezo-Summer und die RGB-LED anschließt. Danach erfährst du, wie alle drei Bauteile zusammen die Alarmanlage bilden.

DER GERÄUSCHSENSOR

Zunächst erfährst du, wie du den Geräuschsensor (KY-037, auch Sound Sensor genannt) anschließt und damit Geräusche sowohl analog als auch digital in deinem Arduino UNO verarbeitest.

Die wichtigsten Bauteile des Geräuschsensors, den du hier kennenlernst, sind: das Mikrofon, ein Komparator (hier der LM393, der zwei Spannungen miteinander vergleicht) und ein Potentiometer (um den Schwellenwert einzustellen). Du schließt den Sensor über mindestens 3 der 4 Pins an – Anode, Kathode, Analog- und/oder Digitalausgang.

Sound Sensor on Arduino

ANSCHLUSS AM DIGITALEN AUSGANG

Du kannst den Geräuschsensor auf zwei Arten an deinem Arduino anschließen – analog oder digital. Der digitale Anschluss ist sinnvoll, wenn du etwas in Gang setzen möchtest, sobald ein lautes Geräusch erkannt wird. Das könnte zum Beispiel ein Klopfen an der Tür oder ein Knall sein. So schließt du deinen Sensor an:

Geräuschsensor am Arduino

Versorge deinen Sensor mit Strom über die Pins + und G (für Ground, also Minus) und schließe den digitalen Ausgang (DO) am Arduino am digitalen Eingang 3 an. Den analogen Ausgang (AO) verbindest du als nächstes am Arduino mit dem Pin A1. Und das war es schon.

Kopiere dir nun den folgenden Sketch und lade ihn auf deinen Arduino UNO.

const int sensor = 3;
const int led = LED_BUILTIN;
int noise  = 0;

void setup() {

pinMode(sensor, INPUT);
pinMode(led, OUTPUT);
Serial.begin(9600);

}

void loop() {

noise = digitalRead(sensor);
Serial.println(noise);

if (noise == 1){
  digitalWrite(led, HIGH);
}else{
  digitalWrite(led, LOW);
  }
}

___STEADY_PAYWALL___

Sollte die interne LED des Arduinos jetzt dauerhaft leuchten, bedeutet das, dass der Sensor durchgehend ein Geräusch erkennt. Nimm jetzt einen kleinen Schraubendreher zur Hand und drehe die Schraube am Potentiometer nach links – solange bis die LED ausgeht.

Jetzt erzeuge direkt neben dem Mikrofon ein lautes Geräusch – schnippe zum Beispiel mit den Fingern. Die LED sollte kurz aufleuchten. Falls nicht – drehe die Schraube wieder leicht nach rechts. Mit etwas Fingerspitzengefühl findest du die richtige Feinjustierung. Du kannst auch im Seriellen Monitor nachverfolgen, ob der Sensor ein Geräusch erkennt: Bei “Stille” siehst du dort eine Null, bei einem Geräusch eine 1.

UND JETZT DER ANALOGE AUSGANG

Wenn du den Geräuschsensor analog anschließt, erhältst du in Echtzeit ein Feedback zur Lautstärke. So kannst du zum Beispiel eine LED aufleuchten lassen, sobald eine von dir bestimmte Lautstärke überschritten wird.

Du hast den analogen Ausgang (AO) des Sensors ja bereits mit deinem Arduino verbunden. Lade nun folgenden Sketch hoch.

const int sensor = A1;
const int led = LED_BUILTIN;
int noise  = 0;

void setup() {

pinMode(sensor, INPUT);
pinMode(led, OUTPUT);
Serial.begin(9600);

}

void loop() {

noise = analogRead(sensor);
Serial.println(noise);

if (noise > 200){
  digitalWrite(led, HIGH);
}else{
  digitalWrite(led, LOW);
  }
}

Um die Lautstärke besser verfolgen zu können, starte den Seriellen Monitor und beobachte dort die Sensorwerte. Auch jetzt ist wieder etwas Feinjustierung nötig. Stelle das Potentiometer so ein, dass du im seriellen Monitor Werte siehst, du etwas unter 200 liegen. Wenn du jetzt ein Geräusch machst, das laut genug ist, dass der Wert über 200 schnellt, leuchtet die interne LED des Arduinos auf.

Du siehst also, es reicht hier nicht, dass ein Geräusch erkannt wird. Dieses Geräusch muss auch noch laut genug sein, um die LED einzuschalten.

Die Lautstärke wirst du mit einer RGB-LED darstellen und sobald eine bestimmte Lautstärke überschritten wird, ertönt ein Alarmsignal aus dem Piezo-Summer.

DEN AKTIVEN PIEZO UND DIE RGB-LED ANSCHLIESSEN

Den Geräuschsensor hast du ja bereits installiert. Allerdings benötigst du für die Arduino Alarmanlage nur den Analogausgang (AO) des Sensors. Das Kabel am Digitalausgang kannst du weglassen bzw. entfernen.

Mit der Spieluhr und dem Theremin hast du ja bereits den passiven Piezo-Summer kennengelernt. Wie du weißt, kannst du mit diesem unterschiedliche Töne erzeugen. Nicht so mit dem aktiven Piezo: Dieses Bauteil kann lediglich einen einzigen Ton erzeugen – und macht das, sobald es mit Strom versorgt wird. Für eine Alarmanlage ist das jedoch völlig ausreichend.

Wenn du dir nicht sicher bist, ob dein Piezo aktiv oder passiv ist, lege einfach 5V Spannung direkt von deinem Arduino an. Erklingt ein Ton? Dann ist es der aktive Piezo, den du für dieses Projekt brauchst.

Der Anschluss ist ganz einfach. Verbinde das kurze Bein des Piezo-Summers mit Minus und das lange mit dem Digitalpin 4 an deinem Arduino. Wenn später der Geräuschsensor einen Alarm auslöst, leitest du über diesen Pin Strom an den Piezo, der daraufhin zu piepsen anfängt.

Aufbau Alarmanlage Piezo RGB-LED

Etwas aufwändiger ist der Anschluss der RGB-LED. Insgesamt besitzt sie 4 Beinchen: eine Kathode, die du mit Minus verbindest, und drei Anoden – je eine für die Farben Rot, Grün und Blau. Wie du es von “regulären” LEDs gewohnt bist, musst du auch hier einen 220Ω Vorwiderstand einbauen – hier für jede Anode einen.

Die drei Anoden verbindest du mit den Digitalpins 9, 10 und 11. Diese drei Pins verfügen über die Pulsweitenmodulation (PWM), die du bereits kennengelernt hast, also du die Helligkeit einer einfachen LED gesteuert hast.

Möglicherweise passen die oben gezeigten Farbkanäle und Arduino-Pins je nach Bauart der LED nicht zusammen. Im Beispiel unten ist der rote Farbkanal rechts von der Kathode, was bei deiner LED jedoch anders sein kann. Das kannst du jedoch leicht herausfinden und beheben, wenn du später die Farbe des Lichts umschaltest: Passe einfach die Variablen im Sketch an schreibe hinter den Farbkanal den richtigen Pin:

int ledRed = 10;
int ledGreen = 9;
int ledBlue = 8;

Wenn du alles so wie auf der Skizze oben aufgebaut und verkabelt hast, kann es mit dem Code weitergehen.

DER SKETCH FÜR DIE Arduino ALARMANLAGE

Jetzt, wo du alles auf deinem Breadboard aufgebaut hast, wird es Zeit für das Programm. Im Folgenden erfährst du mehr über die einzelnen Teile des Programms und deren Funktion.

Gleich zu Beginn des Sketchs legst du fest, welche Hardware du an welchen Pins angeschlossen hast. Diese kannst du mit const natürlich auch als Konstanten festlegen. Außerdem benötigst du ein paar Variablen für die Helligkeit der einzelnen Farbkanäle der RGB-LED (z.B. brightnessRed = 150) und die Lautstärke, die der Geräuschsensor misst. Diese legst du zu Beginn auf Null fest.

int ledRed = 11;
int ledGreen = 10;
int ledBlue = 9;

int brightnessRed = 150;
int brightnessGreen = 150;
int brightnessBlue = 150;

int noise = 0;
int sensor = A1;

int piezo = 4;

DIE SETUP-FUNKTION

Hier gibt es vermutlich auch nichts, das du nicht bereits schon kennst. Du legst die Pins der LED und des Piezos als OUTPUT fest und startest den Seriellen Monitor.

void setup() {
 
  pinMode(ledRed, OUTPUT);
  pinMode(ledGreen, OUTPUT);
  pinMode(ledRed, OUTPUT);

  pinMode(piezo, OUTPUT);

  Serial.begin(9600);
}

DER LOOP

Hier wird es nun spannend. Als erstes misst du die Umgebungslautstärke, denn hierauf basieren später alle weiteren Aktionen im Sketch – also ob deine Arduino Alarmanlage anspringt oder nicht.

noise = analogRead(sensor);
Serial.println(noise);

Anschließend folgt die erste bedingte Anweisung. Wenn nämlich der Geräuschpegel unter einem bestimmten Wert liegt, soll die LED grün leuchten – was so viel bedeutet wie “Die Luft ist rein”. Den Wert von 200 (und die folgenden in den weiteren Anweisungen) kannst du natürlich anpassen. Achte auch darauf, dass du beim ersten Start der Alarmanlage den Geräuschsensor so kalibrierst, dass er bei Ruhe unter dem von dir festgelegten Wert liegt.

if(noise <= 200){
  analogWrite(ledGreen, brightnessGreen);
  analogWrite(ledRed, 0);
  analogWrite(ledBlue, 0);
  digitalWrite(piezo, LOW);
  }

Wie erwähnt, soll in diesem Zustand die LED grün leuchten. Das erreichst du, indem du nur den grünen Farbkanal mit der von dir festgelegten Helligkeit brightnessGreen aufleuchten lässt. Die beiden anderen Kanäle für Rot (Red) und Blau (Blue) erhalten die Helligkeit Null, sind also aus. Du kannst natürlich auch Farben mischen (auch wenn die LED diese nicht sehr differenziert darstellen kann) – hierfür eignet sich z.B. dieses RGB Color Wheel.

Auch der Piezo soll hier nicht ertönen, weswegen du keinen Strom an ihn leitest. Das erreichst du mit dem Parameter LOW in der Funktion digitalWrite().

EINE WEITERE ANWEISUNG

Wenn nun der Geräuschpegel etwas ansteigt, aber immer noch nicht hoch genug für einen Alarm ist, kommt eine zweite bedingte Anweisung ins Spiel – mit else if{}.

else if(noise > 200 && noise <= 350){
  analogWrite(ledRed, brightnessRed);
  analogWrite(ledGreen, brightnessGreen);
  analogWrite(ledBlue, 0);
  digitalWrite(piezo, LOW);
  }

Diese Befehle werden ausgeführt, wenn die Lautstärke zwischen 201 und 350 liegt. Wie gesagt, experimentiere mit diesen Werten, um sie an deine Gegebenheiten anzupassen.

Befindet sich also die Lautstärke in diesem Bereich, wechselt das Licht der LED von Grün zu Gelb. Für diese Farbe gibt es keinen eigenen Farbkanal, weswegen du sie kurzerhand mischst. Gelb ist eine Mischung aus Rot und Grün. Deshalb schaltest du diese Farbkanäle der LED und lässt den blauen Kanal erlöschen.

ALARM!

Wenn es nun noch lauter wird, soll der Alarm ertönen. Die LED strahlt in einem satten Rot und der Piezo-Summer fängt an zu piepsen.

else if(noise > 350){
  analogWrite(ledRed, brightnessRed);
  analogWrite(ledGreen, 0);
  analogWrite(ledBlue, 0);
  digitalWrite(piezo, HIGH);
  delay(10000);
  }

Diesmal schaltest du also nur den roten Kanal der LED ein. Außerdem leitest du nun Strom vom Arduino an den Piezo – mit der Funktion digitalWrite(piezo, HIGH);

Sicherlich sollte eine Alarmanlage so lange Krach machen, bis sie ausgeschaltet wird. Für ein erstes Experiment reicht jedoch vielleicht auch erst einmal eine Sekunde. Deshalb befindet sich am Ende noch ein delay() von 1.000 Millisekunden.

Und das war es! Lade den folgenden Sketch auf deinen Arduino, kalibriere deinen Geräuschsensor und probiere deine Arduino Alarmanlage aus.

int ledRed = 11;
int ledGreen = 10;
int ledBlue = 9;

int brightnessRed = 150;
int brightnessGreen = 150;
int brightnessBlue = 150;

int noise = 0;
int sensor = A1;

int piezo = 4;

void setup() {
 
  pinMode(ledRed, OUTPUT);
  pinMode(ledGreen, OUTPUT);
  pinMode(ledRed, OUTPUT);

  pinMode(piezo, OUTPUT);

  Serial.begin(9600);

}

void loop() {

  noise = analogRead(sensor);
  Serial.println(noise);

  if(noise <= 200){
    analogWrite(ledGreen, brightnessGreen);
    analogWrite(ledRed, 0);
    analogWrite(ledBlue, 0);
    digitalWrite(piezo, LOW);
    }
    else if(noise > 200 && noise <= 350){
      analogWrite(ledRed, brightnessRed);
      analogWrite(ledGreen, brightnessGreen);
      analogWrite(ledBlue, 0);
      digitalWrite(piezo, LOW);
      }
      else if(noise > 350){
        analogWrite(ledRed, brightnessRed);
        analogWrite(ledGreen, 0);
        analogWrite(ledBlue, 0);
        digitalWrite(piezo, HIGH);
        delay(10000);
        }
}

Apropos Piezo: Im verlinkten Tutorial erfährst du, wie du einen passiven Piezo-Summer verwenden kannst.

]]>
Ein Babyphone mit künstlicher Intelligenz und einem Arduino Nano 33 BLE Sense https://polluxlabs.net/arduino-projekte/ein-babyphone-mit-kuenstlicher-intelligenz-und-einem-arduino-nano-33-ble-sense/ Mon, 18 Jan 2021 22:36:23 +0000 https://polluxlabs.net/?p=4884 Ein Babyphone mit künstlicher Intelligenz und einem Arduino Nano 33 BLE Sense Weiterlesen »

]]>

Ein Babyphone ist eine praktische Sache, sollte das eigene Kleinkind mal außer Hörweite sein. Im Prinzip ist solch ein Gerät nichts anderes als ein Sender mit Mikrofon, der per Funk Geräusche an einen Empfänger überträgt. Weint oder schreit ein Baby aus dem Lautsprecher, erkennt jeder Mensch sofort, was hier los ist.

Aber kann eine künstliche Intelligenz auch lernen, Weinen und Schreien von anderen Geräuschen zu unterscheiden? Klar! Hier stellen wir ein Projekt vor, das mithilfe von Machine Learning und TinyML genau das macht. Alles was du dafür brauchst, ist ein Arduino Nano 33 BLE Sense und einen kostenlosen Account bei Edge Impulse.

Fortgeschrittene

3 – 4 Stunden

ca. 40€

Für dieses Projekt benötigst du:

Arduino® Board Nano 33 BLE Sense with headers
Arduino® Board Nano 33 BLE Sense with headers
Arduino Board Nano 33 BLE Sense with headers; Inhalt: 1 Stück

Das vorgestellte Projekt stammt vom Maker Ish Ot Jr. und wurde im Arduino Project Hub veröffentlicht. Du findest die Beschreibung (Englisch) hier. Im Folgenden beschäftigen wir uns mit den Voraussetzungen für das Babyphone mit KI, gehen auf wichtige Aspekte genauer ein und geben einen Ausblick auf weitere Anwendungen und Möglichkeiten.

Grundlagen

Das Babyphone mit dem Arduino Nano 33 BLE Sense funktioniert im Kern so: Zunächst sammelst du Geräusche von (d)einem Baby, die die Künstliche Intelligenz später erkennen soll. Damit sie diese von allen möglichen anderen Geräuschen unterscheiden kann, benötigst du auch Nebengeräusche, die im Kinderzimmer auftreten können – und zwar so viele Samples wie möglich, auch von der Stille eines träumenden Babys. 😉

Die Audiodaten kannst du direkt mit deinem Arduino sammeln. Wenn du noch nicht weißt, wie das geht, lese zunächst diese beiden Tutorials:

Wie du siehst, steht der Service von Edge Impulse im Mittelpunkt. Diesen kannst du kostenlos nutzen, um Daten zu sammeln, zu KI-Modellen zu verarbeiten und auf einem Microcontroller zu deployen.

Audio sammeln und ein Modell entwickeln

Wenn du nun weißt, wie du grundsätzlich Daten mit deinem Arduino Nano sammelst und in Edge Impulse speicherst, kannst du damit loslegen. Im Projekt im Arduino Project Hub legt der Autor zwei Labels an: Weinen (crying) und Geräusche (noise).

Wenn du für jedes deiner Labels mehrere Minuten Audio gesammelt hast, kann es weitergehen. In seinem Tutorial im Arduino Project Hub erläutert der Autor, welche Einstellungen er für sein Impulse Design verwendet. Damit erhält er eine Genauigkeit seines Modells von gut 86%.

Investiere in diesen Schritt des Projekts ruhig etwas Zeit und spiele mit den Einstellungen herum. Es ist wichtig, dass die einzelnen Labels (bzw. Features) gut von einander unterscheidbar sind, wie hier zu sehen. Diese Daten stammen aus einem anderem KI-Projekt, bei dem es um das Erkennen von Gesten geht.

KI-Modell in Edge Impulse
Beispiel für gut getrennte Features

Wenn du auf keinen grünen Zweig kommst, könnte eine Möglichkeit sein, einfach noch mehr Daten zu sammeln. Je mehr Material deine KI zum Lernen hat, desto besser. Achte auch darauf, dass du in Edge Impulse auch genügend Testdaten hast – diese dürfen sich nicht mit den Trainingsdaten überschneiden, um zuverlässige Ergebnisse zu erhalten.

So bringst du die KI auf deinen Arduino

Wenn du zufrieden bist mit deinem KI-Modell, wähle unter dem Menüpunkt Deployment die Kachel Arduino Library und lade dir die ZIP-Datei herunter. Hier enthalten sind eine Bibliothek und ein Sketch, den du im Folgenden etwas modifizierst.

Du könntest unter Deployment auch eine Firmware für deinen Arduino Nano 33 BLE Sense erstellen lassen. Dann könntest du die Auswertungen der KI jedoch nur im Seriellen Monitor verfolgen – etwas unpraktisch für ein Babyphone. Deshalb kommt der Sketch ins Spiel.

Im Tutorial im Project Hub geht der Autor sehr genau auf seine Anpassungen ein und erklärt, wie er die direkt am Arduino verbaute RGB LED verwendet, um darzustellen, ob ein Baby gerade weint oder nicht. Grün steht hier für “Alles in Ordnung”, also dafür, dass die Künstliche Intelligenz nur Noise erkennt. Rot hingegen für Weinen.

Wie geht es weiter?

Das vorgestellte Projekt zeigt sehr anschaulich, wie man mit einem einigermaßen günstigen Microcontroller und Edge Impulse relativ einfach ein KI-Projekt umsetzen kann. Du könntest das Modell noch verfeinern und nicht alles was nicht Weinen ist, einfach unter Noise zusammenfassen. So könnten weitere Labels die Ergebnisse noch verbessern.

Für diese detailliertere Auswertung ist die interne RGB LED vermutlich nicht ausreichend. Auf Pollux Labs findest du viele Tutorials zu Displays und auch zu einem NeoPixel LED Ring.

Wie sieht es mit anderen Geräuschen aus? Duscht gerade jemand? Oder schleudert deine Waschmaschine unruhig und könnte bald kaputtgehen? Das könnten alles Anwendungsfälle für dich sein. 🙂

]]>
Arduino Wettervorhersage https://polluxlabs.net/arduino-projekte/arduino-wettervorhersage/ Wed, 02 Dec 2020 10:34:52 +0000 https://polluxlabs.net/?p=4363 Arduino Wettervorhersage Weiterlesen »

]]>
Eine Wetterstation mit aktuellen Werten ist eine Sache – aber zu wissen, wie das Wetter in einigen Stunden sein wird, eine ganz andere. In diesem Projekt baust du dir so eine einfache Wettervorhersage mit dem Luftdrucksensor BMP180 und einem Servo.

Zugegeben, mit den Meteorologen in den Nachrichten kann dieses Projekt nicht mithalten, aber möglicherweise kann es dich vor den ganz großen Wetterumschwüngen warnen.

Anfänger

1 – 2 Stunden

ca. 10 € + Arduino

Für dieses Projekt benötigst du (Mengen s. Beschreibung):

So funktioniert die Wettervorhersage

Wie eingangs erwähnt, ist eine Wettervorhersage eine komplexe Angelegenheit, an der Spezialisten mit Großcomputern arbeiten. Es gibt jedoch einen Zusammenhang, den wir uns in diesem Projekt zunutze machen: Steigt der Luftdruck, bessert sich das Wetter – fällt er, wird das Wetter schlecht.

Auch das ist eine starke Vereinfachung der Realität sein, aber dieser Zusammenhang soll uns hier einmal genügen. Immerhin wird dieses Prinzip schon seit Jahrhunderten angewandt. Sicherlich kennst du alte Barometer wie dieses hier:

Dosen-Barometer, Quelle: Wikipedia/Langspeed

Mehr über Barometer und die möglichen Anwendungen erfährst du auf Wikipedia. In unserer Arduino Wettervorhersage messen wir in regelmäßigen Abständen den Luftdruck und vergleichen ihn mit dem zuletzt gemessenen Wert. Fällt der Luftdruck immer weiter, dreht ein Servo-Motor einen Zeiger nach links in Richtung schlechtes Wetter. Wenn der Luftdruck kontinuierlich steigt, bewegt sich der Zeig nach rechts – es wird also gutes Wetter geben. Übrigens: Mit unserer ESP8266 Wetterstation speicherst du Daten zum Luftdruck lokal in einer Datenbank.

Luftdruck messen mit dem BMP180

Für die Messung des Luftdrucks verwenden wir den Sensor BMP180. Du kannst auch den genaueren BMP280* oder einen BME280* verwenden. Letzterer misst auch die Luftfeuchte, die wir in diesem Projekt jedoch nicht brauchen.

Diese Sensoren lassen sich leicht per I²C anschließen und mit einer passenden Bibliothek komfortabel verwenden. In diesem Tutorial erfährst du mehr darüber, wie du den BMP180 anschließt und verwendest.

Das Wetter mit einem Servo anzeigen

Es gibt viele denkbare Möglichkeiten, um die Veränderungen des Luftdrucks anzuzeigen: Verschiedene Displays oder auch ein NeoPixel LED-Ring. Hier verwenden wir jedoch einen Servo-Motor und eine passende Schablone. Diese können z.B. Kinder farbig gestalten und sie hat ebenso den gewissen Retro-Charme. 🙂

Schablone für den Servo der Wettervorhersage
Schablone für den Servo

Was ein Servo-Motor ist, wie funktioniert und was es alles zu beachten gibt, erfährst in diesem Tutorial zu Servos.

Der Aufbau der Arduino Wettervorhersage

Es dauert nur wenige Minuten, die Wettervorhersage auf deinem Breadboard aufzubauen. Orientiere dich hierbei an diesem Schema:

Aufbau der Arduino Wettervorhersage

Achte darauf, dass du den Servo mit 5V und den BMP180 mit 3,3V versorgst. Die Beschriftung der Pins des BMP180 befindet sich auf seiner Unterseite – vergewissere dich, dass du sie richtig am Arduino angeschlossen hast, bevor du ihn mit Strom versorgst.

Der Sketch

Es sind nicht viele Zeilen Code nötig, um die Wettervorhersage zum Laufen zu bringen. Starte wie so oft, indem du die nötigen Bibliotheken einbindest. Wie du sie installierst, erfährst du in den oben genannten Tutorials.

#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <Servo.h>

Anschließend erstellst du zwei Objekte – eines für den Luftdruck-Sensor und eines für den Servo:

Adafruit_BMP085 bmp;
Servo myServo;

Dazu benötigst du noch ein paar Variablen, um die Werte des Sensors und die gewünschte Position des Servos zu speichern:

int servoPosition;
long currentPressure;
long oldPressure;
int delta;

Die Setup-Funktion

Hier startest du den Seriellen Monitor und vergewisserst dich, dass der BMP180 richtig angeschlossen und funktionstüchtig ist. Anschließend weist du dem Servo den Anschlusspin 8 zu und drehst den Zeiger nach oben – auf 90°.

void setup() {
  Serial.begin(115200);
  if (!bmp.begin()) {
    Serial.println("Sensor not found!");
    while (1) {}
  }

  myServo.attach(8);
  myServo.write(90);
}

Übrigens: Wenn du nicht weißt, in welcher Position sich dein Servo gerade befindet und in welche Position der Zeiger bei der Montage schauen soll, dann bringe ihn erst nach dem Start an. Zu Beginn des Sketchs steht der Servo auf 90° – sodass der Zeiger nach oben gerichtet ist.

Der Loop der Arduino Wettervorhersage

Hier misst du als erstes den aktuellen Luftdruck und gibst ihn im Seriellen Monitor aus:

  currentPressure = bmp.readPressure();
  Serial.print("Current Pressure = ");
  Serial.print(currentPressure);
  Serial.println(" Pa");

Wie du siehst, geht das ganz einfach mit der Funktion bmp.readPressure(). Gleichzeitig speicherst du diesen Wert – der in Pascal ausgegeben wird – in der Variablen currentPressure.

Danach fragst du ab, ob sich der aktuelle Luftdruck gegenüber der Messung davor (gespeichert in der Variablen oldPressure) verändert hat. Falls ja, speicherst du diese Veränderung in der Variablen delta.

 if (oldPressure && currentPressure != oldPressure) {
   delta = currentPressure - oldPressure;

Im If-Statement siehst du die Bedingung oldPressure && – diese befindet sich hier, da es im ersten Messdurchgang noch keine alte Messung gibt. Erst wenn in dieser Variablen eine Zahl hinterlegt ist – sie also nicht mehr auf 0 bzw. false steht – wird diese Bedingung wahr. Alternativ kannst du auch folgendes schreiben:

 if (oldPressure == true && currentPressure != oldPressure) {

Den Servo steuern

Kommen wir zum Servo und der Anzeige der Wetterlage. Um die Veränderung des Luftdrucks in der Variablen delta anzuzeigen, musst du dem Servo mitteilen, wo er sich hindrehen soll. Ein Servo kann eine Position zwischen 0° und 180° einnehmen – zu Beginn des Sketchs steht er in der Mitte, also auf 90°.

Wir nehmen mal an, dass die maximale Veränderung in unserem Messzeitraum (mehr dazu gleich) bei +- 100 Pa liegt. Bei -100 Pa soll der Servo auf 0° fahren, bei +100 Pa entsprechend auf 180°. Hinweis: Möglicherweise liegen wir mit dieser Einschätzung falsch – hier sind also deine eigenen Experimente gefragt. Verfolge im Seriellen Monitor die Messwerte und kalibriere deine Wetterstation entsprechend.

Jedenfalls musst du die beiden Wertebereiche +-100 Pa und 0-180° unter einen Hut bringen. Hierfür bietet sich die Funktion map() an:

servoPosition = map(delta, -100, 100, 0, 180);

Hier nimmst du die aktuelle Veränderung delta, ihren möglichen Wertebereich +-100 und “mappst” diesen Wert auf die möglichen Winkel des Servos: 0° bis 180°. Heraus kommt der Winkel, der der Veränderung des Luftdrucks entspricht. Diesen speicherst du in der Variablen servoPosition.

Anschließend steuerst du deinen Servo auf diese Position:

myServo.write(servoPosition);

Danach machst du die aktuelle Messung zur alten Messung oldPressure, mit der du die nächste vergleichst. Und als letztes wartest du eine gewisse Zeit bis zur Messung, in diesem Fall 5 Minuten bzw. 300.000 Millisekunden.

oldPressure = currentPressure;
delay(300000);

Hier nun der gesamte Sketch der Arduino Wettervorhersage zum Rauskopieren und Hochladen. Viel Spaß! 🙂

#include <Wire.h>
#include <Adafruit_BMP085.h>

#include <Servo.h>

Adafruit_BMP085 bmp;
Servo myServo;

int servoPosition;
long currentPressure;
long oldPressure;
int delta;

void setup() {
  Serial.begin(115200);
  if (!bmp.begin()) {
    Serial.println("Sensor not found!");
    while (1) {}
  }

  myServo.attach(8);
  myServo.write(90);
}

void loop() {
  currentPressure = bmp.readPressure();
  Serial.print("Current Pressure = ");
  Serial.print(currentPressure);
  Serial.println(" Pa");

  if (oldPressure && currentPressure != oldPressure) {
    delta = currentPressure - oldPressure;
    Serial.print("Change: ");
    Serial.print(delta);
    Serial.println();
  }

  servoPosition = map(delta, -100, 100, 0, 180);
  myServo.write(servoPosition);
  
  oldPressure = currentPressure;

  delay(300000);
}

Fehlen dir noch Bauteile? Dann wirf einen Blick in unsere Übersicht der besten Arduino Starter Kits.

]]>
Komplexe Gesten erkennen mit künstlicher Intelligenz und deinem Arduino https://polluxlabs.net/arduino-projekte/komplexe-gesten-erkennen-mit-kuenstlicher-intelligenz-und-deinem-arduino/ Wed, 26 Aug 2020 16:31:06 +0000 https://polluxlabs.net/?p=2257 Komplexe Gesten erkennen mit künstlicher Intelligenz und deinem Arduino Weiterlesen »

]]>
In diesem Projekt entwickelst du ein KI-Modell, das Gesten wie Kreisbewegungen und Winken erkennen kann. Anschließend lädst du es auf deinen Arduino Nano 33 BLE Sense und lässt dir die erkannten Bewegungen im Terminal deines PCs oder Macs anzeigen.

Mit diesem Setting kannst du später aufwändigere Projekte bauen, um z.B. das Licht durch Gesten an- und ausschalten zu können.

Anfänger

1 – 2 Stunden

Für dieses Projekt benötigst du:

Einen kostenlosen Account bei Edge Impulse und einen Arduino Nano 33 BLE Sense.

Arduino® Board Nano 33 BLE Sense with headers
Arduino® Board Nano 33 BLE Sense with headers
Arduino Board Nano 33 BLE Sense with headers; Inhalt: 1 Stück

Vorbereitungen

In unserem Tutorial Gesten erkennen mit dem Sensor APDS9960 haben wir beschrieben, wie du mit dem Arduino Nano 33 BLE Sense Bewegungen nach oben, unten, rechts und links erkennen kannst. Dieser Microcontroller kann aber deutlich mehr!

Du kannst ihn mit ein paar Vorbereitungen mit dem Service von Edge Impulse verbinden und seinen Beschleunigungssensor verwenden, um viel anspruchsvollere Gesten und Muster erkennen zu können.

Lies zunächst nach, wie du deinen Arduino mit Edge Impulse verbindest.

Bewegungsdaten sammeln

Am Anfang jeder künstlichen Intelligenz stehen Daten. Das bedeutet, dass du zunächst Daten zu den Bewegungen sammeln musst, die du später voneinander unterscheiden möchtest.

In diesem Tutorial lernst du, wie du Bewegungsdaten mit dem Arduino Nano 33 BLE Sense sammeln und speichern kannst. Auf dieses Tutorial bauen wir hier auf.

In diesem Projekt nutzt du dieses Wissen und bringst deinem Arduino bei zu erkennen, ob du eine Kreisbewegung ausführst, in der Luft winkst oder – nichts tust. Öffne in Edge Impulse als den Menüpunkt Data acquisition und sammle Samples für die zwei Bewegungen und den Ruhezustand – jeweils circa 3 Minuten.

Achte darauf, dass sich deine Bewegungen innerhalb einer Geste nicht zu sehr unterscheiden. Eine leichte Varianz ist aber normal und auch gut. Wenn du fertig bist, sollte dein Screen ungefähr so aussehen:

Anschließend geht es mit dem Training des KI-Modells weiter.

Einen Impulse entwickeln

Jetzt geht es weiter mit dem nächsten Menüpunkt: Impulse design. Hier entwickelst du aus deinen Rohdaten sogenannte Features, mit denen später deine Bewegungen analysiert und zugeordnet werden können.

Links siehst du die Karte Time series data – hier musst du zunächst nichts einstellen. Klicke stattdessen rechts daneben auf Add a processing block und wähle anschließend den Eintrag Spectral Analysis. Dieser Block eignet sich besonders für Bewegungsdaten.

Wähle eine Karte weiter den Eintrag Neural Network (Keras). Klicke zuletzt auf Save Impulse.

Neben dem Menüpunkt Create impulse sollte nun ein grüner Punkt erscheinen. Klicke nun gleich darunter auf Spectral features und anschließend oben auf Generate features.

Features generieren in Edge Impulse

Hier gibt es nichts weiter zu tun als auf den Button Generate features zu klicken. Diese Prozedur läuft nun durch und sollte nur wenige Sekunden dauern. Sobald sie abgeschlossen ist, siehst du rechts eine Visualisierung der Features und der Cluster, die sie bilden.

Die fertig generierten Feature-Cluster in Edge Impulse

Wie du oben siehst, bilden die verschieden farbigen Punkte eigene Cluster, die voneinander entfernt liegen. Das sollte auch bei deinen Bewegungsdaten der Fall sein. Je besser du die Cluster voneinander unterscheiden kannst, desto besser kann das auch später dein KI-Modell.

Solltest du nur einen Haufen bunter Punkte sehen, gehe noch einmal zurück und sammle weitere oder neue Bewegungsdaten.

Das neuronale Netz trainieren

Edge Impulse hat nun klar definierte Daten und Klassen, die gut voneinander zu unterscheiden sind. Fehlt nur noch ein neuronales Netz, das neue Daten einem dieser Klassen zuordnen kann.

___STEADY_PAYWALL___

Kurz gesagt, ist ein neuronales Netz nichts anderes als Algorithmen, die versuchen Muster zu erkennen. Auf Wikipedia lernst du mehr über dieses Thema.

Klicke nun im Menü auf den nächsten Punkt NN Classifier.

Der NN Classifier in Edge Impulse

Belasse die Einstellungen zunächst so wie sie sind und klicke auf den Button Start training. Das nun folgende Training des Netzes sollte wenige Minuten in Anspruch nehmen.

Anschließend erscheint eine neue Karte mit den Ergebnissen. Oben links siehst du unter Accuracy, wie akkurat dein neuronales Netz arbeitet. In unserem Fall kam eine Genauigkeit von 100% heraus, was darauf hoffen lässt, dass die Bewegungen und Gesten richtig erkannt werden.

Ergebnisse des Trainings des neuronalen Netzes

Wenn du eine niedrigere Genauigkeit erhalten hast, findest du hinter dem Link Model performing poorly? unten rechts Tipps, wie du ein besseres KI-Modell entwickeln kannst.

Ein erster Test der künstlichen Intelligenz

Jetzt wird es spannend: Erkennt deine KI die Bewegungen, die du mit deinem Arduino Nano 33 BLE Sense ausführst, richtig?

Klicke im Menü auf den Punkt Live classification. Hier kannst einen ersten Test starten, indem du auf den Button Start sampling klickst und eine der trainierten Bewegungen ausführst.

Nachdem du das Sample aufgenommen hast, erscheint das Ergebnis. Wir haben eine Kreisbewegung ausgeführt, was die künstliche Intelligenz richtig der Klasse circle zugeordnet hat.

Ergebnis der Klassifizierung in Edge Impulse

Sollte das bei dir nicht funktioniert haben, gehe am besten wieder ein paar Schritte zurück und versuche bessere Bewegungsdaten zu sammeln oder dein neuronales Netz besser zu trainieren.

Wenn du aber zufrieden bist, wird es Zeit die KI auf deinen Arduino zu bringen.

Die KI auf dem Arduino ausführen

Klicke hierfür auf den Menüpunkt Deployment und wähle unter der Überschrift Build firmware den Arduino Nano 33 BLE Sense.

Du kannst dir auch eine Arduino-Bibliothek erstellen lassen, die du in einen Sketch einbinden kannst. Wir bleiben hier jedoch bei der einfacheren Variante.

Die Firmware für den Arduino Nano 33 BLE Sense erstellen

Weiter unten hast du auch die Möglichkeit, Optimierungen an deinem KI-Modell vorzunehmen, aber auch diese lassen wir hier erst einmal beiseite.

Klicke als nächstes auf den Button Build. Jetzt wird die Firmware mit deinem KI-Modell erstellt, was wieder einige Minuten dauern kann.

Als nächstes erhältst du eine Zip-Datei mit der Firmware. Führe, je nachdem welches Betriebssystem du verwendest, eine der folgenden Dateien aus:

  • flash_windows.bat
  • flash-mac.command
  • flash_linux.sh

Achte darauf, dass du das Terminal, in dem das Sampling der Daten läuft, vorher schließt und diesen Prozess beendest.

Öffne nach dem Installieren der Firmware ein neues Terminal-Fenster und führe diesen Befehl aus:

edge-impulse-run-impulse

Jetzt läuft deine KI in diesem Terminal und prüft alle zwei Sekunden, ob sie eine Bewegung deines Arduinos erkennt und wenn ja, welche. Hier hat sie mit einer Wahrscheinlichkeit von 96% ein Winken erkannt – was stimmte:

Die KI hat das Winken richtig erkannt

Wie geht es weiter?

Du hast jetzt eine funktionierende künstliche Intelligenz auf deinem Arduino, die komplexe Bewegungen und Gesten erkennen kann.

Gehe einen Schritt weiter und integriere sie in ein neues Projekt, das du mit Gesten steuern kannst. Dein Arduino Nano 33 BLE Sense verfügt auch über ein Mikrofon, das du in Edge Impulse verwenden kannst. Sammle Geräusche und entwickle eine KI, die diese unterscheiden kann. Deiner Fantasie sind keine Grenzen gesetzt! 🙂

Edge Impulse ist übrigens nicht der einzige Service, mit dem relativ leicht KI-Modelle erstellen kannst: In diesem Tutorial stellen wir dir Googles Teachable Machine vor.

]]>
Ein einfacher Arduino-Countdown mit Retro-Optik https://polluxlabs.net/arduino-projekte/ein-einfacher-arduino-countdown-mit-retro-optik/ Sat, 08 Aug 2020 11:08:22 +0000 https://polluxlabs.net/?p=2095 Ein einfacher Arduino-Countdown mit Retro-Optik Weiterlesen »

]]>
In diesem Projekt baust du dir einen Arduino-Countdown, der auf Knopfdruck einen Timer startet und die Sekunden auf einem Display herunterzählt.

Für das gewisse Etwas sorgt eine 7-Segment-Anzeige und der Umstand, dass du z.B. dein Ei nicht in 7 Minuten kochst, sondern in 420 Sekunden.

Das haben wir für dieses Projekt verwendet (Mengen siehe unten):

Der Aufbau

Für den Countdown benötigst du drei Bauteile: eine 7-Segment-Anzeige*, einen passiven Piezo-Summer und einen Button, den du mit einem Pull-down-Widerstand mit deinem Arduino verbindest.

In diesem Projekt verwenden wir einen Arduino Uno*, aber du kannst natürlich so gut wie jedes andere Board verwenden. Außerdem benötigst du noch ein Breadboard und ein paar Kabel.

Die 7-Segment-Anzeige anschließen

Los geht es mit dem Display, auf dem der Countdown läuft. Daran befinden sich fünf Pins, die du wie folgt an deinem Arduino anschließt:

7-Segment-AnzeigeArduino
VCC5V oder 3,3V
GNDGND
DIN12
CS10
CLK11

Wir verwenden ein Display mit 8 Ziffern, das dir ermöglichen würde, die Sekunden von gut drei Jahren herunterzuzählen. Du kannst aber natürlich auch ein kleineres verwenden – der später vorgestellte Sketch funktioniert mit jeder Anzeige, die per MAX7219- oder 7221-Chip und der Bibliothek LedControl.h gesteuert wird.

Der Startbutton samt Pull-down-Widerstand

Jeder gute Countdown benötigt natürlich einen Button, der ihn startet. Setze ihn über die Brücke deines Breadboards, sodass zwei Pins darüber und zwei darunter stecken.

Verbinde anschließend den linken Pin mit Plus. Den rechten Pin verbindest du einmal mit einem 10kOhm-Widerstand mit Minus – und außerdem mit einem Kabel mit dem Digitalpin 2 an deinem Arduino. Diesen sogenannten Pull-down-Widerstand benötigst du, damit dein Arduino zuverlässig eine 0 empfängt, solange du den Button nicht drückst. Sobald du ihn drückst, springt das Singal auf 1.

Hier erfährst du mehr über Pull-up- und Pull-down-Widerstände.

Anschluss des Buttons mit Pull-up-Widerstand

Der Piezo-Buzzer für den Alarm

Was, wenn die Zeit abgelaufen ist? Richtig, dann schlägt ein Piezo-Buzzer Alarm. Setze deinen Piezo auf das Breadboard und verbinde einen Pin mit Minus und den anderen mit dem Digitalpin 3.

Anschluss des Piezo-Buzzers

Und das war es auch schon. Schauen wir uns den Code an

Der Sketch für den Arduino-Timer

Die meisten Zeilen im Code benötigst du für den Countdown auf dem Display. In diesem Tutorial auf pollux labs lernst du, wie du eine 7-Segment-Anzeige steuerst, weshalb wir uns hier auf andere Aspekte des Sketchs konzentrieren.

Zu Beginn des Sketchs legst du die Pins für den Button und den Piezo-Summer fest:

const byte buttonPin = 2;
const byte buzzerPin = 3;

Anschließend erstellst du eine Variable, in der du die Sekunden festlegen kannst, die dein Arduino-Countdown herunterzählen soll:

___STEADY_PAYWALL___

long countdown = 10;

Als Typ verwendest du hier long, um große Zahlen speichern zu können, die eine 7-Segment-Anzeige voll ausschöpfen. Der Typ int reicht auf dem Arduino Uno nur für Zahlen im Bereich -32.768 bis 32.767, auf größeren Boards auch für mehr. Hier erfährst du mehr über dieses Thema.

Der Loop

In der Funktion void loop() geschieht eigentlich nicht viel. Hier wartet dein Sketch nur darauf, dass du den Button drückst und den Countdown startest:

void loop() {
  Serial.println(digitalRead(buttonPin));
  if (digitalRead(buttonPin) == 1) {
    timer();
  }
}

Hierfür liest du mit der Funktion digitalRead() den Button-Pin. Wenn du diesen drückst, springt der Wert auf 1, was die Funktion timer() startet, die wir uns jetzt genauer anschauen.

void timer() {
  number = countdown;
  Serial.println("Timer started!");
  while (number > 0) {
    numberIntoDigits();
    displayNumber();
    delay(1000);
    lc.clearDisplay(0);
    number--;
  }
  if (number == 0) {
    tone(buzzerPin, 440, 1000);
  }
}

Zunächst weist du den Wert der Variable countdown, den du zu Beginn festgelegt hast, einer Variablen number zu. Diese Variable verwenden und verändern wir während des Countdowns, sodass die ursprünglich von dir bestimmte Zeit in der Variablen countdown unberührt bleibt.

Warum? Nun, somit kannst du deinen Arduino-Countdown immer wieder starten, da nur die “Hilfsvariable” number verändert wird. 🙂

Im While-Loop startest du die beiden Funktionen numberIntoDigits() und displayNumber(), über die du in diesem Tutorial mehr erfährst. Anschließend wartest du eine Sekunde, löschst das Display und ziehst von der Zahl in der Variablen number eins ab. Dann beginnt der nächste Durchgang.

Sobald der Countdown bei der Null angekommen ist, ertönt dein Piezo:

  if (number == 0) {
    tone(buzzerPin, 440, 1000);
  }

Der Einfachheit halber spielt er im obigen Beispiel nur für eine Sekunde den Ton A (mit 440Hz). In diesem Tutorial erfährst du mehr darüber, wie du einen Piezo verwendest und damit Melodien spielst.

Hier nun der gesamte Sketch zum Herauskopieren und Hochladen:

#include "LedControl.h"

const byte buttonPin = 2;
const byte buzzerPin = 3;
long number;

//Trage hier die Sekunden ein, die heruntergezählt werden sollen
long countdown = 10;

//Ziffern
int a,b,c,d,e,f,g,h;

LedControl lc = LedControl(12, 11, 10, 1);

void numberIntoDigits() {

  h = number % 10;

  if (number > 9) {
    g = (number / 10) % 10;
  }
  if (number > 99) {
    f = (number / 100) % 10;
  }
  if (number > 999) {
    e = (number / 1000) % 10;
  }
  if (number > 9999) {
    d = (number / 10000) % 10;
  }
  if (number > 99999) {
    c = (number / 100000) % 10;
  }
  if (number > 999999) {
    b = (number / 1000000) % 10;
  }
  if (number > 9999999) {
    a = (number / 10000000) % 10;
  }
}

void displayNumber() {

  lc.setDigit(0, 0, h, false);

  if (number > 9) {
    lc.setDigit(0, 1, g, false);
  }
  if (number > 99) {
    lc.setDigit(0, 2, f, false);
  }
  if (number > 999) {
    lc.setDigit(0, 3, e, false);
  }
  if (number > 9999) {
    lc.setDigit(0, 4, d, false);
  }
  if (number > 99999) {
    lc.setDigit(0, 5, c, false);
  }
  if (number > 999999) {
    lc.setDigit(0, 6, b, false);
  }
  if (number > 9999999) {
    lc.setDigit(0, 7, a, false);
  }
}

void timer() {
  number = countdown;
  Serial.println("Timer started!");
  while (number > 0) {
    numberIntoDigits();
    displayNumber();
    delay(1000);
    lc.clearDisplay(0);
    number--;
  }
  if (number == 0) {
    tone(buzzerPin, 440, 1000);
  }
}

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(buzzerPin, OUTPUT);
  Serial.begin(115200);
  lc.shutdown(0, false);
  lc.setIntensity(0, 8);
  lc.clearDisplay(0);
}

void loop() {
  Serial.println(digitalRead(buttonPin));
  if (digitalRead(buttonPin) == 1) {
    timer();
  }
}

Wie geht es weiter?

Mögliche Verbesserungen für deinen Arduino-Countdown könnte eine Alarm-Melodie sein. Oder du versuchst dich an der Möglichkeit, die Zeit nicht im Sketch, sondern über Buttons auf dem Breadboard einstellen zu können.

Ein spannendes Projekt mit Countdown ist die LEGO ISS, die beim Überflug der echten ISS anfängt zu leuchten.

Fehlen dir noch Bauteile? Dann wirf einen Blick in unsere Übersicht der besten Arduino Starter Kits.

]]>
Projekte zum Thema Corona-Virus https://polluxlabs.net/arduino-projekte/projekte-zum-thema-corona-virus/ Mon, 25 May 2020 09:15:52 +0000 https://polluxlabs.net/?p=1737 Projekte zum Thema Corona-Virus Weiterlesen »

]]>
Wie wohl jeder weiß, befindet sich die Welt seit Anfang des Jahres in einer besonders schwierigen Situation, in der es auf die Achtsamkeit und Solidarität jedes einzelnen ankommt. Wir alle versuchen durch Abstandhalten, Hygiene und weitere Vorsichtsmaßnahmen uns selbst und unsere Mitmenschen so gut es geht zu schützen.

Auch Maker rund um den Globus lassen sich Projekte und Tools einfallen, die die Menschheit darin unterstützen können, COVID-19 so gut wie möglich an der Ausbreitung zu hindern. Wir stellen hier einige interessante Projekte zu diesem Thema vor.

Bitte denke daran: Verlasse dich im Zweifelsfall nicht auf DIY-Projekte, um dich und andere zu schützen. Halte dich stattdessen an die offiziellen Empfehlungen und Regeln, informiere dich mit Hilfe von seriösen Quellen und vertraue auf deinen gesunden Menschenverstand.

Aktuelle Zahlen zu Corona abrufen

Mit diesem Projekt kannst du länderspezifische Fallzahlen zu Corona und COVID-19 abrufen und dir auf einem Display anzeigen lassen. Du benötigst dafür einen ESP32 und ein Display – in diesem Fall wird ein Touchscreen verwendet, ein OLED- oder TFT-Display sollte es aber auch tun. Beachte auch die Vielzahl der Kommentare unter der Beschreibung, um wertvolle Hinweise zum Code zu erhalten.

Hier geht es zum COVID-19-Tracker

Berührungsloser Seifenspender

Viele Arduino Projekte befassen sich mit dem Thema Hände waschen und desinfizieren. Die Idee hierbei ist, die Seife oder das Desinfektionsmittel berührungslos auf die Hände zu bekommen. Hierfür verwendet dieses Projekt einen Infrarot-Entfernungsmesser, um zu erkennen, dass sich deine Hand dem Spender nähert – du kannst es aber auch mit einem Ultraschallsensor bauen, wenn du die entsprechenden Anpassungen im Aufbau und im Code durchführen kannst.

Hier geht es zum berührungslosen Seifenspender

Temperatur berührungslos messen

Infrarot-Thermometer

Hier auf pollux labs findest du ein Tutorial, in dem du erfährst, wie du mit dem Infrarotsensor GY-906 berührungslos die Temperatur messen kannst. So kannst du dir eine Art Fieberthermometer bauen – beachte jedoch, dass du dich im Zweifelsfall nur auf professionelle Geräte verlassen darfst.

Hier geht es zum Tutorial

Aktuelle Nachrichten lesen

Es ist natürlich immer wichtig, gut informiert zu sein. In dieser Zeit ist es jedoch noch wichtiger, so früh wie möglich von aktuellen Entwicklungen, Hinweisen und Warnungen zu erfahren – und zwar aus seriösen Quellen.

Auf pollux labs findest du einen Newsticker, den du dir mit einem ESP32 bauen kannst. Dieses Projekt ruft Daten von einer API ab und gibt dir aktuelle Schlagzeilen im Seriellen Monitor aus. Das ist sozusagen der Rumpf für dein Nachrichten-Projekt: Vervollständige es, in dem du ein ein Display anschließt und entscheidest, aus welchen Quellen du Nachrichten lesen möchtest.

Hier geht es zum Newsticker

Weitere Projekte

Wir sind weiter auf der Suche nach interessanten Projekten zu diesem Thema und werden diese Übersicht ständig erweitern.

Viele weitere spannende Ideen findest du auf hackster.io – hier gibt es sogar einen Contest, in dem die besten Projekte zum Thema Corona und COVID-19 gesucht und prämiert werden. Vielleicht hast du ja eine Projekt, das du einreichen möchtest?

]]>
Kompakter Pflanzenwächter mit Batterie https://polluxlabs.net/arduino-projekte/kompakter-pflanzenwaechter-mit-batterie/ Thu, 07 May 2020 14:14:16 +0000 https://polluxlabs.net/?p=1516 Kompakter Pflanzenwächter mit Batterie Weiterlesen »

]]>
Hast du einen grünen Daumen? Selbst wenn, dieses Projekt erinnert dich daran, deine Pflanzen zu gießen. Stecke den Pflanzenwächter einfach neben deine Lieblingspflanze in ihren Topf und kalibriere ihn auf die richtige Feuchtigkeit. Sobald die Erde zu trocken geworden ist, fängt die LED an zu blinken und erinnert dich rechtzeitig an die Gießkanne.

Für dieses Projekt benötigst du:

*Amazon Affiliate Link – wenn du dort bestellst, erhalten wir eine kleine Provision.

Bausatz für den Pflanzenwächter

Das kann der Pflanzenwächter

Ein guter Pflanzenwächter sollte in einem Topf neben der Pflanze nicht allzu sehr auffallen und außerdem eine unabhängige Stromversorgung haben. Hierfür bietet sich der ATtiny85 an, denn diesen kannst du mit einer 3,3V Knopfzelle über eine sehr lange Zeit betreiben – vorausgesetzt du lässt ihn nicht ununterbrochen messen, sondern versetzt ihn die meiste Zeit in den Schlafmodus.

Mit dem Code dieses Projekts testest du nur alle 30 Minuten, ob die Pflanzenerde zu trocken geworden ist. Die restliche Zeit schläft der Pflanzenwächter und zieht nur sehr wenig Strom von der Batterie. So sollte diese ohne Probleme mehrere Monate durchhalten.

Damit der Wächter eine kompakte Große erhält, verwendest du Vorder- und Rückseite des Mini-Breadboards. Auf die Rückseite klebst du einige Bauteile, die du mit Kabeln auf der Vorderseite mit dem ATtiny85 verbindest. Der fertige Pflanzenwächter misst in seiner Box zum Schluss nur ca. 40 x 70 x 40 mm.

So programmierst du den ATtiny85

Bevor du mit dem Zusammenbau loslegst, musst du den passenden Sketch auf deinen ATtiny85 laden. Den Code findest du am Ende dieses Projekts. Erfahre hier, wie du ihn mit Hilfe eines Arduino Uno auf den ATtiny85 hochlädst.

So baust du den Pflanzenwächter zusammen

Der Aufbau dieses Projekts dauert ungefähr 30 Minuten und ist auch von Anfängern zu bewerkstelligen.

Zunächst die Rückseite

Praktischerweise befindet sich auf der Rückseite des Breadboards eine Klebefläche, auf die du einige Bauteile anbringen kannst. Ziehe also zunächst die Schutzfolie von der Rückseite ab.

Klebe anschließend den Batteriehalter sowie Board und Sonde des Feuchtigkeitssensors wie folgt auf die Fläche. Drücke alle Teile zunächst nur leicht an. Wenn alles passt, kannst du sie stärker andrücken – sie halten dann sehr gut auf der Rückseite.

___STEADY_PAYWALL___

Auf die Rückseite geklebte Bauteile
Auf die Rückseite geklebte Bauteile

Die Kabel an der Rückseite anbringen

Bleiben wir zunächst auf der Rückseite. Hier musst du zunächst die Sonde mit dem Board verbinden. Hierfür benötigst du die beiden Kabel, die an beiden Enden Buchsen haben. Bringe sie wie folgt an:

Verbindung des beiden Teile des Feuchtigkeitssensors

Wenn du die Buchsen an die Pins gesteckt hast, lege das Kabel um die Oberseite des Breadboards. So nehmen sie am wenigsten Platz weg.

Jetzt kommt das Board des Feuchtigkeitssensors an die Reihe. An ihm findest du noch vier freie Pins: VCC (Plus), GND (Minus), DO (Digitalausgang) und AO (Analogausgang). Du benötigst allerdings nur die ersten drei.

Stecke also zunächst drei Kabel an die Pins VCC, GND und DO.

Die Kabel an den übrigen Pins des Feuchtigkeitssensors

Damit hast du die Rückseite des Pflanzenwächters vorerst abgeschlossen – Zeit für die Vorderseite des Breadboards!

Den ATtiny85 auf das Board setzen

Nimm deinen ATtiny85 in die Hand und schau ihn dir genau an: In einer Ecke des Chips findest du eine kleine Runde Vertiefung. Diese markiert den Pin neben ihr als Nummer Eins.

Lege das Breadboard nun so vor dich hin, dass die Sonde des Feuchtigkeitssensor nach unten zeigt. Setze den ATtiny85 jetzt vorsichtig in die Mitte des Breadboard, so dass die kleine Vertiefung nach rechts unten zeigt. Vorsichtig deshalb, weil die Pins des Chips sehr sensibel sind. Sei also besonders vorsichtig, wenn du ihn aufsetzt oder wieder vom Breadboard nimmst.

Verwende am besten einen Sockel für deinen ATtiny85, um ihn zu beim Ein- und Ausbau zu schonen.

So sollte das aussehen, wenn du fertig bist:

Der ATtiny85 auf dem Breadboard

Verbinde den Feuchtigkeitssensor mit dem ATtiny85

Bevor du die Kabel des Feuchtigkeitssensors auf das Breadboard steckst, schaue dir zunächst einmal die Nummerierung der Pins des ATtiny85 an:

Pinout des ATtiny85
Pinout des ATtiny85

Wie gesagt, markiert die kleine Vertiefung den Pin 1 des ATtiny85. Die Nummern der anderen Pins erhältst du, wenn du von hier aus gegen den Uhrzeigersinn zählst.

Drehe dein Breadboard nun am besten, sodass die Sonde des Feuchtigkeitssensors nach oben zeigt. So zeigt dein ATtiny85 in die gleiche Richtung wie in der Darstellung oben.

Stecke jetzt das Kabel von Pin DO des Sensors direkt neben Pin 2 des ATtiny85. GND kommt an Pin 4 – das ist der Minuspol. Den Pin VCC des Sensors steckst du zuletzt neben Pin 7 des ATtiny85. Hier noch einmal in der Übersicht:

Pins FeuchtigkeitssensorPins ATtiny85
DO2
GND4
VCC7

Bringe die LED samt Widerstand an

Bevor du den Widerstand auf das Breadboard setzt, musst du ihn zurechtbiegen und die Beine kürzen. So sollte der Widerstand nach deiner Behandlung aussehen:

Widerstand für den Pflanzenwächter

Nimm nun die LED und stecke ihr kurzes Bein (Kathode) neben das Kabel an Pin 4 des ATtiny85. Ihr langes Bein (Anode) kommt zwei Löcher daneben.

Stecke nun den Widerstand wieder eine Reihe weiter, sodass er die Anode mit Pin 3 des ATtiny85 verbindet. So sollte das aussehen:

LED und Widerstand anbringen

Versorge den Pflanzenwächter mit Strom

Jetzt der wichtigste Teil: die Stromversorgung. Nimm die beiden Kabel des Batteriehalters in die Hand uns stecke das rote Kabel neben Pin 8 des ATtiny85 und das schwarze in das letzte freie Loch neben Pin 4:

Der fertige Pflanzenwächter von vorne

Der letzte Draht

Jetzt brauchst du noch eine kleine Drahtbrücke. Diese benötigst du, um den Pflanzenwächter zu kalibrieren, sodass er Alarm schlägt, wenn die Erde um ihn herum zu trocken ist.

Stecke diese Drahtbrücke nun zwischen Pin 8 und Pin 6 des ATtiny85:

Die Drahtbrücke für die Kalibrierung

Und das war es! Dein Pflanzenwächter ist zusammengebaut und bereit für die Kalibrierung.

So kalibrierst du deinen Pflanzenwächter

Bevor du loslegst, drehe mit Hilfe eines Schraubenziehers den Poti an der Rückseite des Feuchtigkeitssensors in beide Richtungen. Wenn du alles richtig miteinander verbunden hast, sollte die LED an- und ausgehen – je nachdem wie weit du den Poti nach links und rechts drehst.

Wenn sie das tut, kann es weitergehen:

Setze deinen Pflanzenwächter mit der Sonde neben eine Pflanze in die Erde. Am besten ist diese Erde gerade so trocken, dass du die Pflanze jetzt eigentlich gießen würdest. Drehe den Poti an der Rückseite so dass die LED gerade noch brennt. Und das war es auch schon – die Kalibrierung ist abgeschlossen und der Wächter weiß, wann er Alarm schlagen muss. Nimm nun die Drahtbrücke auf dem Breadboard zwischen Pin 6 und 8 heraus und lege sie beiseite. Wenn alles stimmt, sollte die LED jetzt alle paar Sekunden mehrmals blinken – das Signal, dass es Zeit für die Gießkanne ist.

Jetzt kannst du den Pflanzenwächter – wenn du möchtest –zunächst wieder herausnehmen, in seine Box stecken und wieder neben die Pflanze setzen.

Gieße anschließend die Pflanze – die LED hört nun auf zu blinken, bis die Erde zu trocken geworden und es Zeit für einen Schluck Wasser ist.

Der Code des Pflanzenwächters

Der Code besteht im Prinzip aus folgenden Teilen:

  • Den Sensor kalibrieren
  • Die Feuchtigkeit messen
  • Alarm geben, wenn die Erde zu trocken ist
  • Den ATtiny85 “schlafen legen”

Zu Beginn müssen allerdings zwei Bibliotheken eingebunden und ein paar Pins definiert werden:

Die benötigten Bibliotheken

Du brauchst für den Code zwei Bibliotheken, die bereits vorinstalliert sind:

#include <avr/sleep.h>
#include <avr/wdt.h>

Mit der Bibliothek avr/sleep.h kannst du deinen ATtiny85 in den Schlafmodus versetzen, was dafür sorgt, dass sein Stromverbrauch erheblich sinkt. Da der Pflanzenwächter mit einer Batterie betrieben wird, ist dieser Schlafmodus besonders wichtig. Erfahre hier mehr über diese Bibliothek (Englisch).

Die Bibliothek avr/wdt.h ist ein sogenannter Watchdog, den du – vereinfacht gesagt – dazu verwendest, deinen ATtiny85 nach einer bestimmten Zeit wieder aufzuwecken. In diesem Beitrag erfährst du hierüber mehr.

Die Pins definieren

Insgesamt musst du vier Pins definieren, die dein ATtiny85 verwendet:

#define calibrationPin 1
#define sensorPin 2
#define sensorValuePin 3
#define ledPin 4

Beachte hierbei, dass die Nummern der Pins nicht mit den Pin-Nummern übereinstimmen, die du vorhin gegen den Uhrzeigersinn durchgezählt hast. Möchtest du die Pins deines Chips im Code ansteuern, benötigst du andere Nummern, die du ebenfalls in diesem Schema findest:

ATtiny85 Pinout

Die Nummern für deinen Code beginnen mit PB. Wie du siehst, entspricht zum Beispiel der erste Pin neben der Vertiefung dem “Code-Pin” PB5. Im Code lässt du die Buchstaben jedoch weg und schreibst nur 5. Insgesamt stehen dir nach Abzug von Plus (VCC) und Minus (GND) noch 6 Pins zur freien Verfügung.

Beim Pflanzenwächter hängt die LED zum Beispiel neben dem “Beinchen” Nr. 3 des ATtiny85 – im Code steuerst du sie jedoch mit dem Pin 4 an:

#define ledPin 4

In den folgenden Erläuterungen sind ab jetzt immer die Pin-Nummern des Codes gemeint.

Im Setup des Sketchs legst du nun noch fest, ob es sich um Eingänge (INPUT) oder Ausgänge (OUTPUT) handelt:

void setup() {
  pinMode(calibrationPin, INPUT);
  pinMode(sensorPin, OUTPUT);
  pinMode(sensorValuePin, INPUT);
  pinMode(ledPin, OUTPUT);
}

Die Kalibrierung des Pflanzenwächters

Kommen wir zum Loop des Sketchs. Hier fragst du zunächst ab, ob die die Drahtbrücke zur Kalibrierung des Sensors eingesteckt ist. Diese befindet sich ja zwischen Plus (VCC) und Pin 1 – das heißt, dein ATtiny85 misst an diesem Pin einen Strom (HIGH), wenn die Drahtbrücke angeschlossen ist.

Ist das der Fall, wird im Loop nur der Code für die Kalibrierung ausgeführt:

if (digitalRead(calibrationPin) == HIGH) {
  digitalWrite(sensorPin, HIGH);
  if (digitalRead(sensorValuePin) == 1) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }
}

Zunächst wird der Sensor angeschaltet, in dem der Pin für seine Stromzufuhr (sensorPin) auf HIGH gesetzt wird. In einer zweiten Abfrage wird die LED eingeschaltet, wenn der Sensor einen Messwert von 1 übergibt (an den Pin sensorValuePin). Ist die Erde feucht, wird die LED ausgeschaltet.

Was trocken und was feucht bedeutet bestimmst du selbst durch Drehen des Potis auf der Platine des Feuchtigkeitssensors. Wie gesagt, kalibrierst du deinen Pflanzenwächter am einfachsten, wenn du ihn in trockene Erde steckst und den Poti so drehst, dass die LED gerade noch leuchtet. Wenn du dann gießt, geht sie aus – bis die Erde wieder so trocken wie bei der Kalibrierung ist.

Die Feuchtigkeit messen

Kommen wir zur eigentlichen Messung der Feuchtigkeit. Hier kann es nur zwei Zustände geben: Die Erde ist zu trocken oder Die Erde ist noch feucht genug.

Zunächst wird der Sensor für 100 Millisekunden eingeschaltet:

digitalWrite(sensorPin, HIGH);
delay(100);

Wenn der Sensor dann eine 1 misst und weitergibt, bedeutet das, dass die Erde zu trocken ist. Dann wird zunächst der Sensor wieder ausgeschaltet, um sofort wieder Strom zu sparen. Dafür blinkt jedoch die LED 10 mal auf und ab.

Zuletzt wird der Watch Dog scharfgemacht, sodass der ATtiny85 schlafen geht und nach 8 Sekunden wieder aufwacht und die LED wieder blinken lässt – sofern du die Pflanze in der Zwischenzeit nicht gegossen hast.

if (digitalRead(sensorValuePin) == 1) {

  digitalWrite(sensorPin, LOW);

  for (byte i = 0; i < 10; i++) {
    digitalWrite(ledPin, HIGH);
    delay(200);
    digitalWrite(ledPin, LOW);
    delay(200);
  }

  myWatchdogEnable (0b100001);
}

Fall du das jedoch gemacht hast, schlägt der Pflanzenwächter natürlich keinen Alarm mehr. Er misst jetzt, dass die Erde feucht genug ist und übergibt eine 0 an den entsprechenden Pin. In dem Fall geht sowohl die LED als auch der Sensor aus und der Watchdog schaltet deinen ATtiny85 für 30 Minuten in den Schlafmodus:

else {
  digitalWrite(ledPin, LOW);
  digitalWrite(sensorPin, LOW);

  for (byte j = 0; j <= 225; j++){
    myWatchdogEnable (0b100001);
  }
}

Zum Einsatz kommt hier die Funktion myWatchdogEnable(), die du ebenfalls im Sketch findest. Dieser Funktion gibst du das Byte 0b100001 mit, das den Timer auf 8 Sekunden stellt. Der For-Loop sorgt dafür, dass dieser 8-Sekunden-Timer 225 Mal ausgeführt wird – was 30 Minuten Schlaf ergibt.

Bleibt nur noch eine Frage: Wie funktioniert der Watchdog? Das ist eine auch für Fortgeschrittene keine so einfache Sache. Aber in diesem Beitrag erfährst du mehr über die grundlegende Funktionsweise.

Der vollständige Sketch

Hier nun der vollständige Sketch – falls du noch nicht weißt, wie du ihn auf deinen ATtiny85 hochlädst, erfährst du hier, wie das funktioniert.

/*
   Code für den ATtiny85
   https://polluxlabs.net
   Copyright: CC BY-NC-ND
*/

#include <avr/sleep.h>
#include <avr/wdt.h>

#define calibrationPin 1
#define sensorPin 2
#define sensorValuePin 3
#define ledPin 4

void myWatchdogEnable(const byte interval)
{
  MCUSR = 0;                          // reset various flags
  WDTCR |= 0b00011000;               // see docs, set WDCE, WDE
  WDTCR =  0b01000000 | interval;    // set WDIE, and appropriate delay

  wdt_reset();
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  sleep_mode();            // now goes to Sleep and waits for the interrupt
}

void setup() {
  pinMode(calibrationPin, INPUT);
  pinMode(sensorPin, OUTPUT);
  pinMode(sensorValuePin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {

  //wenn am calibrationPin Strom anliegt, kann der Sensor kalibriert werden
  if (digitalRead(calibrationPin) == HIGH) {
    digitalWrite(sensorPin, HIGH);
    if (digitalRead(sensorValuePin) == 1) { // 1 = trocken
      digitalWrite(ledPin, HIGH);
    } else {
      digitalWrite(ledPin, LOW);
    }

    //wenn kein Strom anliegt, geht er in den Messmodus
    //Code, wenn die Erde zu trocken ist:
  } else {
    digitalWrite(sensorPin, HIGH);
    delay(100);
    if (digitalRead(sensorValuePin) == 1) {

      digitalWrite(sensorPin, LOW);

      for (byte i = 0; i < 10; i++) {
        digitalWrite(ledPin, HIGH);
        delay(200);
        digitalWrite(ledPin, LOW);
        delay(200);
      }

      myWatchdogEnable (0b100001);

    }
    //Code, wenn die Erde noch feucht genug ist:
    else {
      digitalWrite(ledPin, LOW);
      digitalWrite(sensorPin, LOW);

      for (byte j = 0; j <= 225; j++) {
        myWatchdogEnable (0b100001);  // 8 seconds -- verlängern auf viel Zeit
      }
    }
  }
}

ISR(WDT_vect)
{
  wdt_disable();  // disable watchdog
}

]]>