Taschenrechner selbst gebaut
Individuelle Mathematik mit dem Arduino
Programmierbare Taschenrechner gibt es in großer Menge. Doch geht deren Programmierbarkeit nicht unbedingt mit hoher Flexibilität einher. Für das Berechnen ganz spezieller Aufgaben sind nicht selten umständliche Schritte erforderlich, was ihre Handhabung erschwert. Hier bietet sich der Arduino als Alternative an.
Kleincomputer, wie der Arduino, werden in der Regel aus externen Quellen mit Daten versorgt. Dies kann etwa über Sensoren, Uhrenbausteine oder das Keypad geschehen. Auf diese Weise genügt es, lediglich ein Mal den Arduino mit einem Sketch zu versorgen, was dieser danach selbstständig unter Einbeziehung der extern einfließenden Daten abarbeitet. Da das Programm nach Unterbrechung der Stromversorgung nicht verlorengeht, steht der Arduino nach erneutem Anlegen einer Stromspannung abermals für die vorgesehene Aufgabe zur Verfügung.
Eine solche Aufgabe kann zum Beispiel die Funktion eines Taschenrechners sein, der sich ganz spezieller Berechnungen annimmt. Dazu ist es lediglich nötig, jeden Tastendruck eines Keypads entsprechend zu verarbeiten. Es gilt, Zahlen zu erfassen, diese in einer Variablen zu speichern und nach Betätigen einer Enter-Taste eine Berechnung ausführen zu lassen.
Die Herausforderung für dieses Vorhaben ist, die per Keypad eingegeben Zahlenwerte korrekt zu erfassen, damit am Ende eine Gesamtzahl vorliegt, die für die gewünschten Berechnungen herangezogen werden kann.
Üblicherweise wird eine Abfrage des Keypads über die Funktion ›keypad.getKey()‹ vorgenommen. Diese Funktion wird von der Bibliothek ›Keypad.h‹ bereitgestellt und übergibt an eine Variable des Typs ›char‹ eine Zahl, die, wenn sie über die Funktion ›Serial.println(key)‹ auf dem Monitor ausgegeben wird, als Tastennummer – beispielsweise 6 – ausgegeben wird.
Wird hingegen einer Integervariablen mit dem Namen ›ASCII‹ der Inhalt der Variablen ›key‹ übergeben, so zeigt sich, dass danach in der Variablen ASCII der Ascii-Wert der entsprechenden Zahl steckt. Dieser Sachverhalt ist bemerkenswert und unbedingt zu beachten, führt er doch bei Unkenntnis zu längerer Fehlersuche im eigenen Programm, das unter Umständen nicht wie geplant funktioniert, da der Fehler sich geschickt versteckt.
Folgender auszugsweiser Sketch macht den Zusammenhang deutlich:
void loop()
{
//Lesen, ob eine Taste gedrückt wurde
char key = keypad.getKey();
if (key != NO_KEY) // Wenn Taste am Keypad gedrückt, dann weiter
{
ASCII = key;
Serial.print("Taste = ");
Serial.println(key);
Serial.print("Ascii-Code = ");
Serial.println(ASCII);
}
}
Auf dem Monitor ergibt sich folgendes Bild:
Es ist demnach beim Umgang mit dem Keypad nötig, die Ascii-Tabelle für die dort aufgeführten Zahlenwerte und Symbole zu kennen, um einen korrekten Programmcode erstellen zu können, der in der Lage ist, Eingaben per Keypad korrekt abzuarbeiten. Untenstehendes Bild listet den Ascii-Code für die Tasten des Keypads auf.
Um nun den Arduino als einfachen Taschenrechner nutzen zu können, ist es nötig, die Zahlenwerte der gedrückten Tasten 0 bis 9 als String zu behandeln und in der Reihenfolge der Tastendrücke aneinanderzureihen. Dazu bietet es sich an, die Variable ›zahlenwurm‹ als String zu definieren und anschließend sofort zu leeren. Der Befehl dazu lautet:
String zahlenwurm ="";
Interaktion
Ein Bediener möchte natürlich wissen, in welchem Status sich der Arduino befindet. Demnach macht es Sinn, den Cursor der LCD-Anzeige zu Beginn auf die Position 0,0 zu setzen und dort den Text ›Bereit‹ auszugeben.
Die dazu nötigen Befehle lauten:
lcd.setCursor(0, 0);
lcd.print("Bereit!");
Um anschließend die Zahlen zu einer Zeichenkette aneinanderreihen zu können, muss dafür gesorgt werden, dass jeder Tastendruck entsprechend ausgewertet und verkettet wird. Die eigentliche Erfassung eines Tastendrucks geschieht über den Befehl ›char key = keypad.getKey();‹
In der Variablen ›key‹ wird jeder Tastendruck gespeichert, was bedeutet, dass die dort stehende Zahl genutzt werden kann, um etwa per if-Befehl eine Aktion auf diesen Tastendruck auszulösen. Auf diese Weise kann die Variable ›zahlenwurm‹ mit Inhalt gefüllt werden.
if (key == '1')
{
zahlenwurm = zahlenwurm + ("1");
}
if (key == '2')
{
zahlenwurm = zahlenwurm + ("2");
}
:
:
Um eine saubere Anzeige des eingegebenen Zahlenwerts zu bekommen, muss selbstverständlich die LCD-Anzeige bei der per Keypad getätigten Eingabe der ersten Zahl zunächst gelöscht werden. Dies geschieht mit dem Befehl ›lcd.clear();‹
Wiederholtes Betätigen einer Zahlentaste des Keypads führt zur Darstellung des eingegebenen Zahlenwerts.
Der Dezimalpunkt wird über die *-Taste erzeugt. Der Befehl dazu ist in der if-Abfrage eingearbeitet und lautet:
if (key == '*')
{
zahlenwurm = zahlenwurm + (".");
}
Ist die gewünschte Zahl komplett eingegeben, so wird per Druck auf die #-Taste die in der Variablen ›zahlenwurm‹ stehende Zahl zunächst in eine Integervariable mit dem Namen ›zahl‹ überführt. Der dazu nötige Befehl lautet: ›zahl = zahlenwurm.toFloat();‹
Anschließend kann die Wurzel dieser Zahl mit dem Befehl ›sqrt(zahl)‹ berechnet werden. Das Ergebnis wird in einer eigenen Variablen ›ergebnis‹ gespeichert: ergebnis =sqrt(zahl);
Nun kann das Ergebnis der Berechnung zunächst auf dem Monitor dargestellt werden, was sich insbesondere in der Zeit der Programmentwicklung anbietet, um Fehler schneller zu erfassen. Der dazu nötige Sketch könnte wie folgt aussehen:
Serial.print("Zahlenwurm = ");
Serial.println(zahlenwurm);
Serial.print("Wurzel aus "); Serial.print(zahl); Serial.print(" = ");
Serial.println(ergebnis,6); //Ergebnis mit 6 Nachkommastellen auf Monitor ausgeben
Um das Ergebnis der Wurzelberechnung auf der LCD-Anzeige auszugeben ist folgender Sketch hilfreich:
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Wurzel:");
lcd.setCursor(0, 1);
lcd.print(ergebnis,6);
Als Ergebnis wird auf der LCD folgendes angezeigt:
Wiederholtes Betätigen der #-Taste bewirkt ein stufenweises Berechnen der mathematischen Aufgaben, die selbst festgelegt werden können. Beispielsweise kann aus dem Ursprungswert nicht nur die Wurzel, sondern beispielsweise auch die Potenz berechnet werden.
Natürlich sind auch die trigonometrischen Funktionen problemlos anwendbar. Allerdings ist zu beachten, dass der in der Variablen ›zahl‹ stehende Wert dazu zunächst in das Bogenmaß umgerechnet werden muss, was mit folgender Formel geschieht: ›zahl = zahl*PI/180;‹
Anschließen ist der Sinus mit der Formel ›ergebnis =sin(zahl);‹ ermittelbar. Das Ergebnis präsentiert sich an der LCD-Anzeige wie folgt:
Damit das Durchschalten der Funktionen über die #-Taste funktioniert, muss eine Variable genutzt werden, die dem Programm sagt, welche Funktion als nächstes aufgerufen werden muss. Dazu eignet sich beispielsweise der Name ›Modus‹. Dies ist eine Integer-Variable, die von Null hochgezählt wird und bei Erreichen der maximalen Wertigkeit – die von der Zahl der selbst implementierten Rechenmodule abhängt – wieder auf null zurückgesetzt wird.
Das nachfolgende Programm verdeutlicht den Zusammenhang, um Arduino in einen einfachen Rechner zu verwandeln, der für viele Zwecke genutzt werden kann.
/**************************************************************
Rudimentäres Rechenprogramm unter Verwendung eines 16x2 LCD-Displays sowie eines Keypads
Besonderheit: Die Analogeingänge werden zu Digitaleingängen umprogrammiert und genutzt,
um Platz für den Anschluss des Keypads zu bekommen.
Nötige Bibliotheken: LiquidCrystal.h und Keypad.h
**************************************************************/
// Bibliotheken einbinden
#include <LiquidCrystal.h>
#include <Keypad.h>
// LCD Pins festlegen
// Anschlüsse: RS, E, D4, D5, D6, D7
LiquidCrystal lcd(A5, A4, A3, A2, A1, A0);
// Variablendeklaration
int ASCII;
int Modus = 0;
float zahl = 0;
float ergebnis;
String zahlenwurm =""; // String, in die später Zahlenwerte stehen
//Definieren der Zeilen und Spalten
const byte COLS = 3; //Spalten
const byte ROWS = 4; //Zeilen
//Definieren der Pins, über welche das Keypad
//mit dem Microcontroller verbunden wurde.
byte COL_PINS[COLS] = { 2, 3, 4 }; //Spalten
byte ROW_PINS[ROWS] = { 5, 6, 7, 8 }; //Zeilen
//Aufbau der Tastatur als mehrdimensionales Array abbilden.
//Es ist darauf zu achten das die Tastatur gedreht abgebildet ist.
const char KEYS[ROWS][COLS]={
{'#','0','*'},
{'9','8','7'},
{'6','5','4'},
{'3','2','1'}
};
Keypad (keypad) = Keypad(makeKeymap(KEYS), ROW_PINS, COL_PINS, ROWS, COLS); // keypad initialisieren
void setup()
{
// Serial-Monitor initialisieren
Serial.begin(9600);
// PWM-Signal für LED Hintergrundbeleuchtung
analogWrite(9, 150);
// LCD initialisieren und Eingabebereitschaft anzeigen
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("Bereit!");
}
void loop()
{
//Lesen, ob eine Taste gedrückt wurde
char key = keypad.getKey();
ASCII = key;
if (key != NO_KEY) // Wenn irgendeine Taste am Keypad gedrückt, dann weiter
{
if (Modus == 0)
{
// LCD löschen und Modus auf 1 setzen
Modus = 1;
lcd.clear();
}
}
if (key == '1')
{
zahlenwurm = zahlenwurm + ("1");
}
if (key == '2')
{
zahlenwurm = zahlenwurm + ("2");
}
if (key == '3')
{
zahlenwurm = zahlenwurm + ("3");
}
if (key == '4')
{
zahlenwurm = zahlenwurm + ("4");
}
if (key == '5')
{
zahlenwurm = zahlenwurm + ("5");
}
if (key == '6')
{
zahlenwurm = zahlenwurm + ("6");
}
if (key == '7')
{
zahlenwurm = zahlenwurm + ("7");
}
if (key == '8')
{
zahlenwurm = zahlenwurm + ("8");
}
if (key == '9')
{
zahlenwurm = zahlenwurm + ("9");
}
if (key == '*')
{
zahlenwurm = zahlenwurm + (".");
}
if (key == '0')
{
zahlenwurm = zahlenwurm + ("0");
}
if (ASCII >= 42 && ASCII <= 57) //Wenn Zahl zwischen 0 und 9 sowie * (=.)
{
lcd.setCursor(0, 0);
lcd.print(zahlenwurm); // Eingegebenen Wert an LCD anzeigen
}
if (key == '#')
{
// Moduszähler hochsetzen, um zwischen den Berechnungen wechseln zu können
Modus = Modus+1;
if (Modus == 2)
{
// Wurzel berechnen
zahl = zahlenwurm.toFloat(); //Umwandlung String in Flieskommazahl
ergebnis =sqrt(zahl); // Wurzel berechnen
// Wurzel auf Monitor ausgeben
Serial.print("Zahlenwurm = ");
Serial.println(zahlenwurm);
Serial.print("Wurzel aus "); Serial.print(zahl); Serial.print(" = ");
Serial.println(ergebnis,6); //Ergebnis mit 6 Nachkommastellen auf Monitor ausgeben
// Wurzel auf LCD ausgeben
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Wurzel:");
lcd.setCursor(0, 1);
lcd.print(ergebnis,6);
}
if (Modus == 3)
{
// Potenz berechnen
zahl = zahlenwurm.toFloat(); //Umwandlung String in Flieskommazahl
ergebnis =sq(zahl); // Potenz berechnen
// Potenz auf Monitor ausgeben
Serial.print("Zahlenwurm = ");
Serial.println(zahlenwurm);
Serial.print("Potenz aus "); Serial.print(zahl); Serial.print(" = ");
Serial.println(ergebnis,6); //Ergebnis mit 6 Nachkommastellen auf Monitor ausgeben
// Potenz auf LCD ausgeben
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Potenz:");
lcd.setCursor(0, 1);
lcd.print(ergebnis,6);
}
if (Modus == 4)
{
// Sinus berechnen
zahl = zahlenwurm.toFloat(); //Umwandlung String in Flieskommazahl
zahl = zahl*PI/180; // Dezimalgrad in Bogenmass umwandeln
ergebnis =sin(zahl); // Sinus berechnen
// Sinuswert auf Monitor ausgeben
Serial.print("Zahlenwurm = ");
Serial.println(zahlenwurm);
Serial.print("Sinus aus "); Serial.print(zahl); Serial.print(" = ");
Serial.println(ergebnis,6); //Ergebnis mit 6 Nachkommastellen auf Monitor ausgeben
// Sinus auf LCD ausgeben
lcd.clear(); lcd.setCursor(0, 0);
lcd.print("Sinus:");
lcd.setCursor(0, 1);
lcd.print(ergebnis,6);
}
if (Modus == 5)
{
// Neue Berechnung einleiten
Modus = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Bereit!");
zahlenwurm ="";
}
}
}
War dieser Artikel für Sie hilfreich?
Bitte bewerten Sie diese Seite durch Klick auf die Symbole.
Zugriffe heute: 3 - gesamt: 5141.