Arduino Tutorials Robotik-AG JKG -...

29
1 Arduino Tutorials Robotik-AG JKG Thomas Jörg | Stand: 2. März 2018 | Version 1.5

Transcript of Arduino Tutorials Robotik-AG JKG -...

Page 1: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

1

Arduino Tutorials Robotik-AG JKG Thomas Jörg | Stand: 2. März 2018 | Version 1.5

Page 2: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

2

Inhalt Arduino Tutorials Robotik-AG Weil der Stadt .......................................................... 1

Arduino Pinouts. ...................................................................................................... 3

Erläuterung: ..................................................................................................... 4

„Blink“: Interne LED: ................................................................................................ 5

Schritt 2: Externe LED ....................................................................................... 5

Potentiometer, LDR, Taster: einfache Sensoren ...................................................... 6

Weitere analoge/lineare Sensoren: ................................................................ 7

Kombination von Sensoren und Aktoren ................................................................. 8

Helligkeit einer LED über Potentiometer/Sensor steuern ............................... 8

Die PWM (Pulsweitenmodulation) .......................................................................... 9

Die H-Brücke .......................................................................................................... 10

Beschaltung des L298n: ......................................................................................... 11

Schaltlogik für EnA: ........................................................................................ 12

Ultraschallsensor HC-SR04 ..................................................................................... 13

Interruptsteuerung HC-SR04 („non-blocking“) ...................................................... 14

Adafruit DVR8833 H-Brücke ................................................................................... 15

Erläuterung zu den Tabellen: ............................................................................ 16

DRV8833: Schaltlogik laut Datenblatt ............................................................ 16

DRV8833: PWM-Betrieb laut Datenblatt ....................................................... 16

Pololu DRV8835 H-Brücke ...................................................................................... 17

WS2812B „Neopixels“ ............................................................................................ 18

Der I2C-Bus (sprich: „I-Quadrat-C“) ........................................................................ 19

Beispiele einiger I2C Sensoren/Aktoren für die Robotik: ...................................... 20

OLED128x32 I2C mit SSD1306-Controller ............................................................... 21

Der MPU 6050 IMU-Sensor .................................................................................... 22

Schritt 1: Die Bibliotheken von Jeff Rowberg ................................................ 22

Schritt 2: Verkabelung .................................................................................... 22

Schritt 3: Kalibrierung des MPU 6050 ............................................................ 23

Schritt 4: Test des MPU 6050 ......................................................................... 23

Ersatz für den Ultraschall: VL53L0X-TOF-I2C-Sensor .............................................. 25

Funktionsüberprüfung ................................................................................... 27

Verwendete Bibliotheken .............................................................................. 27

Interrupt-Modus des VL53L0X ........................................................................... 27

Erläuterung der Sensorbefehle im Quelltext: ................................................ 27

„Blink“-Sketch neu: Timersteuerung...................................................................... 28

Skript-Variante 1: Timer-Prinzip ..................................................................... 28

Skript-Variante 2: Zeitmessung eines Loops .................................................. 28

Page 3: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

3

Arduino Pinouts. Quellen-Grundlage: https://makezine.com/wp-content/uploads/2013/02/arduino_uno_pinout_web.png

Page 4: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

4

Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben nach rechts unten gezählt) 7 + 6 + 10 + 8 = 31 Pins. Die wichtigsten Pinouts sind:

5V: Entweder: Eingangsspannung von 5V für die Spannungsversorgung des Arduinos aus einer externen Quelle

oder: Ausgangsspannung von 5V für die permanente Versorgung von LEDs oder Sensoren.

Achtung! Wird der 5V-Pin als Spannungs-Eingang verwendet, wird die Spannung NICHT reguliert!

3V3: Ausgangsspannung von 3,3V für die permanente Versorgung von LEDs oder Sensoren.

Vin: Hierüber kann der Arduino mit einer externen Spannung zwischen 7 und 12 Volt versorgt werden. Ein Spannungswandler sorgt für

konstante Spannungsversorgung des Arduinos von 5V

GND (3 mal): „Ground“, „Minuspol“

A0 … A5: „ADC“ Analog-Digital-Wandler. Hier können analoge Sensorwerte eingelesen werden. C-Befehl: analogRead(A1);

SCL / SDA: I2C-Bus, „Serial-Clock“ / „Serial Data“, Fortgeschrittenes Feature

SCK /MISO /MOSI / SS: SPI-Bus, „Serial Clock“ / „Master In Slave Out“ / „Master Out Slave In“ / „Slave Select“, Fortgeschrittenes Feature

PWM (5 mal): „Puls-Weiten-Modulation“, Ausgabe von Analog-ähnlichen Werten in Form von Rechteckpulsen

TX / RX: Serielle Kommunikationsschnittstelle, TX -> „Transmit“, senden / RX -> „Receive“, empfangen

Es können die Pins 1 bis 13 und A0 bis A5 ebenfalls als digitale Pins genutzt werden! Das heißt: Sie können programmiert werden.

NICHT programmierbar sind die Pins Reserved / Reset / IOREF / GND / 5V / 3V3 / Vin / Aref. Das sind 10 Stück (GND gibt es 3 mal)

Page 5: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

5

„Blink“: Interne LED: Die interne LED an Pin 13 zum Blinken bringen:

void setup() // Setup-Funktion Anfang

pinMode(13, OUTPUT); // Pin Nummer 13 wird als Output, also Ausgang geschaltet.

// Setup-Funktion Anfang

void loop() // Endlosschleife Anfang

digitalWrite(13, HIGH); // LED anschalten

delay(1000); // 1000 Millsekunden warten

digitalWrite(13, LOW); // LED ausschalten

delay(1000); // 1000 Millsekunden warten

// Endlosschleife Ende

Nun sollte die interne LED auf dem Board leuchten.

Schritt 2: Externe LED An den Arduino-Pin 13 wird eine LED zusammen mit einem ca. 150 Ohm-Widerstand

angebunden. Damit der Stromkreis geschlossen ist, verbindet man mit ‚GND‘.

Setzt man den Pin 13 nun durch Programmierung auf ‚HIGH‘, dann wird er angeschaltet.

Und dann liefert er Spannung, um die LED zum Leuchten zu bringen.

Der Quelltext bleibt dabei gleich.

NIEMALS die LED ohne Widerstand mit demArduino verbinden!

Exkurs: Berechnung Vorwiderstand für LED: Eine rote LED benötigt IMMER 1,6 Volt Betriebsspannung.

Der Arduino liefert 5 Volt an jedem PIN.

5 Volt – 1,6 = 3,4 Volt müssen „vernichtet“ werden.

Zusätzlich dürfen maximal 25 Milli-Ampere Stromstärke herrschen.

Mit R = U/I = 3,4 Volt / 0,025 Ampere = 150 Ohm dimensioniert man den Widerstand.

https://www.elektronik-kompendium.de/sites/bau/1109111.htm

100 Ohm bis

330 Ohm

Abbildung 1: Ansteuerung einer LED

100 Ω 150 Ω 220 Ω 330 Ω 470 Ω

Abbildung 2: Beispiele für LED-Vorwiderstände.

Widerstandswerte werden durch die Farben der Ringe codiert:

Die oberen beiden Ringe entsprechen einer Zahl, der dritte Ring einem Multiplikator (z.B. “mal 10” oder “mal 1000”. Der letzte Ring gibt die Genauigkeit wider.

https://www.elektronik-

kompendium.de/sites/bau/1109051.htm

Page 6: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

6

Potentiometer, LDR, Taster: einfache Sensoren Als Beispiel für Sensoren sind hier Potentiometer und LDR gezeigt. Viele andere Sensoren lassen sich genauso programmieren und an den Arduino anschließen.

Abbildung 3: Poti am Arduino

Abbildung 4: Simple Sensorschaltung

Ein ‚Potentiometer‘ am Arduino: Der Arduino misst, wie weit das Poti nach links oder nach rechts gedreht ist. Daraus erzeugt er einen Wert zwischen 0 und 1023.

Ein ‚Helligkeitssensor‘ am Arduino: Der Arduino misst, wie stark das Licht eingestrahlt wird. Der LDR bildet mit dem zweiten Widerstand einen sogenannten Spannungsteiler, genauso wie ein Potentiometer. Deshalb liest man den Sensor genauso aus.

int sensorwert = 0; //Variable für Sensor

void setup()

pinMode(A0, INPUT);

Serial.begin(9600); //Ausgabe an PC vorbereiten

void loop()

sensorwert = analogRead(A0); //Sensor auslesen

Serial.println(sensorwert); //auf dem PC ausgeben

int sensorwert = 0; //Variable für Sensor

void setup()

pinMode(A0, INPUT);

Serial.begin(9600); //Ausgabe an PC vorbereiten

void loop()

sensorwert = analogRead(A0); //Sensor auslesen

Serial.println(sensorwert); //auf dem PC ausgeben

10 kOhm-

Potentiometer

LDR: “Light Dependent Resistor”

Page 7: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

7

Abbildung 5: Schalter am Arduino

Weitere analoge/lineare Sensoren: Beschleunigungssensor, z.B. ADXL335

Temperatursensor, z.B. LM35 (0-100°C)

Licht/Farb/Infrarotsensoren, z.B. CNY70

Magnetsensoren, z.B. Allegro A1324

Barometer (Drucksensoren), z.B. MPX 4115A

Kraftsensoren, z.B. FSR 400

Ein ‚Schalter‘ am Arduino: Der Arduino misst, ob man den Schalter gedrückt hat oder nicht. Der Wert ist 0 oder 1.

int taster = 0; //integer-Variable für Taster

void setup()

pinMode(A0, INPUT);

Serial.begin(9600);//Ausgabe an PC vorbereiten

void loop()

taster = digitalRead(A0);//Sensor auslesen

Serial.println(taster);//auf dem PC ausgeben

10 kOhm-

Widerstand

Page 8: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

8

Kombination von Sensoren und Aktoren

Helligkeit einer LED über Potentiometer/Sensor steuern

int sensorwert = 0; //integer-Variable für Sensor

void setup()

pinMode(A0, INPUT); //zum Auslesen des Potis

pinMode(11, OUTPUT); //zum Ansteuern der LED

Serial.begin(9600); //Ausgabe an PC vorbereiten

void loop()

sensorwert = analogRead(A0); //Sensor auslesen

analogWrite(11, sensorwert/4); //PWM-Ansteuerung der LED

Serial.println(sensorwert); //auf dem PC ausgeben

Erläuterung: zu „analogWrite(11, sensorwert/4)“:

Der Befehl „analogRead“ liefert Werte zwischen 0 und 1023.

Der Befehl „analogWrite“ schreibt aber nur im Bereich zwischen 0 und 255.

Daher muss der Bereich von 0-1023 auf den Bereich von 0-255 „gemapped“ (abgebildet) werden.

Das erreicht man, indem man durch vier teilt.

Abbildung 6: Sensor und Aktor zusammen

Page 9: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

9

Die PWM (Pulsweitenmodulation) Ein Mikrocontroller wie der Arduino Uno kann keine unterschiedlichen Spannungswerte ausgeben.

(moderne Mikrocontrollerboards wie z.B. der Arduino Due besitzen sogenannte DACs (digital to analog-Konverter) ).

Die Helligkeit der LED wird also nicht durch die Spannung des Uno gesteuert, sie erhält immer 5 Volt. Die Steuerung erfolgt über schnelles Ein- und Ausschalten der 5-Volt-

Spannung.

Helles Licht bedeutet „Lange anschalten, kurz ausschalten“, weniger helles Licht erreicht man durch

„kurz anschalten, lange ausgeschaltet lassen“.

Die unterschiedlichen Verhältnisse zwischen An- und Ausgeschaltet bezeichnet man als „Duty-Cycle“.

Ein Duty-Cycle von 50% bedeutet, dass die „An“-Dauer so lange ist wie die „Aus“-Dauer.

Der Arduino schaltet dabei den Analogpin sehr schnell: er ist normalerweise mit 500Hz getaktet,

schaltet also ca. 500mal pro Sekunde an- und aus.

Abbildung 8: PWM gemessen am Oszilloskop

Abbildung 7: Prinzip der PWM

Page 10: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

10

Die H-Brücke Problem: Ein Motor kann nicht vom Arduino direkt angesteuert werden, denn er benötigt viel Energie, die der Arduino nicht liefern kann.

Größenordnung: Maximale Leistungsabgabe Arduino Uno 200mA bei 5 Volt, entspricht 5V * 0,2A = 1 Watt. Anforderungen Motor z.B. Pololu 73:1 Metal Gearmotor: 3,3

Ampere maximal bei 6Volt entspricht 19,8 Watt.

Es muss also ein Bauteil zwischen Arduino und Motor zwischengeschaltet werden, welches einerseits vom Arduino Signale annimmt und weiter die Motoren ansteuert.

Da hier elektrische Leistung gefordert ist, spricht man von sogenannter Leistungselektronik. Eine H-Brücke kann darüber hinaus einen Motor sowohl vorwärts als auch

rückwärts laufen lassen. Für einen Roboter ist die H-Brücke daher ein zentrales Bauteil!

Die Geschwindigkeit des Motors wird über die H-Brücke mit einer PWM gesteuert. Je geringer der Duty-Cycle, desto langsamer bewegt sich der Motor.

Der L298N beinhaltet 2 voneinander unabhängige H-Brücken. Jede einzelne H-Brücke kann einen Motor ansteuern. Diese H-Brücken können betrieben werden zwischen 5

Volt und 35 Volt zur Motorsteuerung, und vertragen dabei maximal 2 Ampere

Stromstärke mit 20 Watt maximaler Gesamtleistung.

Output Motor 2 Output Motor 1

Motor-

Versorgungsspannung

PINs zur Motorsteuerung:

Hier ist die Verbindung

zum Arduino

Abbildung 10: Beschaltung laut Datenblatt des L298N

Abbildung 9: H-Brücke von oben

Page 11: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

11

Beschaltung des L298n: Abbildung 11: Ausschnitt aus der Schaltung

Abbildung 12: Schaltung für "Vorwärts"

Abbildung 13: Schaltung für "Rückwärts"

Page 12: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

12

EnA („Enable A“) ist die Vorrausetzung für die Schaltung.

Ist EnA ausgeschaltet, wird auch gleichzeitig die Motor-

versorgung abgeschaltet.

bedeutet „Logisches UND“ ,

bedeutet „Logisches UND mit einem

Invertierenden Eingang“

Schaltlogik für EnA:

EnA In1 V1 R2 EnA In2 R1 V2

0 0 0 0 0 0 0 0

0 1 0 0 0 1 0 0

1 0 0 1 1 0 0 1

1 1 1 0 1 1 1 0

• Um die H-Brücke 1 „vorwärts“ zu schalten, müssen

V1 und V2 angeschaltet,

R1 und R2 ausgeschaltet sein.

Es muss also: In1 = HIGH, In2 = LOW

• Um die H-Brücke 1„rückwärts“ zu schalten, müssen

R1 und R2 angeschaltet,

V1 und V2 ausgeschaltet sein.

Es muss also: In1 = LOW, In2 = HIGH

int EnA = 10;

int IN1 = 3;

int IN2 = 5;

void setup ()

pinMode (EnA, OUTPUT);

pinMode (IN1, OUTPUT);

pinMode (IN2, OUTPUT);

void loop ()

digitalWrite (IN1, HIGH);

digitalWrite (IN2, LOW);

for (int i=0; i<256; i++)

analogWrite (EnA, i);

delay (10);

digitalWrite (IN1, LOW);

digitalWrite (IN2, HIGH);

for (int i=0; i<256; i++)

analogWrite (EnA, i);

delay (10);

digitalWrite (IN1, LOW);

digitalWrite (IN2, LOW);

analogWrite (EnA, 0);

Abbildung 14: L298N mit Arduino

Page 13: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

13

Ultraschallsensor HC-SR04 Gute Quelle: http://www.mikrocontroller-elektronik.de/ultraschallsensor-hc-sr04/

int trigger = 3; // Arduino Pin an HC-SR04 Trig

int echo = 2; // Arduino Pin an HC-SR04 Echo

void setup()

pinMode(trigger, OUTPUT);

pinMode(echo, INPUT);

Serial.begin(9600);

void loop()

long entfernung = 0;

long zeit = 0;

//Mess-Sequenz start

digitalWrite(trigger, LOW); // Trigger ausschalten

delayMicroseconds(3); // kurz warten

noInterrupts(); // Störungsfreien Betrieb der Messung sicherstellen

digitalWrite(trigger, HIGH); // Trigger Impuls 40 Kilohertz AN ...

delayMicroseconds(10); // ... für 10 Mikrosekunden

digitalWrite(trigger, LOW); // Trigger wieder ausschalten

zeit = pulseIn(echo, HIGH); // Nun wird die Echo-Zeit gemessen.**

interrupts(); // Jetzt darf wieder "gestört" werden

//////////////////////////// // Mess-Sequenz Ende, nun erfolgt Umrechnung

zeit = (zeit / 2); // Zeit halbieren, weil Schall hin- und zurückläuft

entfernung = zeit / 29.1; // Umrechnung Zeit in Zentimeter (v = 343 m/s)

Serial.println(entfernung);

** Der Messvorgang wird durch eine fallende Flanke am Trigger-Eingang ausgelöst. Das vorhergehende High-Signal muss dabei eine Mindestzeit von 10 Mikrosec anliegen.

Strombedarf: 2mA pro Messung

Signalart: TTL-Puls (HIGH/LOW)

Max. Entfernung: 3m

Min. Entfernung: 2 cm

Max. Messungen/s: 50

Genauigkeit: ca. 3mm (naja…)

Abbildung 15: Schaltung SR04

Page 14: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

14

Interruptsteuerung HC-SR04 („non-blocking“) Problematisch am Skript auf der vorherigen Seite: Der Roboter reagiert nicht mehr auf seine Umwelt, solange er auf den Echopuls wartet. Das rührt her von der Funktionsweise des Befehls „pulseIn“. Ist dieser Befehl aktiv, so werden in der Zeitspanne zwischen Schallaussendung und Echo keine weiteren Befehle mehr abgearbeitet. Beispielrechnung: ist die Gesamtstrecke beispielsweise etwa 1,5 Meter lang (Abmessungen eines Soccerfeldes), so vergehen im „Worst-Case“ 2*1,5m/343m/s = 8,75 Millisekunden, in denen der Roboter reaktionslos einfach weiterfährt. Lösung des Problems: Auf das Echo wird nicht gewartet, sondern es wird ein Interrupt eingerichtet. Allgemein ist ein Interrupt ist eine Unterbrechung des normalen Programmablaufs durch ein plötzliches, unvorhersehbares Ereignis – zum Beispiel durch einen sich ändernden Sensorwert (externer Interrupt) oder einen fertig abgelaufenen Zeitraum (interner Timerinterrupt). Im nebenstehenden Skript ist das externe Ereignis das plötzliche Umschalten des Echopins, wenn er das Ultraschallecho bemerkt. Dann wird eine sogenannte „ISR“, eine „Interrupt-Service-Routine“ ausgelöst, die den aktuellen Programmablauf unterbricht und die Entfernung berechnet.

int trigger = 3;

int echo = 2; //nicht ändern: Interruptpin am UNO!

volatile long echo_start = 0; //'volatile' notwendig für Interrupts

volatile long echo_ende = 0;

volatile long entfernung = 0; //in mm

volatile bool darfPulsen = true;

void setup()

pinMode(trigger, OUTPUT);

pinMode(echo, INPUT);

attachInterrupt(digitalPinToInterrupt(echo), echo_ISR, CHANGE);

Serial.begin (9600);

void loop()

triggerPuls(); //wird nur ausgeführt, wenn das Echo bereits zurück ist

delay(50);

void triggerPuls()

if (darfPulsen)

darfPulsen = false;

digitalWrite(trigger, LOW);

delayMicroseconds(3);

digitalWrite(trigger, HIGH);

delayMicroseconds(10);

digitalWrite(trigger, LOW);

void echo_ISR()

switch (digitalRead(echo))

case HIGH:

echo_ende = 0;

echo_start = micros();

break;

case LOW:

echo_ende = micros();

entfernung = (echo_ende - echo_start)/0.582; //Berechnung in mm

Serial.println(entfernung);

darfPulsen = true;

break;

Page 15: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

15

Adafruit DVR8833 H-Brücke Der TI 8833-Motortreiber arbeitet im Bereich zwischen 2,7 – 10,8 Volt. Standardmäßig ist eine

Strombegrenzung von 1,2 A pro H-Brücke eingestellt. Das hält einige Motoren leider davon ab,

zu starten. In diesem Fall wirken die 1,2 A als Anlaufstrombegrenzung, der Motor bleibt

stehen. Mit zwei Methoden lässt sich das eventuell ändern:

a) 0,2 Ohm-Widerstand zwischen AS (BS)-Kanal und GND verdoppeln die Maximalstromstärke.

b) Die PWM-Frequenz kann heruntergesetzt werden (bis herunter auf 30 Hertz).

Bei niedriger PWM-Frequenz läuft der Motor zwar unrund, startet aber bei geringen Duty-

Cycles. Im Skript unten wird der eher unkritische Timer1 verändert, sodass delay ()- und

milli()-Funktionen unverändert funktionieren.

void setup()

pinMode(10, OUTPUT);

pinMode(9, OUTPUT);

cli(); //Interrupts aus.

TCCR1B = TCCR1B & 0b11111000 | 0x05; //PWM auf 30 Hz

sei(); //Interrupts an.

void loop()

digitalWrite(10, LOW); //Vorwärtslauf

for (int i = 1; i < 255; i++) //Beschleunigen

analogWrite(9, i);

delay(10);

for (int i = 255; i > 0; i--) //Abbremsen

analogWrite(9, i);

delay(10);

delay(100);

digitalWrite(9, LOW); //Rückwärtslauf

for (int i = 1; i < 255; i++) //Beschleunigen

analogWrite(10, i);

delay(10);

for (int i = 255; i > 0; i--) //Abbremsen

analogWrite(10, i);

delay(10);

7,4V LiPo

0,2 Ohm-

Widerstand

Abbildung 16: Verdrahtung DRV8833

Abbildung 17: Foto des Aufbaus

Page 16: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

16

DRV8833: Schaltlogik laut Datenblatt

xIN1 xIN2 xOUT1 xOUT2 Funktion

0 0 0 0 Gleiten

0 1 LOW HIGH Rückwärts

1 0 HIGH LOW Vorwärts

1 1 LOW LOW Bremse

DRV8833: PWM-Betrieb laut Datenblatt

xIN1 xIN2 Funktion

PWM 0 Vorwärts mit schnellem Stromabklingen

PWM 1 Vorwärts mit langsamem Stromabklingen

0 PWM Rückwärts mit schnellem Stromabklingen

1 PWM Rückwärts mit langsamem Stromabklingen

Erläuterung zu den Tabellen:

xIN1, xIN2, xOUT1, xOUT2: “x” steht für

Entweder Kanal A oder Kanal B

SLP, Sleep-Modus:

In Abbildung 16 direkt an 5V angeschlos-

sen, also auf HIGH. Kann auch digital an-

gesteuert werden.

Wird SLP auf LOW gesetzt, wird der

gesamte Chip abgeschaltet.

Abbildung 18: Sleep-Funktion

Page 17: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

17

Pololu DRV8835 H-Brücke Der TI DRV8835-Motortreiber beinhaltet zwei unabhängige H-Brücken und arbeitet im Bereich zwischen 1,5 und 11 Volt. Er kann kontinuierlich 1,2 Ampere pro H-Brücke liefern. Bei Vergleich mit dem Datenblatt sieht man, dass der Motortreiber im PHASE/ENABLE mode betrieben wird.

Mo

tor

A

PIN 9 Enable, PWM

PIN 7 Richtung

A OUT1 A OUT2 Funktion

LOW - 0 Volt 0 Volt Bremsen

HIGH (PWM) HIGH 0 Volt VINBatterie Rückwärts

HIGH (PWM) LOW VINBatterie 0 Volt Vorwärts

Mo

tor

B

PIN 10 Enable, PWM

PIN 8 Richtung

B OUT1 B OUT2 Funktion

LOW - 0 Volt 0 Volt Bremsen

HIGH (PWM) HIGH 0 Volt VINBatterie Rückwärts

HIGH (PWM) LOW VINBatterie 0 Volt Vorwärts

void setup()

pinMode(9, OUTPUT); //Motor 1: PWM-PIN

pinMode(7, OUTPUT); //Motor 1: Richtungs-PIN

pinMode(8, OUTPUT); //Motor 2: PWM-PIN

pinMode(10, OUTPUT);//Motor 2: Richtungs-PIN

void loop()

beideVorwaertsRueckwaerts();

beidePWM();

void beidePWM()

for (int i = 0; i < 255; i++)

analogWrite(9, i);//M1 vorwaerts

digitalWrite(7, LOW);

analogWrite(10, i);//M2 vorwaerts

digitalWrite(8, LOW);

delay(20);

for (int i = 0; i < 255; i++)

analogWrite(9, i);//M1 rueckwaerts

digitalWrite(7, HIGH);

analogWrite(10, i);//M2 rueckwaerts

digitalWrite(8, HIGH);

delay(20);

void beideVorwaertsRueckwaerts()

digitalWrite(9, HIGH);//Motor A vorwaerts

digitalWrite(7, LOW);

delay(1000);

digitalWrite(9, HIGH); //Motor A rueckwaerts

digitalWrite(7, HIGH);

delay(1000);

digitalWrite(9, LOW); //Motor A stopp

digitalWrite(7, LOW);

digitalWrite(10, HIGH); //Motor B vorwaerts

digitalWrite(8, LOW);

delay(1000);

digitalWrite(10, HIGH); //Motor B rueckwaerts

digitalWrite(8, HIGH);

delay(1000);

digitalWrite(10, LOW); //Motor B stopp

digitalWrite(8, LOW);

Abbildung 19: Pololu DRV8835 Verdrahtung

Page 18: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

18

WS2812B „Neopixels“ Hierbei handelt es sich um Dreifarb-RGB-LEDs, die 2563 = 16,7Mio Farben darstellen kann.

Die LED besitzt einen eigenen Controller, der mittels einer Adafruit-Bibliothek angesteuert

werden kann (Einbindung der Bibliothek siehe Abbildung 21):

https://github.com/adafruit/Adafruit_NeoPixel/archive/master.zip

Mittels dieser Bibliothek kann die LED recht einfach programmiert werden. Diese sogenannten

„Neopixels“ lassen sich in hoher Anzahl hintereinanderschalten und programmieren. Hier

ist die Programmierung eines einzelnen Neopixel beispielhaft an Pin 11 abgebildet:

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel pixel=Adafruit_NeoPixel(1,11,NEO_GRB+NEO_KHZ800);

void setup(void)

pixel.begin();

void loop(void)

pixel.setPixelColor(0, pixel.Color(255, 0, 0)); pixel.show();

delay(5); pixel.setPixelColor(0, pixel.Color(0, 255, 0));

pixel.show();

delay(5);

pixel.setPixelColor(0, pixel.Color(0, 0, 255));

pixel.show();

delay(5); pixel.setPixelColor(0, pixel.Color(0, 0, 0));

pixel.show();

delay(5);

Neopixel-Bibliothek

1. Neopixel: LED Nr.0

Anzahl Neopixels

Arduino-Pin

Abbildung 20: Schaltschema

Neopixel

Abbildung 21: Einbindung der

Bibliothek

Abbildung 22: Anschlüsse

Neopixel

Page 19: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

19

Der I2C-Bus (sprich: „I-Quadrat-C“) Problem: Viele Sensoren sind in der simplen Spannungsteiler Schaltung zu ungenau (Stichwort: 10-Bit Auflösung des Arduino-Uno-ADC).

Außerdem benötigen viele Sensoren eine aufwendige Datenaufbereitung, die schnell sein muss. Ein gutes Beispiel ist der nebenstehend

abgebildete BNO055, ein „Orientierungssensor“, bei dem Gyro-, Beschleunigungs- und Kompass-Sensor zusammenwirken: Jeder der drei

Sensortypen liefert x-, y- und z-Rohdaten. Diese insgesamt 9 verschiedenen Daten müssen mathematisch sehr aufwendig verarbeitet werden.

Das würde einen einzelnen Arduino deutlich überfordern.

Deshalb verbaut man oftmals Sensoren mit eigenen kleinen Mikrocontrollern zusammen. Der Sensor-eigene Mikrocontroller ist dann einerseits

für die Datenverarbeitung zuständig. Weiterhin stellt dieser Sensor-Controller dem Arduino dann die fertig aufbereiteten Daten zur Verfügung.

Die Daten fließen vom Sensor-Controller zum Arduino in einer eigenen standardisierten Sprache, die über eigene standardisierte Leitungen

erfolgt. Man spricht bei der Sprache von einem sogenannten „Protokoll“, die Leitungen nennt man „BUS“ (BUS für „binary unit system“).

Tipp: Bevor man ein I2C-Gerät besorgt und anschließt, bitte UNBEDINGT darauf achten, dass

a) eine gute ausführliche Dokumentation zum Gerät vorhanden ist

b) eine Bibliothek für den Arduino bereits geschrieben ist.

Sonst verliert man Zeit und Nerven!

Spannungsversorgung

für den Sensor

Serial Clock

Datenleitung

Abbildung 23: I2C-Beispiel BNO055

Abbildung 24: Verkabelungsprinzip I2C-Sensor am Beispiel Adafruit TSL2561

MASTER SLAVE

Page 20: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

20

Beispiele einiger I2C Sensoren/Aktoren für die Robotik: Sensor BNO055

Lagesensor TMP006 Infrarotsensor

TCS34725 Farbsensor

Abbildung

Speicher 7716 Byte (23%) 11116 Byte (34%) 6874 Byte (21%)

Libraries Adafruit_BNO055-master.zip

Adafruit_TMP006-master.zip

Adafruit_TCS34725-master.zip

Sensor VL53L0X „Time Of Flight“ Distanz-S.

AKTOR: OLED Display SSD1366

Abbildung

Speicher 17256 Bytes (53%) 6308 Bytes (19%)

Libraries Adafruit_VL53L0X-master.zip

Adafruit_SSD1306-master.zip Adafruit-GFX-Library-master.zip

Erläuterung: Die Bibliotheken für die Sensoransteuerung benötigen oftmals

selbst eine große Menge an Speicher. Da der Uno nur 32kB an nutzbarem

Speicher besitzt, muss man hier mit dem Speicherbedarf aufpassen und

kalkulieren!

// i2c_scanner

// This sketch tests the standard 7-bit addresses

#include <Wire.h>

void setup()

Wire.begin();

Serial.begin(9600);

Serial.println("\nI2C Scanner");

void loop()

byte error, address;

int nDevices;

Serial.println("Scanning...");

nDevices = 0;

for (address = 1; address < 127; address++ )

Wire.beginTransmission(address);

error = Wire.endTransmission();

if (error == 0)

Serial.print("I2C device found at address 0x");

if (address < 16)

Serial.print("0");

Serial.print(address, HEX);

Serial.println(" !");

nDevices++;

else if (error == 4)

Serial.print("Unknow error at address 0x");

if (address < 16)

Serial.print("0");

Serial.println(address, HEX);

if (nDevices == 0)

Serial.println("No I2C devices found\n");

else

Serial.println("done\n");

delay(5000);

Page 21: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

21

OLED128x32 I2C mit SSD1306-Controller

Der Controller besitzt die I2CAdresse 0x3C. Angeschlossen wird das Display wie folgt:

OLED Arduino UNO

VCC +5V

GND GND

SCL A5 (I2C Anforderung)

SDA A4 (I2C Anforderung)

Als Bibliotheken werden verwendet:

https://github.com/adafruit/Adafruit_SSD1306/archive/master.zip

https://github.com/adafruit/Adafruit-GFX-Library/archive/master.zip

#include <Adafruit_SSD1306.h>

#include <Wire.h>

#include <Time.h>

#define OLED_RESET 4

Adafruit_SSD1306 display(OLED_RESET);

void setup()

Serial.begin(9600);

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);// I2C addr 0x3C

void loop()

display.clearDisplay();

display.setTextSize(0.5); // Textgröße festlegen

display.setTextColor(WHITE);// Textfarbe

display.setCursor(0,0); // Position des Cursors

display.println("Programm laeuft seit:");

display.println(millis());

display.display();

delay(1000);

Abbildung 25: OLED Anschlüsse

Page 22: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

22

Der MPU 6050 IMU-Sensor Der Controller besitzt die Adresse i2C-Adresse 0x68, wenn ADO auf LOW (bzw. Nicht angeschlossen) liegt und 0x69, wenn ADO auf HIGH gesetzt

wird. Datenaustausch erfolgt via I2C, allerdings wird noch ein weiterer PIN am Arduino für einen Interrupt benötigt. Wir verwenden hier Pin 2

(sollte man so verwenden, weil die Bibliotheken darauf ausgerichtet sind). Der Interrupt bewirkt folgendes: Der MPU besitzt einen kleinen internen

Speicher, der sich durch die permanenten Messungen füllt. Läuft dieser Speicher voll, funktioniert der MPU nicht mehr korrekt – allerdings meldet

er sich dann via Interrupt-Signal über den INT-Pin. Durch diesen Interrupt wird in der Arduino-Bibliothek die Leerung des Speichers initiiert und der

Controller läuft im Anschluss weiter.

Schritt 1: Die Bibliotheken von Jeff Rowberg

https://github.com/jrowberg/i2cdevlib

Packt man die Zip-Datei aus, die man auf der Github-Webseite herunterladen kann, erhält man eine große Anzahl verschiedener

Bibliotheken, von denen wir zwei (2!) Stück benötigen. Wir wechseln in den Arduino-Unterordner und wählen I2Cdev und MPU6050

aus. Diese werden dann per Hand in den Arduino-Library-Ordner kopiert. Im Anschluss kann man die Bibliotheken und Beispiele in

der Arduino-Entwicklungsumgebung verwenden.

Schritt 2: Verkabelung Der MPU6050 benötigt VCC bei 3,3 Volt (5V läuft u.Umständen instabil!)

Abbildung 27: Libraries einbinden

Abbildung 26: Der MPU6050

Abbildung 28: Verkabelung MPU 6050

Page 23: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

23

Schritt 3: Kalibrierung des MPU 6050 Der MPU besitzt einen Offset durch Fertigungstoleranzen. Diesen Offset muss man

durch Kalibrierung kompensieren. Man nutzt dazu ein Skript, das den individuellen

Offset eines jeweiligen Sensors bestimmt und als Zahl ausgibt. Diese Zahlenwerte

muss man im Anschluss in sein eigentliches Skript einbauen. Das Skript ist hier:

http://42bots.com/tutorials/arduino-script-for-mpu-6050-auto-calibration/

http://wired.chillibasket.com/2015/01/calibrating-mpu6050/

Das Skript wurde geschrieben von [email protected].

Die aktuelle Version ist: “Version 1.1 (31th January 2014)”. Danach kann man

googeln. Die Werte setzt man nun in sein Skript ein. Hier wurde das Skript

DMP6 verwendet.

Schritt 4: Test des MPU 6050 Getestet wird mit einem Processing-Skript, welches die Sensorneigung visualisiert. Processing ist eine

portable Java-Entwicklungsumgebung und kann unter www.processing.org heruntergeladen werden.

Es wurde mit der 32-bit-Variante der Version 3.3.6 gearbeitet. Nach der Installation wechselt man in

das Verzeichnis \processing\modes\java\libraries.

In diesen Library-Ordner werden die sogenannten “Toxic-Libs” kopiert, eine OpenSource-Physics-

Bibliothek. Diese Biblioteken findet man unter:

https://bitbucket.org/postspectacular/toxiclibs/downloads/

Abbildung 29: Ausgabe Kalbrierskript

Abbildung 30: Eintragen der Kalibrierwerte

Abbildung 31: Toxiclibs in Processing einbinden

Page 24: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

24

Das DMP6-Skript, in dem bereits in Schritt 3 die Kalibierungswerte eingetragen wurden, wird nun auf die Processing-

Demo umgestellt. Dazu wird Zeile 100 auskommentiert und Zeile 117 aktiviert, sodaß die OUTPUT_TEAPOT-Demo

von Processing funktioniert. Das so abgeänderte Skript wird kompiliert und auf den Arduino geladen.

In Processing lädt man aus dem Jeff-Rowberg-Ordnersystem die MPUTeapot.pde – Javadatei:

Es handelt sich dabei um eine Demo, welche sich über die Serielle Schnittstelle mit dem Arduino verbindet, auf diese

Art die Sensordaten des MPU 6050 empfängt und in einem kleinen Grafikfenster visualisiert. Startet man das Programm,

so erscheint ein Fenster mit einem kleinen Flugzeugmodell, welches auf die Bewegung des Sensors reagiert.

Abbildung 32: Anpassung des DMP6-Skripts

Abbildung 33: Demofenster

von Processing

Page 25: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

25

Ersatz für den Ultraschall: VL53L0X-TOF-I2C-Sensor Der Sensor benutzt das I2C-Protokoll, und besitzt die Adresse 0x29.

Der VL53L0X funktioniert im Prinzip wie ein Ultraschallsensor. Während beim

Ultraschallsensor aber Schallwellen genutzt werden, bei dem die Zeit bis zum Echo in

einen Abstand mittels Schallgeschwindigkeit umgerechnet wird, geschieht dies beim

einem TOF („Time Of Flight“)-Sensor durch die Nutzung von Licht: 940nm-Lichtpulse

(Infrarot) werden ausgesendet, an entfernten Gegenständen reflektiert und zum

Sensor zurückgeworfen. Misst man die Zeit zwischen Licht-Aussenden und Licht-

Empfangen, kann mittels Lichtgeschwindigkeit die Entfernung berechnet werden.

Die notwendige Elektronik ist aufgrund der Zeitanforderungen allerdings deutlich

aufwendiger, weil sie andere Zeiten auflösen muss: Schall legt etwa 300 Meter pro

Sekunde zurück, Licht hingegen 300.000 Kilometer pro Sekunde. Will man einen

Gegenstand zum Beispiel in 1,5 Meter Entfernung messen, läuft der Lichtstrahl 1,5 m

hin, dann 1,5 m zurück und löst dann im Photodetektor ein Ereignis aus. Der

Lichtstrahl ist also 3 m insgesamt gelaufen. Die Zeit dafür berechnet sich für 1,5m

Objektdistanz, bzw. 3m Lichtlauflänge:

𝑡𝐿𝑖𝑐ℎ𝑡 = 3𝑚

300.000𝑘𝑚

𝑠

=3𝑚

300.000.000𝑚

𝑠

= 1

100.000.000𝑠 = 10 𝑛𝑠 (𝑀𝑖𝑙𝑙𝑖𝑎𝑟𝑑𝑠𝑡𝑒𝑙 𝑆𝑒𝑘𝑢𝑛𝑑𝑒𝑛)

Wie in Abbildung 34 zu sehen ist, besitzt der Sensor einen Öffnungswinkel von 25°.

Bei einer Entfernung von 1 m entspricht das einer Breite von 43 cm.

Es handelt sich bei diesem Sensor um einen Klasse-1-Laser, weshalb man vorsichtig sein sollte:

Da der Laser im Infrarotbereich strahlt, kann man dessen Laserlicht nicht sehen. Aber: wie in Abbildung 34

zu sehen ist, besitzt der Laserstrahl eine Aufweitung von 35°, weshalb eine Gefährdung für die Augen nur

in unmittelbarer Nähe zur Emitteröffnung gegeben ist.

Also: Mindestabstand vom Sensor 30cm.

Der VL53L0X besitzt eine maximale Reichweite von 2m unter Optimalbedingungen (weisse Fläche), 80cm

bei grauen Flächen; damit sollte er für ein Robotik-Wettkampffeld ausreichen.

Abbildung 34: VL53L0X TOF Sensor

Abbildung 35: Definition Laserklasse 1 Die zugängliche Laserstrahlung ist unter venünftigerweise vorhersehbaren Bedingungen ungefährlich.

Page 26: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

26

//Analogsteuerung *******************************

#include <Wire.h>

#include <VL53L0X.h>

VL53L0X sensor;

int A0Wert = 0;

int A0Alt = 0;

void setup()

Serial.begin(115200);

Wire.begin();

sensor.init();

sensor.setTimeout(500);

sensor.setMeasurementTimingBudget(200000);

sensor.startContinuous();

pinMode(A0, INPUT);

void loop()

A0Wert = analogRead(A0);

if ((A0Wert == 0) && (A0Wert !=A0Alt))

long zeitStart = micros();

int distanz = sensor.readRangeContinuousMillimeters();

long zeitDifferenz = micros() - zeitStart;

Serial.print("Distanz: "); Serial.println(distanz);

Serial.print("Zeit: "); Serial.println(zeitDifferenz);

A0Alt = A0Wert;

//Interruptsteuerung *******************************

#include <Wire.h>

#include <VL53L0X.h>

VL53L0X sensor;

bool neueMessung = false;

void setup()

Serial.begin(115200);

Wire.begin();

sensor.init();

sensor.setTimeout(500);

sensor.setMeasurementTimingBudget(200000);

sensor.startContinuous();

attachInterrupt(digitalPinToInterrupt(2), Fertig, FALLING);

void loop()

if (neueMessung)

int distanz = sensor.readRangeContinuousMillimeters();

Serial.print("Distanz: "); Serial.println(distanz);

neueMessung = false;

void Fertig()

neueMessung = true;

Page 27: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

27

Funktionsüberprüfung Um zu überprüfen, ob der Sensor funktioniert und Licht abstrahlt, kann man seine Smartphonekamera über den laufenden Sensor

halten. Der CCD-Chip in der Smartphonekamera ist dazu in der Lage, Infrarotstrahlung zu detektieren und darzustellen.

Verwendete Bibliotheken Es existieren zwei Bibliotheken, einmal von Adafruit und einmal von Pololu. Die Pololu-Bibliothek benötigt weniger Speicherplatz

und lässt sich besser konfigurieren. Allerdings ist sie ein wenig komplexer in der Anwendung. Wir nutzen hier die Pololu-

Bibliothek. Man findet sie hier: https://github.com/pololu/vl53l0x-arduino

Die Datei vl53l0x-arduino-master.zip wird, wie bereits unter WS2812B-Neopixels beschrieben, in die Arduino-Umgebung

importiert.

Interrupt-Modus des VL53L0X Problematisch sind die Betriebsmodi des VL53L0X: Nutzt man in den Standardbeispielen z.B. den SingleMode, so benötigt der Sensor mindestens 23ms für eine Messung,

und der Arduino „steht still und wartet“. Das ist indiskutabel! Der zweite, sinnvollere Modus nutzt einen Interrupt: Der Sensor tätigt seine Messung permanent, er läuft

damit im sogenannten „Continous Mode“. Ist eine neue Messung fertig, wird ein Interrupt am GPIO-Pin gesetzt. Dann kann normalerweise per Interrupthandler die

Messung abgerufen werden. Die Messzeit am Arduino benötigt hier anstelle von 23ms nur noch 1,3ms und findet etwa alle 30 ms statt.

Bei der Interruptsteuerung gibt es aber ein weiteres Problem: Der GPIO-Pin erzeugt maximal 2,8Volt – und das ist für einen Arduino-Uno-Interrupt eventuell zu wenig.

Der Interrupt wird vom Arduino womöglich nicht zuverlässig ausgelesen – das muss am jeweiligen Arduinoboard ausprobiert werden.

Als Alternative wird hier das Signal via A0-Analogpin ausgelesen: Ändert sich der Zustand des A0-Pins auf den Wert „0“ (Simulation fallende Signalflanke), so ist der Sensor

auslesbar. Zum Schutz werden 470 Ω eingebaut, welche die Stromstärke des Sensors limitieren.

Technisch sauber wäre ein Level-Shifting: Eine Übersetzung der 2,8V-Logik auf die 5V-Logik des Arduinos, was z.B. per BSS138-Chip geschehen könnte.

Erläuterung der Sensorbefehle im Quelltext:

a) sensor.setTimeout() maximale Zeit, die der Arduino auf Sensordaten wartet.

b) sensor.setMeasurementTimingBudget() Angabe in Mikrosekunden. Die Zeit, welche der Sensor zur Generierung von Messdaten erhält. Je höher der

Wert, desto genauer die Messung. Hiermit kann auch indirekt gesteuert werden, wie oft der Interrupt ausgelöst wird.

c) sensor.readRangeContinuousMillimeters() Erzeugt die Messwertausgabe.

Abbildung 36: Handyfotot laufender Sensor

Page 28: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

28

„Blink“-Sketch neu: Timersteuerung In den bisherigen Sketch-Skripten wurde immer die delay()-Funktion verwendet. Für Mikrocontroller-Programmierung ist das aber von erheblichem Nachteil und sollte

vermieden werden. Der Grund ist, dass während eines delay-Warteschleife der Prozessor nichts anderes machen kann und man so wertvolle Zeit verschenkt. Zeit, in der

man Messungen, Motoransteuerungen und Berechnungen durchführen sollte.

Um diese Nachteile zu verhindern, unterteilt man das Programm in einzelne Aufgaben, die in bestimmten Zeitintervallen abgearbeitet werden. In einem ersten Schritt kann

man dazu das unten abgebildete Skript nutzen. Hier laufen zwei Prozesse – nämlich das LED-Blinken und die Serielle Kommunikation – zeitlich voneinander entkoppelt in

unterschiedlichen Zeitintervallen.

Skript-Variante 1: Timer-Prinzip unsigned long zeitVorbei_LED;

unsigned long zeitVorbei_Serial;

unsigned long zeitJetzt;

void setup()

pinMode(13, OUTPUT);

digitalWrite(13, LOW);

zeitVorbei_LED = millis();

zeitVorbei_Serial = millis();

Serial.begin(9600);

void loop()

zeitJetzt = millis();

if (zeitJetzt - zeitVorbei_LED > 500)

zeitVorbei_LED = zeitJetzt;

digitalWrite(13, !digitalRead(13));

if (zeitJetzt - zeitVorbei_Serial > 333)

zeitVorbei_Serial = zeitJetzt;

Serial.println(zeitJetzt);

Skript-Variante 2: Zeitmessung eines Loops unsigned long zeitVorbei_LED;

unsigned long zeitVorbei_Serial;

unsigned long zeitJetzt;

unsigned long LOOPDURCHLAEUFE = 0;

void setup()

pinMode(13, OUTPUT);

digitalWrite(13, LOW);

zeitVorbei_LED = millis();

zeitVorbei_Serial = millis();

Serial.begin(9600);

void loop()

zeitJetzt = millis();

if (zeitJetzt - zeitVorbei_LED > 500)

zeitVorbei_LED = zeitJetzt;

digitalWrite(13, !digitalRead(13));

if (zeitJetzt - zeitVorbei_Serial >= 1000)

zeitVorbei_Serial = zeitJetzt;

Serial.print(LOOPDURCHLAEUFE);

Serial.println(" Loopdurchlaeufe pro Sek.");

LOOPDURCHLAEUFE = 0;

LOOPDURCHLAEUFE++;

In Skriptvariante 2 wird gemessen, wie häufig die

loop-Funktion pro Sekunde durchlaufen wird. Im

Seriellen Monitor wird bei einem Standard-UNO

bei diesem Skript ein Wert von ca. 150.000

Durchläufen pro Sekunde angezeigt. Das

entspricht ca. 6,7 Mikrosekunden (Millionstel

Sekunden) für einen Loop-Durchgang.

Da sich in der Loop-Funktion etwa 5 Anweisungen

befinden (die Anweisungen innerhalb der if-Ver-

zweigung werden so gut wie nie aufgerufen und

spielen daher keine Rolle), kann man abschätzen,

dass eine Anweisung in ca. 1 Mikrosekunde

abgearbeitet wird (grob vereinfacht).

Programmiert man also ein delay() von z.B.

5 Millisekunden irgendwo ein, so verliert man bis

zu 5000 Berechnungsmöglichkeiten!

Page 29: Arduino Tutorials Robotik-AG JKG - iludis.deiludis.de/wp-content/uploads/2018/03/RobotikAG_ArduinoTutorial.pdf · 4 Erläuterung: Der Arduino Uno besitzt insgesamt (von links oben

Arduino CheatSheet Robotik-AG

Aufbau Quelltext

void setup() // einmalige Anweisungen void loop()

// permanent wiederholte Anw.

Kontrollstrukturen

if (x == 1)

//Anweisungen

else

//andere Anweisungen

switch (x)

case 1: //Anweisungen1

break;

case 2: //Anweisungen2

break;

default://Anweisungen

for(int i=0;i<255;i++)

//Anweisungen

while(x==true)

//Anweisungen

Funktionsdefinition (Beispiel)

int Quadrat(int x)return x*x;

Rückgabewert FunktName(Parameter)

Anweisungen;

return-Anweisung;

Zeitmessung

unsigned long millis()//50Tage

unsigned long micros()//70Min.

delay(x)//x in Millisekunden

delayMicroseconds(x)//Mikro-s.

Präprozessor-Anweisungen

#define //Compiler-Direktive

#include “file“//externe Bib.

#include <file.h>//interne Bib

Datentypen

boolean//1bit: 0/1, false/true

char //8bit -127..128

unsigned char //8bit 0..255

byte // 8bit 0..255

int //16bit -32767..32768

unsigned int //16bit 0..65535

long //32bit ±2147483647

unsigned long //0..4294967295

float //32bit Kommazahl

(double //64bit, nur bei DUE)

void//KEIN (Rückgabe)-Wert

Mathematische Operatoren

+ // Addition

- // Subtraction

* // Multiplikation

/ // Division

% // Modulus

= // Zuweisung

Logische Operatoren

== // bool "gleich"

!= // ungleich

< // kleiner als

> // größer als

<= // kleiner gleich

>= // größer gleich

&& // bool UND

|| // bool ODER

! // bool NICHT

Bitweise Operatoren

& //Bitweise UND

| //Bitweise ODER

^ //Bitweise Exklusiv ODER

~ //Bitweises invertieren

x<<n //Bitshift n bit links

x>>n //Bitshift n bit rechts

Zufallszahlen

random(maxV)//Zufallszahl bis

random(minV,maxV)//Z.Z von/bis

randomSeed(x)//Initialisierung

Qualifier

static x //lokale Variable

//wird nicht gelöscht

volatile x//Interrupt-Variable

const x //Read Only-Variable

Mathematik

min(x,y)//gibt kleinere Zahl

max(x,y)//gibt größere Zahl

abs(x) //Entfernt Vorzeichen

constrain(x,minV,maxV)

//Beschränkt Wertebereich

map(x,vonL,vonH,bisL,bisH)

//Überträgt Wertebereich

pow(basis,exponent)

// "Basis hoch Exponent"

sqrt(x) // Wurzel x

sin(x) cos(x) tan(x)//Trig.

atan(x) //Arkustangens x

atan2(x,y)//Arkustangens x/y

log10(x) //Dekadischer Log x

x++ //Inkrementieren „plus 1“

x-- //Dekrementieren „minus 1“

PIN Input/Output

pinMode(pin,INPUT)//Eingang

pinMode(pin,OUTPUT)//Ausgang

pinMode(pin, INPUT_PULLUP)

//Eingang auf HIGH mit 10kOhm

digitalRead(Pin)//High od Low

digitalWrite(Pin, HIGH)//5V

digitalWrite(Pin, LOW)//0V

analogRead(Pin)//liest 0..1023

analogWrite(Pin,x)//0..255 PWM

Frequenzoutput an PWM-Pin

tone(Pin,freq)//PWM-Frequenz

//mit 50%Duty-Cycle,

//min 31Hz, max 65535Hz

tone(Pin, freq, dauer)//in ms

stop()//Stoppt Ton

noTone(Pin)//stoppt Ton an Pin

Arrays

int myVar[6]//Deklaration

int myVar[]=2,3,7,5

char text[5]= "Hallo"

char text[3]='H', 'a', 'l'

text.length//Anzahl Elemente

Zahlendarstellungen

x = 100; //Dezimal

x = 0144; //Oktal

x = 0b01100100 //Binär

x = 0x64 //Hexadezimal

Serielle Kommunikation

Serial.begin(9600)//bytes/s:

300,1200,2400,4800,9600,14400,

19200,28800,38400,57600,115200

Serial.end()

Serial.available()//test ob >0

char x = Serial.read()

Serial.write(x)//schreibe Byte

Serial.print(x)//Bytesequenz

Serial.println(x)//mit Newline

Serial.flush()//warte bis fertig

#include <SoftwareSerial.h>

SoftwareSerial xy(2,3)//Rx, Tx

xy.print/ xy.read / xyz.end …

Typecasting

float f=3.6; f = (int) f; //3

float g=3.6; g = (char) g; //3

int x= 256; x = (char) x;//255

int y= 3; y = (float) y; //3.0

Interrupts

attachInterrupt(IR,ISR,Modus)

//IR-Pin UNO: 2 od. 3,

//ISR: Interrupt Service Routine,

//Modus: Trigger, wenn Signal:

//LOW CHANGE RISING FALLING

detachInterrupt(IR)//entfernen

interrupts()//Interrupts an

noInterrupts()//Interrupts aus

PIN-Funktionen

Serial Pins: 0-Tx 1-Rx

PWM Pin: 5,6 Timer 0;

9,10 Timer 1;

3,11 Timer 2;

SPI: 10-SS, 11-MOSI,

12-MISO, 13-SCK

I2C: A4-SDA, A5-SCK

Interrupt: 2,3

dauer = pulseIn(pin, HIGH)

//wartet, bis Pin auf HIGH,

startet Zeitmessung, wartet auf

LOW und stoppt Messung. Liefert

die Pulslänge in Microsekunden.

FUNKTIONERT AUCH MIT LOW.