1. Advent 2022: Der kleine Schneemann

Der kleine Schneemann

Das Jahresende rückt immer näher und damit auch Weihnachten. Wir dekorieren mit weihnachtlichen Motiven. Warum grüßen wir da nicht mit netten Figuren, die uns ein frohes Fest wünschen?!

Mit diesem Projekt werden wir einen Schneemann bauen, der uns in mehreren Sprachen zu Weihnachten grüßt, dessen Körper leuchtet und der mit seinem Arm Bewegungen ausführt. Dazu brauchen wir einen WS2812B-RGB-LED-Ring mit 50 mm und einen weiteren mit 37 mm Durchmesser. Außerdem einen SG90- oder MG90S-Servomotor, einen 1,8-Zoll-SPI-TFT-Bildschirm mit 128 x 160 Pixeln, ein MB102-Breadboard-Kit und zur Steuerung all dieser Elemente einen ATmega328-Mikrocontroller.

Benötigte Materialien

1

AZDelivery Mikrocontroller Board ATmega328 mit USB-Kabel

alternativ:

Nano V3.0 Atmega328 mit USB Kabel

oder

Mega 2560 Board mit ATmega2560 mit USB Kabel

1

LED Ring 5V RGB WS2812B 12-Bit 50mm

1

LED Ring 5V RGB WS2812B 12-Bit 37mm

1

SG90 Micro Servo Motor 9G oder

MG90S Micro Servomotor

1

1,8 Zoll SPI TFT Display 128 x 160 Pixel

1

MB 102 Breadboard Kit

1

Jumper Wire Kabel 40 STK. je 20 cm F2F Female to Female

1

Metalldraht 2mm

 

Küchenrolle

 

Bastelkarton weiß

 

Weißleim

Je 1

Kugelform 6,5 cm und 8,5 cm

1

SD Card

 

Benötigte Software

Schaltkreis

Bild als Download

Statt des Uno Mikrocontrollers mit ATmega328 können Sie auch den Nano mit ATMega328 oder Mega mit ATmega2560 verwenden!

Schneemann basteln

Wir basteln einen Schneemann aus Küchenpapier und Weißleim. Der Weißleim wird mit Wasser verdünnt. Wir nehmen zwei Kugelformen von 8,5 cm für den Körper und 6,5 cm für den Kopf, bedecken sie mit Papierstücken und tragen mit einem Pinsel ein wenig von der Lösung aus Weißleim und Wasser auf. Wir fügen davon mehrere Schichten hinzu, damit sie zusammen so dick sind, dass wir sie später noch bearbeiten können und lassen sie trocknen. Wenn sie trocken sind, machen wir einen Schnitt in den Umfang der Kugeln, um die inneren Formen zu entfernen und die LED-Ringe darin zu installieren. Außerdem den Servomotor, der die Bewegung des Armes antreibt. Wir machen auch ein Loch hinein, um die Verbindungskabel zum Mikrocontroller durchführen zu können.

Für den Hut verwenden wir weißen Karton. Die spätere Farbe und die Form sind dem Leser überlassen. Wie Sie auf den Fotos sehen können, wird der 2mm-Metalldraht am Servomotor angebracht und durch ein seitliches Loch in der Kugel des Körpers herausgeführt. Er dient als Drehpunkt des Arms. Am Ende des Arms kleben wir den Hut auf. Wenn wir alles im Inneren installiert haben, kleben wir die beiden Teile der Kugeln zusammen und schneiden ein Loch in den oberen Teil der Körperkugel. Dort wird die Kopfkugel aufgetragen. Zum Schluss bringen wir den Schal und die Nase an, die wir ebenfalls nach der gleichen Methode wie die Kugeln hergestellt haben. Abschließend können wir ihn noch z.B. orange bemalen.

Die zwei LED-Ringe werden verwendet, um das Innere des Körpers und den Kopf unseres Schneemanns zu beleuchten. Mit dem Servomotor bewegen wir den Arm. Dieser hält den Hut und seine Bewegung lässt uns begrüßen. Der TFT-Bildschirm zeigt die Grußbotschaften in mehreren Sprachen an.

Wichtiger Hinweis: Um den SD-Kartenleser mit TFT-Bildschirm verwenden zu können, müssen vier Pins angelötet werden. Das tun wir, da wir das AZ-Delivery-Logo zeigen werden. Um die vom Kartenlesegerät heruntergeladenen Bilder auf dem Bildschirm anzeigen zu können, muss das Bild eine Auflösung von 160 x 128 Pixeln haben, im Querformat vorliegen und der Dateityp BMP - 24 Bit Bitmap sein.

Programmablauf und Sketch

Das Programm beginnt mit der Initialisierung der LED-Ringe und des Servomotors. Der SD-Kartenleser wird initialisiert, indem geprüft wird, ob eine Karte eingesteckt ist. Bei einem Fehler wird die Ausführung des Programms angehalten. Wenn die Initialisierung erfolgreich ist, wird der TFT-Bildschirm initialisiert.

Sobald alle Module initialisiert sind, wird das Bild des Logos von der SD-Karte heruntergeladen und auf dem Bildschirm angezeigt. Der Schneemann begrüßt uns, indem sie ihren Hut abnimmt und das Logo mit der ersten Nachricht erscheinen. Nach dieser ersten Nachricht leuchtet der Körper der Puppe auf, die erste Begrüßung erscheint in einer Sprache und der Kopf der Puppe leuchtet auf, gefolgt von der Begrüßung in einer anderen Sprache. Die Farbe des Körpers der Puppe ändert sich und sie macht eine weitere Begrüßung. Dann ändert sich die Farbe der Kopfbeleuchtung. Die Farbe des Körpers und des Kopfes ändern sich bis zur letzten Nachricht, dann werden die LEDs am Körper und Kopf ausgeschaltet, pausieren und beginnen von neuem.

Beginnen wir mit der Analyse des Sketches. Das erste, was wir wie bei allen Projekten tun müssen, ist die Einbindung der notwendigen Bibliotheken, um später die Funktionen und Methoden zu implementieren, die wir für die Arbeit mit den LED-Ringen, dem 1,8-Zoll-TFT-Bildschirm, dem SD-Kartenleser des Bildschirms und dem Servomotor des Arms benötigen.

#include <Adafruit_NeoPixel.h>

#include <SPI.h>
#include <SD.h> 
#include <TFT.h>

#include <Servo.h>

Als Nächstes werden wir ein Objekt des TFT-Bildschirms implementieren. Als Argumente dieser Implementierung müssen wir die Pins der Verbindung zum Mikrocontroller seiner Steuer- und Zugriffspins eintragen. Diese sind der Pin lcd_sc (Signal, um anzuzeigen, dass Informationen zu ihm gesendet werden), dc (Daten senden) und rst (Zurücksetzen des Bildschirms). Für diese drei Leitungen müssen wir definieren, an welche Pins des Mikrocontrollers wir sie angeschlossen haben. Außerdem müssen wir auch den Anschlusspin der Leitung für die Verwendung des SD-Kartenlesers definieren, das ist sd_cs.

#define sd_cs 4
#define lcd_cs 10
#define dc 9
#define rst 8
TFT TFTscreen = TFT(lcd_cs, dc, rst);

Um den Code besser lesbar zu machen, definieren wir eine Konstante mit der Pin-Nummer des Mikrocontrollers, an den wir jeden LED-Ring angeschlossen haben und die Anzahl der LEDs (12), die jeder Ring hat.

#define big_ring_LED 7
#define big_ring_LED_count 12
#define small_ring_LED 6
#define small_ring_LED_count 12

Um die LED-Ringe zu verwenden, müssen wir wie beim TFT-Bildschirm für jeden von ihnen ein Objekt instanziieren. Als Argumente müssen wir die Anzahl der LEDs des jeweiligen Rings eintragen (big_ring_LED_count und small_ring_LED_count). Außerdem die Pins des Mikrocontrollers, an die jeder einzelne angeschlossen ist (big_ring_LED und small_ring_LED). Dazu kommen die Eigenschaften des Rings (dreifarbige LEDs; NEO_GRB) und die Arbeitsfrequenz von 800 KHz (NEO_KHZ800).

Adafruit_NeoPixel big_ring(big_ring_LED_count, , NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel small_ring(small_ring_LED_count, small_ring_LED, NEO_GRB + NEO_KHZ800);

Auch für den Servomotor erzeugen wir ein Objekt.

Servo servo_arm;

Um die Farbe anzugeben, die wir leuchten lassen wollen, konfigurieren wir den Leuchtwert, den jede LED (rot, grün und blau) ausstrahlt, mit einem Höchstwert von 150. Die Funktion dafür ist ring_name.Color(150,0,0), wobei wir das Objekt (Name des Rings), den Namen der Farbe und den Wert der Leuchtdichte jeder LED (R, G, B) angeben. Um zum Beispiel die rote Farbe leuchten zu lassen bekommt die rote LED einen Wert von 150 und die anderen beiden 0, also "aus". Um die Arbeit in der Programmierung zu erleichtern, definieren wir einige Variablen mit den Initialen des LED-Rings (b für groß und s für klein) und der Farbe. Auf diese Weise müssen wir nur den Namen der Farbe angeben, wir vermeiden mögliche Fehler und die Weiterverfolgung der Skizze ist einfacher. Die Definitionen der Variablen und die Zuordnung der Farben sind:

// Definition of the colors variables' names for WS2812B big ring
uint32_t b_red = big_ring.Color(150,0,0);
uint32_t b_green = big_ring.Color(0,150,0);
uint32_t b_blue = big_ring.Color(0,0,150);
uint32_t b_yellow = big_ring.Color(150,150,0);
uint32_t b_purple = big_ring.Color(150,0,150);
uint32_t b_light_blue = big_ring.Color(0,150,150);
uint32_t b_white = big_ring.Color(150,150,150);

// Definition of the colors variables' names for WS2812B small ring
uint32_t s_red = small_ring.Color(150,0,0);
uint32_t s_green = small_ring.Color(0,150,0);
uint32_t s_blue = small_ring.Color(0,0,150);
uint32_t s_yellow = small_ring.Color(150,150,0);
uint32_t s_purple = small_ring.Color(150,0,150);
uint32_t s_light_blue = small_ring.Color(0,150,150);
uint32_t s_white = small_ring.Color(150,150,150);

Um ein Bitmap-Bild von einer SD-Karte anzuzeigen, muss eine Instanz der PImage-Klasse verwendet werden. Wir erstellen also die Instanz namens logo.

PImage logo;

Der nächste Schritt ist nun die Implementierung der setup()-Methode, um die Anfangsbedingungen festzulegen, wenn wir Spannung anlegen oder den Mikrocontroller initialisieren. Wir beginnen mit der Initialisierung des seriellen Monitors, um Informationen auf dem Seriellen Monitor anzuzeigen.

Serial.begin(9600);

Als Nächstes müssen wir die beiden LED-Ringe initialisieren. Dazu schreiben wir das Objekt, das wir für jeden Ringtyp deklariert haben, gefolgt von dem Funktionsaufruf begin().

big_ring.begin();
small_ring.begin();

Anschließend deklarieren wir die Anfangsbedingungen unseres Servomotors. Wir geben mit der Funktion attach() den Pin des Mikrocontrollers an, an den wir ihn angeschlossen haben (5). Mit der Anweisung write() legen wir die Position in Grad fest, in der er anfänglich positioniert wird. In unserem Fall sind es 90 Grad.

servo_arm.attach(5);
servo_arm.write(90);

Das nächste zu initialisierende Modul ist der SD-Kartenleser auf dem TFT-Bildschirm. Zuerst zeigen wir eine Meldung auf dem seriellen Monitor an, die besagt, dass wir den SD-Kartenleser initialisieren werden. Für die Initialisierung des Kartenlesers wird eine einfache Bedingung implementiert. Wenn der SD-Kartenleser nicht initialisiert ist (!SD.begin), wird das Programm eine Fehlermeldung ausgeben und nicht weiter fortgeführt. Wenn das Lesegerät hingegen korrekt initialisiert wird, wird die if-Anweisung nicht ausgeführt und die nächste Zeile des Sketches wird ausgeführt, wodurch wir im Seriellen Monitor über den Erfolg der Initialisierung informiert werden.

Serial.print(F("Initializing SD card..."));
if (!SD.begin(sd_cs)) {
  Serial.println(F("failed!"));
  return;
}
Serial.println(F("OK!"));

Die nächste Komponente, die wir initialisieren, ist der TFT-Bildschirm mit dem Aufruf begin() nach dem Namen des Objekts, das wir für den Bildschirm erstellt haben. Mit der Anweisung background(0, 0, 0) setzen wir den Hintergrund des Bildschirms auf Schwarz.

TFTscreen.begin();
TFTscreen.background(0, 0, 0);

Als letzter Schritt folgt das Laden der BMP-Datei von der SD-Karte in die Instanz, die wir logo der PImage-Klasse genannt haben. Wir übergeben den Namen der Datei als Argument der Anweisung zum Laden des Bildes mit logo = TFTscreen.loadImage("az12.bmp"). Für den Fall, dass das Bild nicht geladen werden kann, wird eine Bedingung implementiert, die uns die Information auf dem Seriellen Monitor ausgibt.

logo = TFTscreen.loadImage("az12.bmp");
if (!logo.isValid()) {
  Serial.println(F("Error while loading arduino.bmp"));       
}

Damit ist die Implementierung der setup()-Methode abgeschlossen, und wir beginnen mit der Implementierung der loop()-Methode.

Mit der ersten Zeile der loop()-Methode überprüfen wir, ob das Format des heruntergeladenen Bildes korrekt ist, um es auf dem Bildschirm anzeigen zu können. Wenn das Format nicht korrekt ist, bricht der Sketch mit der return-Anweisung ab.

if (logo.isValid() == false) {
              return;
      }

Wenn das Format der bmp-Datei korrekt ist, läuft der Sketch weiter. Zuerst werden alle LEDs in den Ringen mit clear() ausgeschaltet. Mit der show()-Anweisung wird dann der Befehl auf die LED-Ringe übertragen.  

big_ring.clear();
big_ring.show();
        
small_ring.clear();
small_ring.show();

Jetzt müssen wir die heruntergeladene Bilddatei auf dem TFT-Bildschirm anzeigen, wofür wir den Hintergrund des Bildschirms mit TFTscreen.background(0, 0, 0) schwarz darstellen. Mit der Anweisung TFTscreen.image(logo, 0, 0) zeichnen wir auf dem Bildschirm die Grafik des Logos beginnend mit dem Pixel, das sich an den Koordinaten X=0 und Y=0 befindet.

TFTscreen.background(0, 0, 0);
      
Serial.println(F("drawing image"));
TFTscreen.image(logo, 0, 0);  

Sobald die Grafik auf dem Bildschirm zu sehen ist, nimmt die Puppe freundlicherweise ihren Hut ab, um Hallo zu sagen. Die Bewegung erfolgt durch den Servomotor mit der Ausgangsposition von 90 Grad bis zur Endposition von 40 Grad in Intervallen von je einem Schritt und einer kleinen Pause von einer halben Sekunde.

for (int pos=90; pos>40; pos -=1) {
  servo_arm.write(pos);
}
     
delay(500);

Dann, ohne die bmp-Datei zu löschen, zeigen wir darunter die Nachricht "WISHES YOU", für die wir die Textgröße mit TFTscreen.setTextSize(3) auf 3 setzen. Die Farbe des Textes wird mit TFTscreen.stroke(255, 40, 20) hellblau dargestellt. Die drei Werte des Arguments sind die Werte der Farben. Mit der folgenden Zeile schreiben wir das Wort WISHES an die Koordinaten X=30 und Y=45 und das Wort YOU an die Koordinaten X=55 und Y=80. Wir halten eine halbe Sekunde inne, um den Text lesen zu können.

TFTscreen.setTextSize(3);
TFTscreen.stroke(255, 40, 20); 
TFTscreen.text("WISHES", 30, 45);
TFTscreen.text("YOU", 55, 80);
delay(500);

Nun werden wir den Körper unseres Schneemanns beleuchten, wofür wir zunächst alle LEDs ausschalten, die Helligkeit auf einen Wert zwischen 50 über 255 einstellen und die LEDs festlegen, die leuchten sollen.

Eine Anmerkung: Der Ring hat 12 LEDS, aber die Nummerierung für die Bedienung beginnt mit der Nummer 0, die der ersten LED entspricht, bis zur Nummer 11 der letzten LED.

Wenn wir alle LEDs mit der gewünschten Farbe konfiguriert haben, führen wir die Anweisung big_ring.show() aus. Damit werden alle vorherigen Zeilen ausgeführt, so dass unser Ring aufleuchtet.

big_ring.clear();      // Power off the large ring LEDs.
big_ring.setBrightness(50);         // Set Luminosity set to 50 out of 254
big_ring.setPixelColor(0, b_green); // We set the LED 1 of 12 of the ring lights green
big_ring.setPixelColor(2, b_green);                 // LED 3
big_ring.setPixelColor(4, b_green);                 // LED 5
big_ring.setPixelColor(6, b_green);                 // LED 7
big_ring.setPixelColor(8, b_green);                 // LED 9
big_ring.setPixelColor(10, b_green);                // LED 11
big_ring.show();

Wir werden zum Weihnachtsfest in verschiedenen Sprachen gratulieren, also müssen wir die Nachrichten ändern, die auf dem Bildschirm erscheinen. Wir werden die Größe, die Farbe des Textes und der Nachricht ändern, also werden wir als erstes den Bildschirmhintergrund mit der Anweisung TFTscreen.background(0, 0, 0, 0) löschen. Die Größe des Textes konfigurieren wir mit dem Wert 2, die Farbe konfigurieren wir in blau und das erste Wort wird an den Koordinaten X=20 und Y=20 und das zweite Wort an den Koordinaten X=30 und Y=70 ausgegeben. Diese Koordinaten sind für die Zentrierung der Wörter auf dem Bildschirm in Spanisch. Wir halten 3 Sekunden lang inne.

TFTscreen.background(0, 0, 0);
TFTscreen.setTextSize(2);
TFTscreen.stroke(150, 150, 0);
TFTscreen.text("FELIZ", 50, 20);
TFTscreen.text("NAVIDAD", 37, 70);
delay(3000);

Nach dieser Botschaft werden wir den Kopf unseres Schneemanns beleuchten. Die Anleitung ist ähnlich wie die für die Beleuchtung des Körpers.

small_ring.clear();
small_ring.setBrightness(50);
small_ring.setPixelColor(0, s_blue);
small_ring.setPixelColor(2, s_blue);
small_ring.setPixelColor(4, s_blue);
small_ring.setPixelColor(6, s_blue);
small_ring.setPixelColor(8, s_blue);
small_ring.setPixelColor(10, s_blue);
small_ring.show();
delay(1000);

Wir Grußbotschaften in verschiedenen Sprachen geschrieben und die Farbe des Körpers, sowie des Kopfes unseres freundlichen Schneemanns variiert. Sie können beliebig viele Nachrichten einfügen, die Farbe und auch die Anzahl der leuchtenden LEDs ändern, indem Sie einfach die Werte der Parameter in den Anweisungszeilen der einzelnen Elemente ändern. Die Koordinaten müssen so geändert werden, dass die Nachrichten in den verschiedenen Sprachen zentriert wird.

Sobald die letzte Meldung auf dem TFT-Bildschirm angezeigt wird, wird nach einer Wartezeit von 3 Sekunden der Servomotor aktiviert und der Hut auf den Kopf unseres Schneemanns gesetzt. Ds passiert in einer Schleife.

for (int pos=40; pos<90; pos +=1) {
          servo_arm.write(pos);
}

Nachdem der Schneemann den Hut aufgesetzt hat, wird die Nachricht auf dem Bildschirm gelöscht.

TFTscreen.background(0, 0, 0); 

Als letzte Aktion werden die LED-Ringe ausgeschaltet, allerdings schalten wir jede einzelne LED jede halbe Sekunde einzeln aus.

small_ring.setBrightness(50);
small_ring.setPixelColor(0, s_black);
delay(500);
small_ring.show();
small_ring.setPixelColor(2, s_black);
delay(500);
small_ring.show();
small_ring.setPixelColor(4, s_black);
delay(500);
small_ring.show();
small_ring.setPixelColor(6, s_black);
delay(500);
small_ring.show();
small_ring.setPixelColor(8, s_black);
delay(500);
small_ring.show();
small_ring.setPixelColor(10, s_black);
delay(500);
small_ring.show();
delay(500); 

Nachdem alle LEDs ausgeschaltet wurden, beginnt nach einer kurzen Wartezeit der Ablauf der Hauptschleife von vorn.

Mit diesem Projekt wünschen wir Ihnen ein frohes Weihnachtsfest, genießen Sie Ihre freie Zeit. Wir freuen uns auf Ihre Kommentare und Anregungen.

Frohe Weihnachten und herzlichen Dank.

DisplaysFür arduinoSpecials

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert