lehrkraefte:blc:informatik:ffprg2-2018:ffprg2-2018

This is an old revision of the document!


https://fginfo.ksbg.ch

Freifach Programmieren

In diesem Kurs werden die Grundlagen von C++ vermittelt, mit Fokus auf die Anwendung mit der Arduino-IDE. Damit werden dann Elektronik-Experimente mit Arduino und/oder ESP32 programmiert.

Ziel ist es, bis vor den Herbstferien so weit mit C++ vertraut zu sein, damit erste Elektronik-Experimente angegangen werden können.

Sammlung von Tutorials und Dokumentation:

Potentiometer auslesen

Ein Potentiometer hat normalerweise 3 Anschlüsse. Der Widerstand zwischen 1. und 3. Anschluss ist konstant (z.B. 10k$\Omega$). Der Widerstand zwischen 1. und 2. Anschluss kann stufenlos geregelt werden, zwischen 0 und dem Gesamtwiderstand.

Typischerweise wird zwischen 1. und 3. Anschluss 5V angelegt und die Spannung am 2. Anschluss gemessen. Diese variiert dann stufenlos zwischen 0V und 5V, vorausgesetzt, es kann (praktisch) kein Strom über Anschluss 2 abfliessen.

Der 2. Anschluss wird am Arduino an einen der “Analog-Ports” angeschlossen, A0 bis A5. Die Spannung kann mit 10 Bit Auflösung ausgelesen werden mit

  int wert = analogRead(A0);

Man erhält einen Wert zwischen 0 (0V) und 1023 (5V).

Hardware PWM

Der Arduino kann Hardware ein PWM-Signal erzeugen, und zwar auf den Pins 3, 5, 6, 9, 10, 11.

Mit einer Auflösung von 8 Bit kann das Signal wie folgt gesteuert werden:

  // im setup():
  pinMode(3, OUTPUT);
 
  // sonst wo:
  analogWrite(3, 127); // Halbe Kraft voraus... 0 heisst augeschaltet, 255 eingeschaltet

Mögliche Aufgaben

  • Steuerung der Helligkeit einer LED
  • Steuerung der Motorengeschwindigkeit.

Debugging. Im Setup

Serial.begin(115200)

Im Code:

Serial.print(i);
Serial.print(" ist ");
Serial.println(j);

Die Ausgabe unter Tools → Serial Monitor (Ctrl-Shift-M) anschauen.

LEDs dimmen mit PWD (Pulsweitenmodulation).

Idee. Ganz schnell ein- und ausschalten. Zeit, während der die LED eingeschaltet ist variieren.

Installation der Arduino-IDE:

  • https://www.arduino.cc/en/Main/Software (Windows-Installer auf den eigenen Geräten, zip-Datei auf den Schulcomputern)
  • Auf den Schulcomputern einen Ordner auf C:\ anlegen und die IDE darin entpacken.
int ports[] = {12,11,10};
int num = sizeof(ports)/sizeof(int);  // Anzahl Elemente
 
void setup() {
  // put your setup code here, to run once:
  for (int i=0; i<num; i++) {
    pinMode(ports[i], OUTPUT);
  }
}
 
void loop() {
  // put your main code here, to run repeatedly:
  for (int i=0; i<num; i++) {
    digitalWrite(ports[i], HIGH);
    delay(100);  // 100ms warten
    digitalWrite(ports[i], LOW);
  }
  delay(500);
}
  // Nur für kleine Arrays!
  int zahlen[10];  // Variablenname ist Plural!
  zahlen[0]=2;     // Erstes Element Index 0
  zahlen[9]=42;    // Letztes Element hat Index Länge -1
 
  //  Für grosse Arrays:
  int grenze = 10000000;            // Bis **ohne** diese Grenze!
  bool* prim = new bool[grenze];    // kein new ohne delete!
 
  delete[] prim;    // Speicher wieder freigeben  

Lösungsvorschlag

Lösungsvorschlag

#include <iostream>
 
using namespace std;
 
int main()
{
    int grenze = 100000000;
    bool *prim = new bool[grenze];
    cout << "Alloc finished" << endl;
    // Initialisierung
    for (int i=0; i<grenze; i++) {
        prim[i] = i>1;
    }
    cout << "Init done " << endl;
    int akt = 0;   // Zahl zum Abstreichen
    while (akt*akt<=grenze) {  // Abstreichen bis zur Wurzel
        while (!prim[++akt]);   // Nächste Primzahl ermitteln, ! heisst "nicht"
        for (int p=akt*akt; p<grenze; p+=akt) {   // Zahlen abstreichen
            prim[p] = false;
        }
    }
    // Ausgabe der Liste
    for (int i=0; i<grenze; i++) {
        if (prim[i]) {
            cout << i << endl;
        }
    }
    // Speicher wieder freigeben
    delete[] prim;
    return 0;
}

Das Ergebnis eines Vergleichs (z.B. mit ==, !=, <, >, etc. ist ein Wahrheitswert true oder false. Diese Werte können in einer Variable mit Typ bool gespeichert werden.

bool gleich;
gleich = (42==6*7);
if (gleich) {   // Gleicher effekt wie gleich==true
   cout << "gleich ist wahr: " << gleich << endl;
} else {
   cout << "gleich ist falsch: " << gleich << endl;
}

Hinweis: Werden andere Typen als bool interpretiert, ist alles wahr, was nicht Null ist. Wird ein bool als Zahl interpretiert, kommt 0 (für false) oder 1 (für true) heraus.

Schreiben Sie ein Programm, das alle Primzahlen bis zu einer gegebenen Grenze ausgibt.

Lösungsvorschläge

Lösungsvorschläge

#include <iostream>
#include "math.h"
 
using namespace std;
 
int main()
{
    int grenze = 10000000;
    int anzahl = 1;
    int maxprimes = 1000;
    int primes[1000];
    primes[1] = 3;
 
    for (int k=3; k<=grenze; k+=2) {
        bool hatTeiler = false;
        for (int t=1; primes[t]*primes[t]<=k; t++) {
            if (k%primes[t]==0) {
                hatTeiler = true;
            }
        }
        if (hatTeiler==false) {
            cout << k << endl;
            if (anzahl<maxprimes) primes[anzahl]=k;
            anzahl++;
        }
    }
    cout << anzahl << " Primzahlen bis " << grenze << endl;
 
    return 0;
}

Ein bool könnte mit einem einzigen Bit dargestellt werden. Tatsächlich werden aber meistens 1 Byte (8 Bits) Speicher dafür reserviert. In einem ersten Schritt wird ein Array von bool reserviert:

int n = 10000;  // Obere Grenze
bool prim[n];   // prim (true/false)
// Initialisierung
for (int i=0; i<n; i++) {
  prim[i]=true;
}
// Spezialfälle
prim[0] = false;
prim[1] = false;
 
int wegmit=2;  // Erste Primzahl zum rausstreichen
while (wegmit*wegmin<n) {    // Bis zur Wurzel von n
   // TODO: Alle Vielfachen von wegmit wegstreichen
   // TODO: Nächste Primzahl im Array bestimmen.
}
   for(INITIALISIERUNG;  BEDINGUNG VOR DER SCHLAUFE;   AKTION NACH DER SCHLAUFE) {
       // Dinge, die wiederholt werden
   }

Typischerweise sieht eine For-Schleife so aus:

  for (int i=0; i<100; i++) {
     // Tu was mit i
  }
  // ACHTUNG: i existiert hier nur in der Schleife und nicht ausserhalb!

Spezialfälle

   for(;;) {
      // Endlosschleife
   }
 
   // Das sollte man nie so schreiben, sondern wie?
   for (int i=0, j=0; i<10; i+=(j==9?1:0), j=(j+1)%10) {
      cout << i << ", " << j << endl;
   }
   // Besser:
   for (int i=0; i<10; i++) {
      for (int j=0; j<10; j++) {
        cout << i << ", " << j << endl;
      }
   }
 

Was macht das folgende Programm?

#include <iostream>
 
using namespace std;
 
int main()
{
    for (int i=0; i<32; i++) {
        if (i % 3 == 0) {
            cout << "Dreierzahl" << endl;
        } else {
            cout << i << endl;
        }
    }
    return 0;
}

Schreiben Sie ein Programm, das die Zahlen von 0 bis und mit 31 ausgibt. Anstelle jeder Zahl, die durch 3 teilbar ist, soll “Fizz” ausgegeben werden, anstelle jeder Zahl, die durch 5 teilbar ist, soll “Buzz” ausgegeben werden. Ist die Zahl sowohl durch 3 als auch durch 5 teilbar, soll “FizzBuzz” ausgegeben werden.

Lösungsvorschläge

Lösungsvorschläge

Mark

#include <iostream>
 
using namespace std;
 
int main()
{
    for (int i=0; i<32; i++) {
        if (i % 15 == 0) {
            cout << "FizzBuzz" << endl;
        } else if (i % 5 == 0) {
            cout << "Buzz" << endl;
        } else if (i % 3 == 0) {
            cout << "Fizz" << endl;
        } else {
            cout << i << endl;
        }
 
    }
    return 0;
 
}

Lukasz

#include <iostream>
 
using namespace std;
 
int main()
{
for (int i=1; i<32; i++) {
    if (i%3==0 && i%5==0) {
        cout << "FizzBuzz" << endl;
    }
    else if (i%5==0) {
        cout << "Buzz" << endl;
    }
    else if (i%3==0) {
        cout << "Fizz" << endl;
    }
    else if (i==i) {
        cout << i << endl;
    }
    }
    return 0;
}

Noah

#include <iostream>
 
using namespace std;
 
int main()
{
    for (int i=1; i<32; i++) {
        if (i % 3 == 0 && i % 5 == 0) {
            cout << "FizzBuzz" << endl;
        }
        else if (i % 5 == 0) {
            cout << "Buzz" << endl;
        }
        else if (i % 3 == 0) {
            cout << "Fizz" << endl;
        }
 
        else {
            cout << i << endl;
        }
    }
    return 0;
}

Blc: (so nicht zu empfehlen):

#include <iostream>
 
using namespace std;
 
int main()
{
    for (int i=0; i<32; i++) {
        cout << (i%3==0?"Fizz":"") << (i%5==0?"Buzz":"") << ((i%3)*(i%5)?to_string(i):"") << endl;
    }
 
   return 0;
}

}

if, for, while, break

Verifizieren Sie die ersten 8 Einträge der Tabelle auf https://primes.utm.edu/howmany.html

  • lehrkraefte/blc/informatik/ffprg2-2018/ffprg2-2018.1544799197.txt.gz
  • Last modified: 2018/12/14 15:53
  • by Ivo Blöchliger