Arduino Lektion 36: Multifunktionales Shield

Das Multifunktionale Shield enthält eine vielzahl von Aktoren und Sensoren und Anschlüsse (Interfaces) für weitere Sensoren.

Folgende Aktoren sind auf dem Multifuntionalem Shield (im weiteren nur als Shield bezeichnet) enthalten:

  • 4 SMD LEDs,
  • 4fach 7 Segment LED Display,
  • Buzzer,
  • 3 Push Buttons (Taster),

Folgende Anschlüsse (Interfaces) sind für weitere Sensoren / Aktoren enthalten:

  • LM35,
  • DS18B20,
  • IR LED,
  • Servo

Die Sensoren / Aktoren sind nicht Bestandteil des Lieferumfangs zu dem Shield.

Übersicht

 

Multifunktionales Shield für Arduino UNO & Arduino Leonardo
Multifunktionales Shield für Arduino UNO & Arduino Leonardo

Das Shield ist für den Arduino UNO und Arduino Leonardo konzipiert, d.h. es kann „einfach“ auf den Microcontroller gesteckt werden.

Achtung: Wenn man das Shield auf einen Arduino UNO steckt liegen die letzten beiden PINs des 4fach 7 Segment LED Displays auf dem USB Anschluss des Arduino UNO auf. Daher verwende ich in den folgenden Beispielen ein Arduino Leonardo.

Shield verbunden mit Arduino Leonardo
Shield verbunden mit Arduino Leonardo

Bezug

Das Shield kann über amazon.de oder aber auch bei ebay.de erworben werden.
(Sicherlich gibt es noch andere Portale wo man dieses kaufen kann.)

Der Preis liegt zwischen 1,95€ und 11,95€.

Schaltungen

Folgende Tabelle zeigt die vorhandenen Sensoren & Aktoren und die PINs über welche diese angesprochen werden können.

Element PIN
Potentiometer A0
 Taster S1 A1
Taster S2 A2
Taster S3 A3
Anschluss für LM35
oder DS18B20
A4
IR Sensor (Anschluss) d2
Buzzer d3
4fach 7 Segment Display Latch d4, Clock d7, Data d8

Quellcode

LED Blinken

Das Shield verfügt über 4 SMD LEDs welche an den PINs 10,11,12 und 13 angelegt sind.
Im folgenden Beispiel möchte ich nun die LED D1 (PIN 13) zum Blinken bringen.

//LEDs an den digitalen PINs 10,11,12,13
const byte LED[] = {13,12,11,10};
 
void setup(){
pinMode(LED[0], OUTPUT); //LED1 am digitalen PIN 13
digitalWrite(LED[0], HIGH); //LED1 ausschalten
}
 
void loop(){
  digitalWrite(LED[0], HIGH); //LED1 ausschalten
  delay(1000); //Pause von 1000ms.
  digitalWrite(LED[0], LOW); //LED1 einschalten
  delay(1000); //Pause von 1000ms.
}

LED Fade Effect

Das nachfolgende Beispiel habe ich 1:1 aus dem Tutorial Arduino Lektion 2: LED mit FadeEffekt übernommen.

int brightness = 0;    // Definiert den Startwert für die Helligkeit.
int fadeAmount = 5;    // Definiert die Stufen in welche der Fade erfolgen soll
int pin = 13;           // Definiert den PIN an welchem die LED angeschlossen ist.
int delayTime = 10;    // Definiert den Wert der Pause welche die Loop nach einem Fade machen soll.
 
void setup() {
  pinMode(pin, OUTPUT); // Setzt den PIN9 als Ausgangssignal. 
}    
 
void loop()  {    
    analogWrite(pin, brightness); // Schreibt ein Analoges PWM Signal an den PIN13
    brightness = brightness + fadeAmount; // Addiert einen Schritt auf die Helligkeit
    if (brightness == 0 || brightness == 255) { // Wenn die Helligkeit gleich 0 ODER die Helligkeit gleich 255 dann
        fadeAmount = -fadeAmount ;  // die Schritte im Minusbereich setzen , aus dem Startwert von 5 wird -5
    }             
  delay(delayTime); // eine kleine Pause damit der Fadeeffekt sichtbar wird, sonst würde die LED nur schnell flackern.
}

Potentiometer & 4fach 7 Segment Display

Im folgenden Beispiel möchte ich zeigen wie man den Wert des Potentiometers auf dem 4fach 7 Segment Displays anzeigen kann.

#define potentiometer 0

#define latch 4
#define clk 7
#define data 8

/* Mapping der Adressen für die Zahlen 0 bis 9 */
const byte SEGMENT_MAP[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0X80,0X90};
/* Mapping für die Segmente 0 bis 3 */
const byte SEGMENT_SELECT[] = {0xF1,0xF2,0xF4,0xF8};

/* letzter Zeitpunkt der Ausführung.*/
unsigned long previousMillis = 0;
/* Interval der Ausführung.*/
const long interval = 550;   
 
void setup(){
  Serial.begin(9600);
  pinMode(latch,OUTPUT);
  pinMode(clk,OUTPUT);
  pinMode(data,OUTPUT);
}
 
void loop(){
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) { 
    int value = analogRead(potentiometer);
    Serial.print("Wert des Potentiometer : ");
    Serial.println(value);
  
    WriteNumberToSegment(0 , value / 1000); 
    WriteNumberToSegment(1 , (value / 100) % 10);
    WriteNumberToSegment(2 , (value / 10) % 10);
    WriteNumberToSegment(3 , value % 10);
  }
}

/**
 * Schreibt eine Zahl (value) auf ein Segment (segment).
 */
void WriteNumberToSegment(byte segment, byte value){
  digitalWrite(latch,LOW);
  shiftOut(data, clk, MSBFIRST, SEGMENT_MAP[value]);
  shiftOut(data, clk, MSBFIRST, SEGMENT_SELECT[segment]);
  digitalWrite(latch,HIGH);
}

Taster S1, S2 & S3

Die Taster S1, S2, & S3 sind jeweils mit dem Anschluss beschriftet welchen man für den Sketch benötigt.

Taster S1, S2 und S3 auf dem Multifunktionalem Shield
Taster S1, S2 und S3 auf dem Multifunktionalem Shield

Folgender Quellcode bewirkt dass,

  • wenn der Taster S1 gedrückt wird alle LEDs ausgeschaltet werden,
  • wenn der Taster S2 gedrückt wird die LEDs 1,3 eingeschaltet und die LEDs 2,4 ausgeschaltet werden,
  • wenn der Taster S3 gedrückt wird die LEDs eingeschaltet werden.
//LEDs an den digitalen PINs 10,11,12,13
const byte LED[] = {13,12,11,10};
 
#define BUTTON1 A1 //Taster S1
#define BUTTON2 A2 //Taster S2
#define BUTTON3 A3 //Taster S3
 
void setup(){
pinMode(LED[0], OUTPUT); //LED1 am digitalen PIN 13
pinMode(LED[1], OUTPUT); //LED2 am digitalen PIN 12
pinMode(LED[2], OUTPUT); //LED3 am digitalen PIN 11
pinMode(LED[3], OUTPUT); //LED4 am digitalen PIN 10

digitalWrite(LED[0], LOW); //LED1 ausschalten
digitalWrite(LED[1], LOW); //LED2 ausschalten
digitalWrite(LED[2], LOW); //LED3 ausschalten
digitalWrite(LED[3], LOW); //LED4 ausschalten
}
 
void loop(){
  //Wenn der Taster S1 gedrückt wird,
  //so sollen alle LEDs eingeschaltet werden.
  if(!digitalRead(BUTTON1)){
    setLEDs(LOW, LOW, LOW, LOW);
  }

  //Wenn der Taster S2 gedrückt wird, 
  //so sollen die LEDs 1,3 ausgeschaltet und 2,4 eingeschaltet werden.
  if(!digitalRead(BUTTON2)){
    setLEDs(HIGH, LOW, HIGH, LOW);
  }

  //Wenn der Taster S3 gedrückt wird,
  //so sollen alle LEDs ausgeschaltet werden.
  if(!digitalRead(BUTTON3)){
   setLEDs(HIGH, HIGH, HIGH, HIGH);
  }
}

void setLEDs(int led1Status, int led2Status, int led3Status, int led4Status){
  digitalWrite(LED[0], led1Status);
  digitalWrite(LED[1], led2Status);
  digitalWrite(LED[2], led3Status);
  digitalWrite(LED[3], led4Status);
}

Buzzer

Der Buzzer ist ab Werk mit einem Aufkleber versehen welcher vor gebrauch entfernt werden sollte.

In folgendem Beispiel möchte ich mit dem Potentiometer die Frequenz des Buzzers ändern.

#define potentiometer 0 //Potentiomenter am analogen PIN A0

#define buzzerPin 3 //Buzzer am digitalen PIN 3
 
void setup(){}
 
void loop(){
  int frequenz = analogRead(potentiometer); //Lesen des Wertes vom Potentiometer
  tone(buzzerPin, frequenz); //Ändern der Frequenz des Buzzers
}

Für die nachfolgenden Beispiele werden zusätzliche Sensoren & Aktoren benötigt welche NICHT bestandteil des Lieferumfang des Shields waren.

Temperatursensor LM35

Den Temperatursensor LM35DZ habe ich bereits im Tutorial Arduino Lektion 5: Temperatur messen erläutert daher möchte ich hier „nur“ auf die Verbindung mit dem Shield eingehen.

Auf dem Shield ist eine weiße Markierung welche vermuten läßt wie der Temperatursensor LM35DZ aufgesteckt wird. Dies ist aber nicht so der Temperatursensor wird genau andersherum drauf gesteckt.

Temperatursensor LM35DZ auf dem Multifunktionalem Shield
Temperatursensor LM35DZ auf dem Multifunktionalem Shield
#define latch 4
#define clk 7
#define data 8

#define temperatursensorPin 4 // Bestimmen das der Temperatursensor LM35 an den analogen PIN 0 angeschlossen ist.

const byte SEGMENT_MAP[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0X80,0X90};
const byte SEGMENT_SELECT[] = {0xF1,0xF2,0xF4,0xF8};

void setup() { 
  Serial.begin(9600);  // Verbindungsgeschwindigkeit (Baudrate) auf 9600 setzen.
  pinMode(latch,OUTPUT);
  pinMode(clk,OUTPUT);
  pinMode(data,OUTPUT);
} 
 
void loop() {
  int val = analogRead(temperatursensorPin); // Den analogen Wert des Temperatursensors lesen.
  int dat = (125*val)>>8 ;                   // Aus dem gelesenen Wert die Temperatur berechnen.
  
  //Der Temperatursensor LM35DZ kann nur bist 100C messen jedoch 
  //kann dieser Sketch auf für andere Baugleiche Sensoren verwendet werden.
  WriteNumberToSegment(0 , dat / 1000); 
  WriteNumberToSegment(1 , (dat / 100) % 10);
  WriteNumberToSegment(2 , (dat / 10) % 10);
  WriteNumberToSegment(3 , dat % 10);
}

void WriteNumberToSegment(byte segment, byte value){
  digitalWrite(latch,LOW);
  shiftOut(data, clk, MSBFIRST, SEGMENT_MAP[value]);
  shiftOut(data, clk, MSBFIRST, SEGMENT_SELECT[segment] );
  digitalWrite(latch,HIGH);
}

IR Empfänger

Das Shield verfügt über einen Anschluss für einen IR Empfänger.

Anders als die Markierung für den Temperatursensor stimmt beim IR Sensor die Markierung auf dem Shield.

IR Sensor am Multifunktionalem Shield
IR Sensor am Multifunktionalem Shield
#include <IRremote.h>
 
#define irPin 2 //IR Sensor auf dem digitalen PIN 2

//LEDs an den digitalen PINs 10,11,12,13
const byte LED[] = {13,12,11,10};
 
IRrecv irrecv(irPin);
 
decode_results results;
 
void setup(){
  pinMode(LED[0], OUTPUT); //LED1 am digitalen PIN 13
  pinMode(LED[1], OUTPUT); //LED2 am digitalen PIN 12
  pinMode(LED[2], OUTPUT); //LED3 am digitalen PIN 11
  pinMode(LED[3], OUTPUT); //LED4 am digitalen PIN 10

  digitalWrite(LED[0], HIGH); //LED1 ausschalten
  digitalWrite(LED[1], HIGH); //LED2 ausschalten
  digitalWrite(LED[2], HIGH); //LED3 ausschalten
  digitalWrite(LED[3], HIGH); //LED4 ausschalten
  
  Serial.begin(9600);
  irrecv.enableIRIn();
}
 
void loop(){
  if (irrecv.decode(&results)){ 
    digitalWrite(LED[0], HIGH); //LED1 ausschalten
    digitalWrite(LED[1], HIGH); //LED2 ausschalten
    digitalWrite(LED[2], HIGH); //LED3 ausschalten
    digitalWrite(LED[3], HIGH); //LED4 ausschalten

    String value = String(results.value, HEX);
    
    if(value == "ff30cf"){ digitalWrite(LED[0], LOW); } 

    if(value == "ff18e7"){ digitalWrite(LED[1], LOW); }

    if(value == "ff7a85"){ digitalWrite(LED[2], LOW); }

    if(value == "ff10ef"){ digitalWrite(LED[3], LOW); }
    
    irrecv.resume();
  }
}

Servo und 4fach 7 Segment Display

In folgendem Beispiel möchte ich einen Servo ansteuern und den Wert des Servos auf dem 4fach 7 Segment Display anzeigen.

Servo SG90 am Multifunktionalem Shield
Servo SG90 am Multifunktionalem Shield
Anschluss für den Servo SG90
Anschluss für den Servo SG90
#include <Servo.h>  //Bibliothek zum ansteuern von Servo

#define latch 4
#define clk 7
#define data 8

Servo servo; //Servo Objekt erstellen (noch nicht initialisiert)

const byte SEGMENT_MAP[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0X80,0X90};
const byte SEGMENT_SELECT[] = {0xF1,0xF2,0xF4,0xF8};

int position = 0; //Variable zum speichern von der aktuellen Position
const int waitTime = 3000; //Zeit zum pausieren zwischen den einzelnen Schritten des Servos

void setup() { 
  Serial.begin(9600);
  pinMode(latch,OUTPUT);
  pinMode(clk,OUTPUT);
  pinMode(data,OUTPUT);
  servo.attach(9); //setzen des Servo Objektes auf den digitalen PIN 9 
  servo.write(0);
} 
 
void loop() { 
  //For Schleife zum drehen des Servos um 180°
  for(position = 0; position < 180; position++) { 
    servo.write(position); //Schreiben des aktuellen Wertes der Variable 'position' (1...180)
    displayPosition(position);
  } 

  //For Schleife zum drehen des Servos um 180°  
  for(position = 180; position>=1; position--){ 
    servo.write(position); //Schreiben des aktuellen Wertes der Variable 'position' (180...1)
    displayPosition(position);
  } 
}

void displayPosition(int position){
  //Eine For Schleife, denn eine Pause mit delay
  //ist nicht möglich. Hier muss "nur" die Zeit durch
  //den max Wert der For Schleife angepasst werden.
  for(int i =0;i<750;i++){
    WriteNumberToSegment(0 , position / 1000); 
    WriteNumberToSegment(1 , (position / 100) % 10);
    WriteNumberToSegment(2 , (position / 10) % 10);
    WriteNumberToSegment(3 , position % 10); 
  }
}

void WriteNumberToSegment(byte segment, byte value){
  digitalWrite(latch,LOW);
  shiftOut(data, clk, MSBFIRST, SEGMENT_MAP[value]);
  shiftOut(data, clk, MSBFIRST, SEGMENT_SELECT[segment] );
  digitalWrite(latch,HIGH);
}

IR Sensor, 4fach 7 Segment Display und Servo SG90

Im nächsten Beispiel möchte ich etwas komplexer werden. Es wird nun der Servo mit einer kleinen Fernbedienung bedient. Es gibt für den Arduino (und Raspberry Pi) günstige, kleine Fernbedienungen zum basteln.

IR Fernbedienung für den Arduino und Raspberry Pi
IR Fernbedienung für den Arduino und Raspberry Pi

Von den oben abgebildeten IR (Infrarot) Fernbedienungen nutze ich die rechte (schwarz,  mit den Pfeiltasten) für das folgende Beispiel.

#include <IRremote.h>
#include <Servo.h>  //Bibliothek zum ansteuern von Servo

#define irPin 2 //IR Sensor auf dem digitalen PIN 2

#define latch 4
#define clk 7
#define data 8

const byte SEGMENT_MAP[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0X80,0X90};
const byte SEGMENT_SELECT[] = {0xF1,0xF2,0xF4,0xF8};
 
IRrecv irrecv(irPin);
decode_results results;
String rechts = "ffc23d";
String links = "ff22dd";

Servo servo; //Servo Objekt erstellen (noch nicht initialisiert) 
int servoPosition = 0;

void setup(){
  Serial.begin(9600);
  irrecv.enableIRIn();
  servo.attach(9); //setzen des Servo Objektes auf den digitalen PIN 9 
  servo.write(0);
  
  pinMode(latch,OUTPUT);
  pinMode(clk,OUTPUT);
  pinMode(data,OUTPUT);
}
 
void loop(){
  if (irrecv.decode(&results)){     
    String value = String(results.value, HEX);
    if((value == rechts) && servoPosition < 180){
      servoPosition++;
    } else if((value == links) && servoPosition > 0){
      servoPosition--;
    }
    Serial.print("Servoposition = ");
    Serial.println(servoPosition);
    servo.write(servoPosition);
    irrecv.resume();
  }

  WriteNumberToSegment(0 , servoPosition / 1000); 
  WriteNumberToSegment(1 , (servoPosition / 100) % 10);
  WriteNumberToSegment(2 , (servoPosition / 10) % 10);
  WriteNumberToSegment(3 , servoPosition % 10); 
}

void WriteNumberToSegment(byte segment, byte value){
  digitalWrite(latch,LOW);
  shiftOut(data, clk, MSBFIRST, SEGMENT_MAP[value]);
  shiftOut(data, clk, MSBFIRST, SEGMENT_SELECT[segment] );
  digitalWrite(latch,HIGH);
}

Video

Im nachfolgenden Video habe ich die oben genannten Funktionen zusammen geschnitten.

Multifunktionales Shield für den Arduino

Fazit

Für den Anfang ist das Multifunktionale Shield gut, da es einfach auf den Microcontroller gesteckt wird braucht man sich um eine eventuelle Verkabelung keine Sorgen machen. Jedoch verfügt dieses Shield „nur“ über eine Handvoll Sensoren & Aktoren um die Anschlüsse zu nutzen benötigt man zusätzliche Sensoren wie den Temperatursensor DS18B20 oder LM35. Nach meiner Meinung hätte das Board noch einiges bieten können da ein Temperatursensor nicht den Platz einnimmt.

5 Gedanken zu „Arduino Lektion 36: Multifunktionales Shield

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.