Elektronische Flächen-Wasserwaage mit Arduino Nano und Beschleunigungssensor [Teil 2]

Im zweiten Teil gibt es nun ein Gehäuse für unsere Wasserwaage. Außerdem eine verbesserte Version der Software. Die Kalibrierung wird nun im EEPROM des Arduino Nano gespeichert. Außerdem wird die Batteriespannung gemessen und im Display angezeigt.

Benötigte Hardware:

Anzahl Bauteil Anmerkung
1 Beschleunigungssensor GY-61
1 Arduino Nano
1 1.3 Zoll OLED
1 Widerstand 4.7 kOhm
1 Widerstand 10 kOhm
1 Lochrasterplatte 50x70 mm
2 Federleiste 16polig
1 Federleiste 6polig
1 Federleiste 4polig
1 Mikrotaster 6x6x8mm
5 Batteriekontakte
1 Schiebeschalter
4 Blechschrauben 2.2 x 9,5
4 Teile aus dem 3-D Drucker

 Schaltung

Da die Software auch die Batteriespannung überwachen soll, müssen wir diese über einen Spannungsteiler auf einen der Analogeingänge führen. Wir verwenden einen Vorwiderstand von 4.7 kOhm und einen Parallelwiderstand von 10 kOhm. Am Parallelwiderstand dürfen maximal 5V auftreten. Das heißt, die Eingangsspannung darf maximal 5V/10k * (10k + 4,7k) = 7.35V betragen, was mit vier Batterien nicht erreicht wird.

Schaltung Wasserwaage

Verdrahtung der Lochrasterplatte

Die Abbildung zeigt die zugeschnittene Lochrasterplatte von der Unterseite. Für den Arduino Nano verwenden wir zwei Federleisten mit 16 Kontakten, für den Sensor einen mit 6 Kontakten und für das Display einen mit 4 Kontakten. Taster, Schiebeschalter und Widerstände werden direkt eingelötet.

Es ist wichtig, alle Bauteile genau an den Positionen einzubauen, die auf der Abbildung dargestellt werden, da sonst die Elektronik nicht in das Gehäuse passt. Jeder schwarze Punkt ist ein genutzter Lötpunkt.

Die Software

Zur Erklärung ist der Code ausführlich kommentiert.

#include <U8g2lib.h>
#include <Wire.h>
#include <math.h>
#include <EEPROM.h>

#define PINTASTER 4 //Pinnummer für den Taster

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); //Instanz für OLED Display

bool mod_run; //Flag für den Betriebszustand
bool pressed; //Status des Tasters zur Entprellung
uint8_t sl=0; //Level für Kalibrierung

//die Kalibrierungsdaten werden in einer Struktur zusammengefasst
//das vereinfacht das Lesen und das Schreiben vom und zum EEPROM
typedef
struct {
uint16_t id; //Kennung damit wir wissen ob bereits 
//Kalibrierungsdaten gespeichert wurden
int x0,y0,z0; //Nullpunkte
float xa, ya, za; //Amplituden
} KALIBRIERUNG;

//hier definieren wir den Speicherplatz für die Struktur
KALIBRIERUNG cal;

int xlast= 0, ylast = 0; //Vorheriger messwert

//Diese Funktion bereitet das Display zur Anzeige vor
void u8g2_prepare(void) {
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.setFontRefHeightExtendedText();
  u8g2.setDrawColor(1);
  u8g2.setFontPosTop();
  u8g2.setFontDirection(0);
}

//Messwerte anzeigen
void showMessung() {
  int x,xneu;
  int y,yneu;
  int z;
  float wx,wy,wz;
  char tmp[10];
  //Werte einlesen
  xneu= analogRead(A0)-cal.x0;
  yneu= analogRead(A1)-cal.y0;
  z= analogRead(A2)-cal.z0;
  //Mittelwertbildung um nRauschen zu reduzieren
  x = (xneu+xlast)/2;
  y = (yneu+ylast)/2;
  xlast = xneu;
  ylast = yneu;
  //Winkel berechnen
  wx = asin(x/cal.xa)*180/M_PI;
  wy = asin(y/cal.ya)*180/M_PI;
  wz = asin(z/cal.za)*180/M_PI;
  //Zur Kontrolle auf die Konsole ausgeben
  Serial.print(x);Serial.print(",");
  Serial.print(y);Serial.print(",");
  Serial.print(z);Serial.print(",");
  Serial.print(wx);Serial.print(",");
  Serial.print(wy);Serial.print(",");
  Serial.print(wz);Serial.println();
  //Batteriespannung messen
  //Spannungsteiler 4.7k und 10k bei 5V an A7
  //Eingangsspannung = 5V/10k *14,7k = 7.35V
  float bat = analogRead(A7)*7.35/1023;
  //Anzeige am Display
  u8g2.clearBuffer();
  u8g2_prepare();
  //Kreis für den Sollwert
  u8g2.drawCircle(32,32,5);
  //Punkt für den Istwert
  u8g2.drawDisc(32-(x*2),32+(y*2),2);
  //X-Winkel
  u8g2.drawStr(70,10,"X = ");
  dtostrf(wx,3,1,tmp);
  u8g2.drawStr(100,10,tmp);
  //Y-Winkel
  u8g2.drawStr(70,30,"Y = ");
  dtostrf(wy,3,1,tmp);
  u8g2.drawStr(100,30,tmp);
  //Batterie
  u8g2.drawStr(70,50,"B = ");
  if (bat > 4.9) {
    dtostrf(bat,3,1,tmp);
    u8g2.drawStr(100,50,tmp);
  } else {
    u8g2.drawStr(100,50,"LOW");
  }
  u8g2.sendBuffer();
}

//Kalibrierungsanweisungen anzeigen
void showSetup(uint8_t level) {
  u8g2.clearBuffer();
  u8g2_prepare();
  switch(level) {
    case 0 : u8g2.drawStr(10,30,"flach hinlegen"); break;
    case 1 : u8g2.drawStr(10,30,"90 Grad hochkippen"); break;
    case 2 : u8g2.drawStr(10,30,"90 Grad seitlich kippen"); break;
  }
  u8g2.sendBuffer();
}

//Setup
void setup() {
 Serial.begin(9600);
 u8g2.begin();
 //Pin für Taster auf Input setzen
 pinMode(PINTASTER,INPUT_PULLUP);
 //Wir lesen die Kalibrierungsdaten aus dem EEPROM von Adresse 0
 EEPROM.get(0,cal);
 //wenn die id 54321 ist haben wir gültige Kalibrierungswerte
 //sonst müssen wir eine Kalibrierung starten
 mod_run = (cal.id == 54321);
 //Anfangswerte lesen
 if (mod_run) {
  xlast= analogRead(A0)-cal.x0;
  ylast= analogRead(A1)-cal.y0;
 }
}

void loop() {
  //Taster einlesen
  uint8_t taster = digitalRead(PINTASTER);
  if ((taster == 0) && (!pressed)) {
    //wenn der Wert 0 ist und der Taster noch nicht gedrückt wurde
    //registrieren wir, dass der Taster jetzt gedrückt wurde
    pressed = true;
  }
  if ((taster == 1) && (pressed)) {
    //wenn der Wert 1 ist und der Taster gedrückt war, wurde er
    //jetzt losgelassen
    pressed = false;
    
    if (mod_run) {
      //Wenn wir im Messmodus waren, schalten wir in den Kalibrierungs Modus
      //und setzen den Kalibrierungslevel auf 0
      mod_run = false;
      sl = 0;
    } else {
      //wir sind im Kalibrierungsmodus und müssen je nach Level
      //die Kalibrierungswerte erfassen
      sl++;
      switch (sl) {
        //das Gerät liegt flach X und Y sind 0 Z ist ´Maximum
        case 1: cal.x0= analogRead(A0);  cal.y0 = analogRead(A1); cal.za = abs(analogRead(A2)); break;
        //das Gerät wurde nach oben gekippt Z ist 0 X ist Maximum; 
        case 2: cal.z0= analogRead(A2);  cal.xa= abs(analogRead(A0)); break;
        //das Gerät ist seitlich  Y ist Maximum
        case 3: cal.ya = abs(analogRead(A1)); break;
      }
      //wir haben alle nötigen Werte und können die Kalibrierungswerte setzen
      //anschließen wird der Mess Modus aktiviert
      if (sl > 2) {
        //die Amplituden werden relativ zum Nullpunkt ermittelt
        //die Multiplikation mit 1.0 stellt sicher, dass wir
        //eine Fließkommazahl haben
        cal.xa = cal.xa-cal.x0*1.0; 
        cal.ya = cal.ya-cal.y0*1.0; 
        cal.za = cal.za-cal.z0*1.0;
        //die id setzen wir auf 54321 um zu wissen,
        //dass Kalibrierungsdaten vorliegen
        cal.id =54321;
        //wir schreiben die Kalibrierung in den EEPROM auf Adresse 0
        EEPROM.put(0,cal);
        //Die Betriebsart wird auf Messen gesetzt.
        mod_run = true;
       //Anfangswerte lesen
       if (mod_run) {
        xlast= analogRead(A0)-cal.x0;
        ylast= analogRead(A1)-cal.y0;
       }
      }
    }
  }
  //Je nach Modus wird die Anzeige entsprechend umgeschaltet
  if (mod_run) {
    showMessung();
  } else {
    showSetup(sl);
  }
  
  delay(200);
}

Wir sollten jetzt die Lochrasterplatte mit dem Nano, dem Sensor und dem Display bestücken und den Sketch hochladen, damit wir die Verdrahtung überprüfen können.

ACHTUNG!!
Da die Federleisten für den Nano und den Sensor jeweils um einen Kontakt mehr als nötig haben, ist zu beachten, dass beide Module rechtsbündig eingesteckt werden. Nachdem die Hardware getestet wurde, können wir die Gehäuseteile drucken und dann die Elektronik einbauen.

Gehäuse aus dem 3-D Drucker

Alle Files zum Herstellen des Gehäuses findet man unter folgenden Link in Thingiverse
https://www.thingiverse.com/thing:4305737
Unterteil

Oberteil

Knopf für Taster

Batteriefach

Zusammenbau

Nach dem Drucken des Batteriefachs werden die Federkontakte montiert. Auf einer Seite zwei Doppelkontakte, auf der anderen Seite außen jeweils ein Kontaktplättchen und eine Feder. In der Mitte ein Doppelkontakt. Da dieser aber andersherum eingebaut werden muss, müssen wir die Lötfahne beim Doppelkontakt entfernen.

Das Batteriefach und die bestückte Lochrasterplatte kommen jetzt in das Gehäuse-Unterteil.

Die Anschlüsse des Batteriefachs verbinden wir mit den entsprechenden Anschlusspunkten auf der Lochrasterplatte. Polung beachten! Dann können wir den Arduino Nano, den Sensor und das Display bestücken. Damit der Sensor sicher mit dem Gehäuse verbunden und parallel zur Auflagefläche ist, wird er mit zwei Schrauben festgeschraubt.

Ehe wir das Gehäuse schließen, können wir noch einmal die Funktion mit Batteriebetrieb testen. In den Zylinder im Deckel fügen wir den Knopf ein. Den Deckel selbst kann man mit zwei Schrauben sichern.

Nun können wir das fertige Gerät kalibrieren. Wir schalten das Gerät im Batteriebetrieb ein. Falls schon eine Kalibrierung gespeichert wurde, werden Messwerte angezeigt. Durch Drücken der Taste kommen wir in den Kalibrier-Modus. Im ersten Schritt legen wir das Gerät auf eine ebene Fläche und drücken die Taste. Im zweiten Schritt wird das Gerät hochkant gestellt und wieder der Knopf gedrückt. Im letzten Schritt kippen wir das Gerät seitlich und drücken nochmals den Knopf. Das Gerät ist jetzt kalibriert und kann eingesetzt werden. Da die Kalibrierung im EEPROM gespeichert wurde, bleibt sie auch nach dem Abschalten gespeichert.

 Viel Spaß beim Nachbauen

Auf vielfachen Wunsch hier der Download des Blog-Beitrags als pdf-Dokument.

 

Gy-61Nanov3OledWasserwaage

7 Kommentare

Gerald Lechner

Gerald Lechner

Hallo Alexander,
der Sketch im Teil 2 macht genau das. Die Kalibrierung wird im EEPROM des Nano gespeichert. Beim Einschalten wird geprüft ob gespeicherte Kalibrierungsdaten vorhanden sind. Ist das der Fall wird sofort der Messmodus gestartet. Sind keine gespeicherten Kalibrierungsdaten vorhanden, muss eine Kalibrierung durchgeführt werden. Durch Drücken des Tasters, kann in jedem Fall eine Kalibrierung ausgelöst werden.
"

Alexander

Alexander

Hallo,
gibt es vielleicht auch eine Version, die man Kalibriert und die Werte abspeichert?
So hat man eine genaue Kontrolle ohne jedes mal die Wasserwaage neu zu kalibrieren.
Man braucht ja sonst immer eine Referenzfläche, wer hat die immer dabei?

LG

Dietmar Grummt

Dietmar Grummt

gibt es den Software Code auch zum runterladen ?
MfG
Dietmar

Bernd Albrecht

Bernd Albrecht

@ Conny: Das verwendete Programm heißt Inkscape. In den meisten Fällen eignet es sich auch für Schaltpläne, da man bei fritzing oft die Bauteile nicht findet.

Vorankündigung: In den nächsten vier Wochen soll hier auch ein fritzing Tutorial veröffentlicht werden.

C0NNY

C0NNY

Mit welchen Programm ist denn das Layout auf der Lochrasterplatine gemacht?

Gerald

Gerald

Das Rauschen beträgt etwa +/- 1Grad. Das ist auch ungefähr die Fläche des Kreises. Bei ebener Lage und korrekter Kalibrierung, wird der Messpunkt innerhalb des Kreises herumtanzen.

Gunther Waage

Gunther Waage

Danke für die gut geschriebene Anleitung.
Ich habe beide Blog-Beiträge gelesen aber keine Angaben zu der Genauigkeit des Aufbaus gefunden.
Kann man darüber eine Aussage treffen?
Ich freue mich auf die Antwort
MfG

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert