====== Datentypen, Scope, Arrays ===== ==== Wichtigste Datentypen ==== Vollständige Übersicht, siehe "Data Types" auf https://www.arduino.cc/en/Reference/HomePage === int === 16 Bit (2 Bytes), vorzeichenbehaftet, Zahlen von $-2^{15}$ bis $2^{15}-1$ (ca. -32'000 bis 32'000). === long === Wie int, aber 32 Bits (4 Bytes) -2 Milliarden bis +2 Milliarden. === float === 32 bits (4 Bytes) Dezimalzahlen, Genauigkeit 6-7 Stellen. === char === 8 bits (1 Byte): 1 Buchstabe (bzw. Zahl von -128 bis 127). === char * (C-Strings) === Zeichenkette (nullterminiert). char *b = "Ein String"; Serial.println(b); === String === Zeichenkette "mit Klasse" ;-) Insbesondere das Zusammenhängen von Strings und anderen Variablen funktioniert (wie in Java). int v = 42; String a = "Wert ="; Serial.println(a+v); // Gibt 'Wert =42' aus. // Erstes Element muss vom Typ String sein. Serial.println(String("Das Quadrat von ")+v+" ist "+(v*v)); ==== Scope (Gültigkeitsbereich, Lebensdauer einer Variablen) ==== Vor oder bei der ersten Zuweisung muss eine Variable mit Typ deklariert werden. Die Variable existiert nur im Block (was zwischen { und } steht), wo diese deklariert wurde. Wird eine Variable ausserhalb eines Blocks deklariert, ist diese global. Darauf kann in Code, der **nach** der Deklaration steht, überall zugegriffen werden. // Variable vom Typ int, direkt initialisiert. int status=42; // Funktion, die einen int zurückliefert. int quadrat() { return status*status; // Zugriff auf globale Variable, Resultat der Funktion quadrat(); } // Unterprogramm (Funktion, die nichts zurückliefert). void machwas() { int x = status*2-1; if (status == 2) { int y=0; // Achtung! y existiert nur zwischen den innersten '{' und '}'. } else { int y=12; // Dito } int z = x+y; // FEHLER, y existiert hier nicht mehr! } ==== Arrays ==== Ein Array ist eine Aneinanderreihung von Werten **gleichen Typs**. Das **erste** Element hat den **Index 0**. Das letzte von $n$ Elementen hat den Index $n-1$. Die Anzahl Elemente muss bei der Initialisierung bekannt sein. (Dynamische Arrays sind aber auch möglich). int a[4]; // Platz für 4 int-Werte (a[0], a[1], a[2] und a[3]). a[2] = 42; a[1] = 3; a[0] = -4; int b[a[1]]; // Platz für 3 int-Werte int c[] = {3,6,123,1555}; // Initialisierung mit 4 Elementen. Die Angabe der Anzahl kann entfallen. Serial.println(c[2]); // Gibt 123 aus. === Pointer === Ein Pointer ist ein Verweis auf eine Speicheradresse (Ort im RAM) kombiniert mit einer Typeninformation. Eine Array-Variable ist nichts anderes, als ein Pointer auf das erste Element des Arrays. Darum ist der Index des ersten Elements 0 (nämlich die Anzahl Positionen, die zur Startadresse hinzugezählt werden müssen). void meineArrayFunktion(int *a) { // Unterprogramm mit Pointer auf int als Argument for (int i=0; i<5; i++) { a[i] = 42; // Direkte Manipulation des Inhalts des übergebenen Arrays. } } int c[5]={5,4,76,3,12}; Serial.println(c[4]); // Gibt 12 aus meineArrayFunktion(c); Serial.println(c[4]); // Gibt 42 aus ===== LEDs und Taster ===== ==== LEDs ==== Eine Diode lässt Strom nur in eine Richtung passieren (bei vernünftigen Spannungen). Man kann sich eine Diode als Schleusentor vorstellen. In der Gegenrichtung passiert kein Wasser. In der Flussrichtung braucht es einen gewissen Druck (Spannung), damit sich das Tor öffnet. Einmal geöffnet, fliesst viel Wasser (Strom). Dieser Strom muss limitiert werden, typischerweise mit einem Vorwiderstand. **LEDs immer mit Vorwiderstand anschliessen**. (oder "Nachwiderstand", spielt keine Rolle). Typischerweise 220 $\Omega$. * Langes Bein: Anode, Plus Pol, //Do chunnt d'Spannig **ane**// * Kurzes Bein (und Abschliff auf dem Diodenring): Kathode, Minus Pol === LED auf Port 2 blinken lassen === Passen das Blink-Beispiel entsprechend an. === LED auf Port 2 dimmen === Eine LED kann gedimmt werden, indem man diese ganz schnell ein- und ausschaltet. Je nach Anteil der Zeit, während der die LED angeschaltet ist, erscheint diese heller oder dunkler. Schreiben Sie ein Programm, das die LED schön "an- und ausdimmt". Beachten Sie, dass unser Helligkeitsempfinden nicht linear ist. Eine gute Variante besteht darin, den Anteil der "An-Zeit" quadratisch ansteigen zu lassen. Für eine feinere Auflösung kann auch eine Anzahl Mikrosekunden gewartet werden: delay(100); // 100 ms warten delayMicroseconds(200); // 200 us = 0.2 ms warten === LED mit analogWrite dimmen === Dazu muss die LED auf einen der Ports 3,5,6, 9,10,11 angeschlossen werden. Lesen Sie dazu die Arduino-Dokumentation: https://www.arduino.cc/en/Reference/AnalogWrite === Knight Rider simple === 1 Widerstand hinter allen LEDs auf GND reicht dafür. Lassen Sie die LED hin- und her blinken. Verwenden Sie für die Pin-Nummern ein Array und arbeiten Sie mit for-loops! === Knight Rider classy === Lassen Sie LED sanft ein- und ausschlaten (dimmen). ==== Taster ==== 2 Varianten: Externer Pulldown-Widerstand (hier auf Port 2) oder interner Pullup-Widerstand (hier auf Port 3): {{ :lehrkraefte:blc:informatik:ffprg2017:l3:taster-pulldown.png |}} === Externer Pulldown-Widerstand === Das offene Ende des Tasters muss mit einem Widerstand auf eine definierte Spannung gezogen werden. Schliesst man einfach einen losen Draht an einen Eingang an, fungiert dieser als Antenne und die gemessene Spannung fluktuiert zufällig. Es kann zu jedem Zeitpunkt sowohl LOW wie auch HIGH gemessen werden. Die obige Schaltung realisiert dies mit einem **Pulldown Widerstand**. Der Arduino Eingang ist also LOW, wenn der Taster nicht gedrückt ist, und HIGH sonst. === Interner Pullup-Widerstand === Der Arduino kann interne Pullup-Widerstände aktivieren. Erreicht wird dies durch schreiben eines HIGH auf INPUT-Eingänge oder durch pinMode(pinNummer, INPUT_PULLUP); // oder pinMode(pinNummer, INPUT); digitalWrite(pinNummer, HIGH); Durch Schreiben eines LOW kann der Pullup-Widerstand wieder ausgeschaltet werden. Der Taster wird jetzt auf GND verbunden (nicht mehr auf 5V). Der Vorteil dieser Schaltung ist, dass kein zusätzlicher Widerstand nötig ist. Der "Nachteil" ist, dass jetzt HIGH und LOW vertauscht sind (LOW heisst jetzt gedrückt).