Kategorie-Archiv: Software

Test eines einfachen Ultraschall Sensors für 80 Cent

In diesem Video teste ich einen einfachen Ultraschallsensor, der bei Aliexpress gerade mal 80 Cent kostet. Die Ansteuerung ist sehr einfach und schnell (wenn man keine unnötigen Fehler macht) und die Ergebnisse sind erstaunlich gut.

#include <Arduino.h>

const int TRIG_PIN = 12;
const int ECHO_PIN = 13;
const int ITEM_COUNT = 50;

long simpleMultiMeasure();

void setup() {
  Serial.begin(9600);
  pinMode(TRIG_PIN,OUTPUT);
  digitalWrite(TRIG_PIN, LOW);

  pinMode(ECHO_PIN,INPUT);
}

void loop() {
  long duration = simpleMultiMeasure();
  long distanceMm;
 
  // convert the time into a distance
  distanceMm = duration * 100l / 582l;
 
  if (distanceMm <= 0)
  {
    Serial.println("Out of range");
  }
  else 
  {
    Serial.print(duration);
    Serial.print(" ticks, ");
    Serial.print(distanceMm);
    Serial.print(" mm");
    Serial.println();
  }
  
  delay(500);
}

long simpleMultiMeasure() {
  long sum = 0;

  for (int i = 0; i < ITEM_COUNT; i++) {
    digitalWrite(TRIG_PIN, HIGH);
    delayMicroseconds(20);
    digitalWrite(TRIG_PIN, LOW);
    sum += pulseIn(ECHO_PIN,HIGH);
    delayMicroseconds(20000);
  }

  return sum / ITEM_COUNT;
}


Ein RISC-V Test mit dem Sipeed Longan Nano Board

Ich wollte schon lange mal mit einem RISC-V Prozessor experimentieren. Mit dem Longan Nano Board für 2,50 Euro steht in Development Board zur Verfügung bei dem man nicht lange nachdenken muss. Für ein Euro Aufpreis bekommt man noch ein farbiges LCD dazu.

Falls jemand an dem winzigen Assembler Programm aus dem Video interessiert ist, kann man es hier kopieren:

.section .text
.align 2
.global toggle

.equ GPIO_PORT_B_CONTROL, 0x40010c10
.equ SET_ALL_BITS, 0x0000ffff
.equ RESET_ALL_BITS, 0xffff0000


toggle:
  li t0, GPIO_PORT_B_CONTROL
  li t1, SET_ALL_BITS
  li t2, RESET_ALL_BITS

loop:
  sw t1, (t0)
  sw t2, (t0)
  sw t1, (t0)
  sw t2, (t0)
  j loop

Startbild: RISC V prototype chip – crop of File:Yunsup Lee holding RISC V prototype chip.jpg. Wikimedia, Creative-Commons-Lizenz „CC0 1.0 Verzicht auf das Copyright“

Ein computergesteuerter Messplatz mit einem ESP 32, Teil 2

In diesem zweiten Teil wird die Software zu dem Projekt beschrieben. Sie besteht aus drei Teilen.

  1. Ein Platform IO Projekt mit einem C++ Programm welches auf dem ESP32 läuft.
  2. Ein Netbeans Projekt in Java welches auf dem PC ein Framework zur Verwendung des Messplatzes zur Verfügung stellt. Weiterhin enthält es einen komfortablen Weg zur Erstellung von CSV (comma separated values) Dateien.
  3. Ein Netbeans Projekt welches die Verwendung der DataIO jar Datei zeigt.

Touchsensor TTP223 Test

Ich wollte mal ausprobieren, ob sich die Touchsensoren für den Aufbau von Stellpulten eignen. Die Verwendung ist einfach und sie funktionieren gut, es gibt aber auch ein paar Schattenseiten.

#define TOUCH_INPUT 2
#define SIGNAL 3
#define SETTLE_TIME 100

void setup() {
pinMode( TOUCH_INPUT, INPUT );
pinMode( SIGNAL, OUTPUT );
}

void loop() {
int isTriggered = digitalRead( TOUCH_INPUT );
digitalWrite( SIGNAL, switchState( isTriggered ) );
}

boolean actState = false;
boolean lastActive = false;
boolean switchState( boolean signal ) {
boolean deb = debounce( signal );
if ( deb ) {
if ( !lastActive ) {
lastActive = true;
actState = !actState;
}
} else {
lastActive = false;
}

return actState;
}

int trig = 0;
boolean debounce( boolean signal ) {
if ( signal ) {
if (trig == 0) {
trig = millis();
} else {
int now = millis();
if ( now – trig > SETTLE_TIME ) {
return true;
}
}
} else {
trig = 0;
}

return false;
}

Ein kleines JavaScript Spielprogramm

In der letzten Woche habe ich durch Zufall ein JavaScript Spielprogramm gefunden. Die Spielidee ist einfach: es gibt ein Array von verschieden farbigen Kacheln. Der Anwender kann diese paarweise auswählen – was dazu führt, dass die beiden Kacheln vertauscht werden. Dabei können aber nur direkt benachbarte Kacheln getauscht werden. Wenn es mehr als 3 zusammenhängende gleichfarbige Kacheln in einer Zeile oder Spalte gibt, war der Spielzug gültig und es werden einem Punkte dafür gut geschrieben.

Das Original war mit einer recht kurzen Zeitschranke versehen. Ich wollte aber wissen, ob das Spiel zwingend irgendwann zum Ende kommt, weil es keine weiteren Kombinationen mehr gibt, die durch einen einfachen Austausch zu erreichen wären. Mein erster Versuch dazu war, dass ich im Browser versucht habe, den Timer stillzulegen. Das Programm hat sich aber gegen Veränderungen gewehrt, deshalb habe ich mich entschlossen, es gleich nachzuprogrammieren.

Meine Version hat keine Zeitbeschränkung und zudem auch eine Hilfefunktion. Wenn man an einem Punkt nicht weiter weiß, kann man sich über eine Tipp Funktion eine Möglichkeit markieren lassen – falls es noch eine gibt. Ich habe noch nicht beobachtet, dass die Tipp-Funktion eine Möglichkeit übersehen hat. Schon nach kurzer Zeit hat sich gezeigt, dass es im Allgemeinen ein Ende gibt. Manchmal schon nach 200 Spielzügen. Ich habe aber auch schon 1500 Spielzüge überstanden, ohne dass ein Ende absehbar war. Ich gehe aber davon aus, dass sich jedes Spiel irgendwann in einer Situation befindet, in dem es keine weiteren gültigen Spielzüge mehr gibt.

Das Spiel ist komplett in html / CSS / JavaScript programmiert. Es gibt noch nicht mal eine Image Datei. Es wird auch kein Framework, wie z.B. JQuery, verwendet. Ich wollte auch mal ausprobieren, wie gut man zu Fuß mit Animationen zurecht kommt. Das eine oder andere könnte man mit CSS Animationen noch besser machen. Für mich war der aktuelle Stand aber gut genug.

Die Animationen, wie z.B. das Verschieben der Kacheln sowie ein- und ausblenden des Hilfe-Dialogs werden über Timer-Callback Funktionen durchgeführt. Das Skript ist relativ kurz und hat deshalb nur drei Klassen: das Spiel-Objekt, das Gitternetz im Spiel und ein Kachel-Objekt. Insgesamt etwa 100 Zeilen CSS für die Formatierung und 600 Zeilen JavaScript für die Spielausführung.

THM-Flip: hier geht’s zum Spiel

ThmFlip

Fließkommazahlen und unerfahrene Programmierer

Gestern habe ich auf slashdot.org ein Beitrag eines Programmierers gesehen, der sich darüber beklagt hat, dass von ihm verlangt wurde, eine Steuerberechnung mit JavaScript zu entwickeln. Schließlich kennt JavaScript nur Fließkommazahlen und „jeder“ weiß, dass man damit keine kaufmännischen Anwendungen schreiben kann.

Diese Meinung ist weit verbreitet – gerade in diesen Kreisen. Das weckt bei mir den Argwohn, ob im Bereich kaufmännischer Software verstärkt mäßig erfahrene Programmierer unterwegs sind? Und aus solchen Vorurteilen und mangelnden Wissen resultieren dann BCD Arithmetik-Libraries und BCD Befehle in Prozessoren (BCD = binary coded decimal – zwei Dezimalziffern 0-9 und 0-9 in einem Byte).

Das ist totaler Unfug und zeigt nur einen erheblichen Mangel an (mathematischen) Wissen.

Mythos 1: im Binärsystem kann man Zahlen nicht exakt darstellen, im Dezimalsystem schon.
Fast völliger Unsinn. Es wird immer der Wert 0.1 (als Bruch: 1/10) als Beispiel genommen. Dieser Wert ist im Binärsystem tatsächlich nur gerundet darzustellen, da er dort eine unendliche Periode besitzt. Aber solche Zahlen gibt es im Dezimalsystem auch: 1/3. Dieser Wert lässt sich Dezimal auch nur gerundet darstellen. Prinzipiell gilt für (teilerfremde) Brüche der Art p/q, dass sie eine periodische Darstellung haben, wenn q Primfaktoren besitzt, die in der Basis nicht vorkommen. Das Binärsystem hat nur den Primfaktor 2 in der Basis – wirklich nicht üppig. Im Dezimalsystem sind es 2 und 5 – auch nicht wirklich besser. 1/3 – 1/7 – 1/11 – 1/13… verdammt viele Brüche erzeugen in beiden Systemen eine periodische Darstellung.

Das Problem ließe sich hier noch lösen, indem man mit Rationalen Zahlen arbeitet. Das hat aber Grenzen, denn man kann niemanden eine Rechnung schicken, auf der 47/11 Euro gefordert werden. Auf der Rechnung werden also doch nur 4,272727272727272727272727272727… Euro oder gerundet 4,27 Euro auftauchen.

Mythos 2: mit Fließkommazahlen kann man nicht Cent-genau rechnen
Eine double Fließkommazahl (wie sie z.B. von JavaScript verwendet wird) besitzt über 50 Bit für die Mantisse. Das sind mehr als 15 Dezimalstellen. Damit kann man mehr als nur das gesamte Geld dieser Welt auf einen Cent genau darstellen. Man muss lediglich darauf achten, den Fließkommawert bei der Ausgabe zum nächsten Cent hin auf- oder abzurunden.

Wenn die NASA mit Fließkommaberechnungen Satelliten auf Milliarden Kilometer genau steuern kann, dann sollte auch ein mäßig begabter Programmierer in der Lage sein, eine Leberwurst und 200 Gramm Butter abzurechnen. Das ist keine Raketenwissenschaft.

Mythos 3: wenn ich Integer-Werte für Cent-Beträge verwende, habe ich keine Rundungsfehler
Das gilt nur, wenn man sich auf simple Addition, Subtraktion oder Multiplikation beschränkt. Sobald eine Division ins Spiel kommt, ist der Vorteil dahin (ab hier sind es rationale Zahlen). Sieben Prozent Mehrwertsteuer auf mein Buch für 43,21 Euro sind 3,0247 Euro. Natürlich kann ich auch in hundertstel-Cent statt Cent rechnen. Aber das verschiebt das Problem nur und löst es nicht prinzipiell. Sobald ich den Betrag über eine Split-Buchung auf drei Kostenstellen aufteile, ist es mit exakten Werten vorbei.

Mythos 4: in einer Rechnung müssen alle Beträge auf den Cent genau stimmen
Das funktioniert nur, wenn man genügend ungenau hinschaut. Wenn ich auf einer Rechnung die gerundeten Mwst-Beträge zu jeder Rechnungsposition ausweise, wird die Summe der Beträge nur zufällig exakt zum gerundeten Mwst-Betrag der Netto Summe passen. Das Finanzamt weiß das. Jeder vernünftige Kaufmann ebenfalls. Und ein Programmierer sollte das auch wissen.

Fazit: man kann auch kaufmännische Software mit Fließkommazahlen erstellen
Es müssen halt einfach ein paar Rahmenbedingungen beachtet werden. Alle Ausgabewerte sollten auf den nächsten Cent auf- oder abgerundet werden. Sonst passieren so Dinge wie „überweisen Sie 4,272727272727273 Euro auf unser Konto“. Das ist immer für einen Lacher gut, aber genau genommen ist nichts schlimmes passiert. Der Betrag ist unhandlich aber nicht so falsch, dass ein messbarer Schaden entsteht.

Man kann einen Fließkommawert nicht unbesehen als Schleifenzähler verwenden. Dann kann es zu den gefürchteten „one off“ Fehlern kommen, die Schleife läuft einmal zu oft oder zu wenig. Auch hier muss man mit einer geeigneten Skalierung und Rundung arbeiten – dann geht das sehr wohl.

Bei extrem unterschiedlichen Werten kann die Reihenfolge der Berechnung für das Ergebnis wichtig sein: (1.001 * 10 hoch 15 + 0.00000001) – 1.0005 * 10 hoch 15 wird ein anderes Ergebnis liefern als (1.001 * 10 hoch 15 – 1.0005 * 10 hoch 15) + 0.00000001. So etwas kommt in der Physik und in der Mathematik durchaus vor. In kaufmännischen Anwendungen hat man so eine Dynamik eher nicht.