Bienenwaage: Prototyp im Testlauf (Bauanleitung)

Das ist Eintrag 11 in der Serie "Bienenwaage".

Der Bauanleitungen dieser Serie sind veraltet. Aktuell ist die Serie Bienenkiste 2.0.

Zusammenfassung

Das wichtigste vorneweg: Die Waage produziert zuverlässig hinreichend genau (+/- 15g) Gewichts- und Temperaturwerte, deren Entwicklung und aktueller Stand in Echtzeit im Netz durch zwei Kurven visualisiert sind. Zweck der Übung ist die Erleichterung und Verbesserung der Gewichtskontrolle eines Bienenstocks im Hinblick auf die Herbstfütterung und Einwinterung. Außerdem soll die Anlage beim Abgang eines Schwarms eine Alarmemail verschicken.

Funktionsweise: Eine Wägezelle, zwischen zwei aus Vierkantprofilen geschweißten H-Teilen geschraubt, bildet das Wägegestell (vgl. die Gestellalternative ohne Schweißen). Ein AD-Wandler nimmt die Signale der Wägezelle entgegen, ein Arduino rechnet sie um, nimmt außerdem die Werte eines Temperatursensors entgegen und hält eine Webseite vor, die die Daten enthält (vgl. Sketch). Auf einem Webserver löst ein cronjob regelmäßig ein PHP-Skript aus, das die Webseite mit den Daten beim Arduino abruft, offensichtliche Messfehler aussortiert, jeder Messwertserie einen Zeitstempel verpasst und gültige Daten in eine Flatfiledatenbank (Textdatei sensorik.csv) schreibt. Eine weitere Webseite, in die das javascript-Kurvendarstellungssystem dygraphs eingebunden ist, stellt dann aus der Flatfiledatenbank die Kurven dar.

Einen ähnlichen Ansatz verfolgt everettsprojects. Er diente für mich jedoch eher als proof-of-konzept denn als Anleitung, der ich folgen konnte. Zu viele Details in der Konfiguration waren unterschiedlich.

Beachte auch die Liste der jetzt noch anstehenden Schritte. Kommentare und Fragen sind willkommen!

Teileliste

Wägezelle, Analog-Digital-Wandler, Waagenunterbau sind in einem früheren Artikel genauer beschrieben. Und eine umfassende Teileliste gibt es ebenfalls in einem separaten Artikel.

Übersicht Teilschritte

Die Inbetriebnahme des Wägegestells mit der Wägezelle und der Grundfunktion der Waage (vernünftige Gewichtswerte auf dem seriellen Monitor des Arduino) hat schon vor einigen Wochen stattgefunden und wird im Artikel „Durchbruch Bienenwaage“ beschrieben. Dieser Artikel baut darauf auf. Den Aufbau der Schaltung behalten wir bei, es kommt nur der Temperatursensor hinzu. Das vorhandene Arduino-Skript wird erweitert. Ganz unten protokolliere ich Änderungen.

Damit stehen jetzt folgende Schritte an:

  1. Temperatursensor dazuschalten
  2. Arduino-Skript anpassen
  3. Webseite mit der Kurvendarstellung (und ggf. Webserver) klar machen
    • eine javascript-Bibliothek auswählen, die die Kurvenformatierung übernimmt („charting library“)
  4. eine mit der ausgewählten javascript-Bibliothek kompatible Textdatei (Flatfile) zur Datenspeicherung anlegen
  5. php-script aufsetzen, das die Werte abruft, prüft, Zeitstempel vergibt und sie in die Flatfiledatenbank anhängt
  6. Arduino per dyndns (im LAN) für das PHP-Skript (auf dem Webserver im Internet) erreichbar machen:
    • dyndns anmelden
    • dyndns im Router/Fritzbox einrichten
    • Portweiterleitung auf Arduino einrichten
  7. cronjob einrichten, der das PHP-Skript regelmäßig aufruft

Vorgehensweise im Detail

Temperatursensor dazuschalten

DS18B20-hookup
Schaltschema für den Temperatursensor

Bei mir kommt der DS18B20 zum Einsatz. Die Verdrahtung ist einfach, der Sensor wird einfach gemäß Schaltschema (siehe Abb.) zur bestehenden Schaltung hinzugesteckt (Details zur bestehenden Schaltung liefert der Artikel „Durchbruch Bienenwaage“). Lediglich wenn der Sensor unmittelbar nach dem Einstecken heiß wird, dann ist er falschrum eingesteckt! Sofort umdrehen, sonst brennt er aus. Wen Einzelheiten interessieren, mir halfen folgende Seiten:
http://tushev.org/articles/arduino/item/52-how-it-works-ds18b20-and-arduino
http://playground.arduino.cc/Learning/OneWire
http://bildr.org/2011/07/ds18b20-arduino/

arduino-skript (Volltext weiter unten)

Die Erweiterung des Arduino-Skripst stellt eine Netzwerkverbindung per Ethernet zum LAN her, übernimmt die je aktuellen Sensorwerte vom AD-Wandler und verschickt eine kurze Webseite, die dann per http-Weiterleitung ein PHP-Skript namens add_line2.php aufruft und diesem mit dem Aufruf die Sensorwerte zur Weiterverarbeitung übergibt. Der PHP-Aufruf sieht so aus:

http://www.euse.de/honig/beescale/add_line2.php?kiste1=11.023&temp=23.0

Einen etwas anderen Lösungsweg verfolgt hier Uwe Ziegenhagen. Und vor einer lehrreichen Sackgasse warne ich: Mit dem Befehl php-include zu experimentieren, bringt nichts. Der Befehl bildet ein krasses Einfallstor für Hackerangriffe und ist deshalb meistens serverseitig deaktiviert, hat also nur auf meinem lokalen Entwicklungsserver funktioniert (nachdem ich ihn gegen alle Warnungen aktiviert habe), nicht mehr aber auf dem dem Internet ausgesetzten Server meines Providers.

Die Dinge auf dem Webserver einrichten

Ich habe das Glück, dass mein Provider (in-berlin.de) für nicht-kommerzielle Projekte tolle Infrastruktur und Support vorhält. Daher beschäftige ich mich nicht mit dem Aufsetzen des Servers selbst. Lediglich ein Verzeichnis lege ich in meinem www-userspace an, wo dann der ganze Bienenwaagenkram drin liegen wird, konkret ./bienenwaage.

In diesem Verzeichnis landet dann die javascript-Kurven-Bibliothek dygraphs meiner Wahl, die ich zuvor downgeladen habe (Vielen Dank, Clemens, für diesen Tipp!).

Dann landet in diesem Verzeichnis auch die Datei graph.php, die Kurven darstellt und einige Erläuterungen bietet. Bei der Datei handelt es sich um eine HTML-Datei mit eingebetteten PHP-Schnippseln. Damit letztere vom Server auch ausgeführt werden, muss die Datei die Endung .php erhalten (und nicht etwa .htm).

<html>
<head>
<title>Bienenstockwaage - Bee Hive Scale</title> 
<style> 
    body {margin: 1em;} 
    header {background: #eee; padding: 0.5em;} 
    article {margin: 0.5em; padding: 0.5em;} 
</style>
<script type="text/javascript"
  src="dygraph-combined.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" >
<!--meta http-equiv="refresh" content="300"; URL=""-->
</head>
<body>
<header> 
    <img src="" alt=""> 
    <h3>Bienenstockwaage (Testbetrieb) - Bee Hive Scale (Test Run)</h3> 
    <small><?php
  $intervall = 2;  # aktueller wert des cronjobs zur datenerfassung (in minuten)
  #datei mit datenreihe oeffnen
  $datei = fopen("sensorik.csv","r") or die("Kann die Datei nicht aufmachen.");    
  // zeilen einlesen
  $oldlines = @file("sensorik.csv");
  $oldline = (count($oldlines)) ? $oldlines[count($oldlines)-1] : NULL;
  $status = substr($oldline, 0, 16);              #zeitstempel letzte messung    
  $status_minute = substr($oldline, 14, 2);      #minute letzte messung    
  $date = date('Y/m/d H:i');                     #serverzeitstempel abgreifen
  $date_minute  = date('i');                     #serverminute
  if(abs($date_minute-$status_minute) > $intervall)        # Messreihe unterbrochen?
    {     echo "Der Datensammler scheint seit ",$status," offline.<br>";
        echo "Data collection seems offline since ",$status,"."; }            
    else
    {    echo "Letzter Datenstand: ",$status,"<br>";
        echo "Last valid data: ",$status;
    }            
  fclose($datei);
?></small>
</header>
<article>
    <p>Die Waage läuft seit <?php
  $datei = fopen("sensorik.csv","r") or die("Kann die Datei nicht aufmachen.");    
  // erste datenzeile einlesen
  $oldlines = @file("sensorik.csv");
  $oldline = (count($oldlines)) ? $oldlines[2] : NULL;
  $start = substr($oldline, 0, 16);      #zeitstempel erste messung einlesen    
//  echo "Der Datensammler ist seit ",$start," online.";            
  echo $start;
  fclose($datei);
?> im Testbetrieb, d.h. es steht keine Bienenkiste drauf, sondern irgendwelches Testgewicht. Bei der Temperatur handelt es sich um die Zimmertemperatur in einem Raum mit Nachmittagssonne. Solle die Waage keine aktuellen Werte liefern, dann könnte das zusammenhängen mit der Stromversorgung: Derzeit hängt sie an der <a href="https://www.euse.de/wp/blog/2012/03/solarladegerat-fertig/">Solarzelle</a>.<br>
    The scale is running in test mode since <?php
  $datei = fopen("sensorik.csv","r") or die("Kann die Datei nicht aufmachen.");    
  // erste datenzeile einlesen
  $oldlines = @file("sensorik.csv");
  $oldline = (count($oldlines)) ? $oldlines[2] : NULL;
  $start = substr($oldline, 0, 16);      #zeitstempel erste messung einlesen    
//  echo "Der Datensammler ist seit ",$start," online.";            
  echo $start;
  fclose($datei);
?>. There is no beehive on it but some test weight. Temperature is room temperature in a room with afternoon sun. If it doesn't work, it could be due to problems with the power supply. Right now power is provides by the <a href="https://www.euse.de/wp/blog/2012/03/solarladegerat-fertig/">solar module</a>, which is also beta.
    <div id="graphdiv3"
      style="width:1000px; height:400px;"></div>
    <script type="text/javascript">
        g2 = new Dygraph(
        document.getElementById("graphdiv3"),
        "sensorik.csv", // path to CSV file
            {            // options
                labels: [ 'Date', 'Gewicht', 'Temperatur', ],
                ylabel: 'Gewicht/Weight (kg)<br>grün/green',
                valueRange: [0, 80],    //festeinstellung des wertebereichs
                y2label: 'Temperatur/e (°C)<br>blau/blue',
                series : {
                  'Temperatur': {
                        axis: 'y2'
                  },
                  },
                  axes: {
                  y2: {
                    // set axis-related properties here
                    labelsKMB: true,
                    drawGrid: true,
                    independentTicks: true,
                    gridLinePattern: [2,2]
                    }
                },
                xlabel: 'Datum/Uhrzeit',
                digitsAfterDecimal: '3'
            } 
        );
      g2.setAnnotations([            // Ab hier folgen die Anmerkungen
        { series: 'Gewicht',
          x: Date.parse('2014/06/19 22:05:03'),
          shortText: '01',
          text: 'Ab hier lag eine Weile das Lötkolbenkabel über den Waagfuß.' },
        { series: 'Gewicht',
          x: Date.parse('2014/06/19 22:45:03'),
          shortText: '02',
          text: 'Hier hab ichs dann gemerkt.' },
        { series: 'Gewicht',
          x: Date.parse('2014/06/20 11:06:03'),
          shortText: '03',
          text: 'Belastung jetzt: halber Tisch, Schuhkiste, zwei alte Schlepptopps.' }
        ]);
    </script>
    <br>
    Aktualisierung: Alle 5 Minuten kommt der aktuelle Wert automatisch zur <a href="sensorik.csv">Datenbasis</a> hinzu. Zum Aktualisieren der Kurve den Reload-Button des Browsers klicken oder die Tastenkombination Strg/Cmd+"r"!<br>
    Update: The <a href="sensorik.csv">database</a> is automatically updated every 5 minutes. To update the chart, click the update button of your browser or the reload hotkey, commonly string/cmd+r!
    <br><br>
    Bedienung:<br>
    Zoom: Klicken-Halten-Ziehen, Schieben: SHIFT-Klick-Ziehen, Reset: Doppelklick 
    <br><br>
    Usage:<br>
    Zoom: click-drag, Pan: shift-click-drag, Restore: double-click
    <p><a href="https://www.euse.de/wp/blog/2014/06/bienenwaage-testbetrieb/">Wie das im einzelnen funktioniert</a> und mehr im Projektblog unter <a href="https://www.euse.de/wp/blog/series/bienenwaage/">"Bienenwaage"</a>.
    <p>Find out <a href="https://www.euse.de/wp/blog/2014/06/bienenwaage-testbetrieb/">how this is done</a> and more in the bee scale's project blog filed under <a href="https://www.euse.de/wp/blog/series/bienenwaage/">"Bienenwaage"</a> (sorry, only in German).
    <p><br><br><center><small><a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons Lizenzvertrag" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/80x15.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Bienenstockwaage graph.htm</span> von <a xmlns:cc="http://creativecommons.org/ns#" href="http://www.euse.de" property="cc:attributionName" rel="cc:attributionURL">mois</a> ist lizenziert unter einer <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Namensnennung-<br>Nicht-kommerziell-Weitergabe unter gleichen Bedingungen 4.0 International Lizenz</a>.<br>
    <span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Bee Hive Scale graph.htm</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="http://www.euse.de" property="cc:attributionName" rel="cc:attributionURL">mois</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-<br>NonCommercial-ShareAlike 4.0 International License</a>.
    <p>Kurvendarstellung durch <a href="http://dygraphs.com/">dygraphs</a> Javascript-Charting-Bibliothek.<br>Chart rendered by <a href="http://dygraphs.com/">dygraphs</a> javascript charting library.
    </small></center>
    </article>
</body>
</html>

Das ganze sieht dann online so aus.

Die Kurvendarstellung läßt sich layouten, indem man dygraphs per Optionen Formatierungsanweisungen übergibt. Das ganze ist gut dokumentiert, vor allem mit Beispielen, aus denen man sich dann alles brauchbare zusammenklauben kann. Ich habe viel mit den verschiedenen Interaktionsmöglichkeiten experimentiert, mir alle Beispiele angeguckt. Mit dem Online-Editor hab ich gar nicht gearbeitet.

Flatfile-Datenbank aufsetzen

Eine Flatfile-Datenbank ist eine Textdatei, in der die Datensätze Zeile für Zeile abgelegt werden. Das Format dieser Sorte Datenbank richtet sich nach dem Gegenüber, das mit der Datenbank kommunizieren will. Daher folgt meine Textdatei den Formathinweisen von dygraphs. Ich nenne die Datei „sensorik.csv„, und sie sieht so aus:

 Date,Kiste1,GradC
 2014/06/19 21:14:45,10.990,21.0        # comments are OK on data lines
 2014/06/19 21:14:45,10.990,23.0
 2014/06/19 21:15:03,11.005,23.0
 2014/06/19 21:20:02,10.993,23.0
 ...

Windowsbenutzer aufpassen mit den (unsichtbaren) Markierungen des Zeilenendes!

per php-script zeitstempel und sensorwerte an .csv anhängen

Auch das PHP-Skript „add_line2.php“ landet in diesem Verzeichnis:

  <?php
  #datei mit datenreihe oeffnen
  # Bee Hive Scale add_line2.php von mois ist lizenziert unter einer Creative Commons Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 4.0 International Lizenz.
  # Bee Hive Scale add_line2.php by mois is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
  $datei = fopen("sensorik.csv","a+") or die("Kann die Datei nicht aufmachen.");    
  // letzte zeile einlesen
  $oldlines = @file("sensorik.csv");
  $oldline = (count($oldlines)) ? $oldlines[count($oldlines)-1] : NULL;
  $oldkiste1 = substr($oldline, 20, -5);      #letztes gewicht einlesen
  $oldtemp = substr($oldline, 27, 4);    
  $date = date('Y/m/d H:i:s');                 #serverzeitstempel abgreifen
  # echo $date,","; 
  $kiste1 = $_GET["kiste1"];                    #variable aus der url einlesen
  $temp = $_GET["temp"];
  # $kiste2 = $_GET["kiste2"];
  # $line = "\n".$date.",".$kiste1.",".$kiste2;    #datensatz zusammenstellen
  $line = "\n".$date.",".$kiste1.",".$temp;
  $alt_line = "\n".$date.",".$kiste1.",".$oldtemp; #alternative falls temp=0.0
      #datensatz an datenreihe anfuegen...
  $diff = abs($kiste1-$oldkiste1);        # gewichtsdifferenz letzte mess.
        // ist die gewichtsdifferenz zwischen zwei benachbarten messungen
        // kleiner als 2kg, dann wird die messung als gueltig akzeptiert...
  if ($diff < 2)
  {  if($temp != 0.0)                            #...wenn ein Temperaturwert ex.
    {  fwrite($datei, $line);            #...und gespeichert.
       echo "<p>Folgende Werte wurden in die Datenbank aufgenommen: ",$date,", ",$kiste1,"kg, ",$temp," Grad C";
    }            
    else  #damit nicht wg. falscher temp-messung der gewichtswert verloren geht
    {  fwrite($datei, $alt_line); 
       echo "<p>Folgende Werte wurden in die Datenbank aufgenommen: ",$date,", ",$kiste1,"kg, ",$oldtemp," Grad C";        
    }                        
  }
  else { echo $kiste1," kg!? Ist irgendein Vieh auf die Kiste gesprungen - oder runter?<br>(Die Gewichtsdifferenz gegenüber der letzten Messung ist größer als erwartet, daher wird nichts in die Datenbank geschrieben.)"; }
  fclose($datei);                                #datei mit datenreihe schliessen
  #messung nach $intervall sekunden wiederholen:
  $intervall = "120";
  $arduinoserver = "wbk.in-butter.de";            #dyndns-adresse
//  $arduinoserver = "192.168.178.177";                #lan-adresse
//  echo "<meta http-equiv=\"refresh\" content=\"",$intervall,"; URL=http://",$arduinoserver,"\">";
//  echo "<p>Folgende Werte wurden in die Datenbank aufgenommen: ",$date,", ",$kiste1,"kg, ",$temp," Grad C";
//  echo "<p><small>Solange diese Seite im Browser offen ist, erfolgt alle ",$intervall," Sekunden eine neue Messung.</small>";
  echo "<p><a href=graph.htm target=new>Zur Kurve</a>";
//  echo "<p>",$oldline;        #debug
//  echo "<p>Letzte Wägung: ",$oldkiste1," kg";        #debug
//  echo "<p>Diese Wägung: ",$kiste1," kg";             #debug
//  echo "<p>Differenz zwischen den beiden letzten Messungen: ",$diff," kg";    #debug
//  echo "<p>Letzte Temperaturmessung: ",$oldtemp,"°C";    #debug
//  echo "<p>Diese Temperaturmessung: ",$temp,"°C";        #debug
?>

Da ich eigentlich gar kein PHP kann und diese Datei aber from the scratch selbst zusammenstoppeln musste, war ich dankbar für das übersichtlich dargebotene, deutschsprachige PHP-EinsteigerInnenkompendium bei schattenbaum.net.

Ardunino von außen erreichbar machen:

Zuerst bei einem dyndns-Anbieter anmelden. in-berlin.de bietet mir das glücklicherweise als Mitglied an.
https://service.in-berlin.de/intern/en/config.cgi?command=dyndns
Die dyndns-Daten dann im eigenen Router/Fritzbox einrichten:
https://wiki.in-berlin.de/dyndns_fritzbox

Der damit unabhängig von wechselnden IP-Adressen feste Link durchs Internet auf den Arduino lautet dann in meinem Fall:
http://wbk.in-butter.de

Jetzt muss noch im Router/Fritzbox eine Portweiterleitung eingerichtet werden, damit Anfragen aus dem Internet auch auf den Arduino weitergeleitet werden. Zuletzt musste ich noch beim Noscript-Plugin meines Browsers im ABE-Modul eine Ausnahme für Arduino einrichten, stackoverflow zeigt wies geht (Noscript spielt selbstverständlich keine Rolle, wenn der Sketch auf dem Arduino lediglich durch den cronjob mit lynx aufgerufen werden soll).

Werte regelmäßig per chronjob erfassen

Als Sackgasse hat sich cronjob.de erwiesen. Die führen keine Weiterleitungen und auch nichts Sonstiges aus, was nach Code aussieht. Ein glück erlaubt in-berlin.de seinen Mitgliedern, selbst cronjobs anzulegen. Dass passiert per shell (in-berlin-Hilfe zum Shell-Zugang, es braucht login&webpasswort) direkt auf dem Webserver.

Dort öffnet crontab -e die Liste der cronjobs in einem Editor namens vi. Die 3 verschiedenen, auf den ersten Blick nicht unterscheidbaren Arbeitsmodi dieses Editors machen die Arbeit mit ihm etwas gewöhnungsbedürftig. Es lohnt sich aber, sich da reinzudenken, da man ihm auf der Konsole hin und wieder begegnet und sich dann weniger ärgert.

Also: Mit „i“ in den Eingabemodus. Dort eine Zeile mit dem neuen cronjob ergänzen, z.b. für alle 5 minuten. Die Zeile in der crontab sieht dann so aus:

 */5 * * * * lynx -cmd_script=lynxlog.txt http://wbk.in-butter.de

Mit <ESC> gehts dann in den Befehlsmodus zurück, von dort mit „:“ weiter in den Kommandozeilenmodus. „wq“ und <return> schließen die Prozedur dann ab (wq = write&quit).

Da der Konsolenbrowser lynx der Weiterleitung auf der vom Arduino bereitgestellten Webseite nicht automatisch folgt, müssen wir ihn dazu zwingen. Das geschieht, indem lynx die notwendige Tastatureingabe (Strg+j) per Option -cmd_script=lynxlog.txt überreicht bekommt (wen es genauer interessiert, der oder die lese in den lynx-Man-Pages nach). Bei der Gelegenheit können wir lynx auch gleich ordentlich beenden (q=quit und y=yes, I really want to quit). Zurück auf der Konsole lässt sich diese Datei „lynxlog.txt“ mit der Kommandozeilenanweisung

lynx -cmd_log=lynxlog.txt http://wbk.in-butter.de

automatisch erstellen. Oder eben folgenden Text in einer Textdatei mit Namen „lynxlog.txt“ ablegen (Arg2 entsprechend anpassen!):

 # Command logfile created by Lynx 2.8.8dev.12 (22 Feb 2012)
 # Arg0 = lynx
 # Arg1 = -cmd_log=lynxlog.txt
 # Arg2 = http://wbk.in-butter.de
 key ^J
 key q
 key y

Hinweis: Nach einer Änderung des in der crontab gesetzten Zeitintervalls muss dieser neue Wert manuell an zwei Stellen in der Kurvendarstellungsdatei (graph.php) geändert werden: 1. als Wert der Variable $intervall in Zeile 19 und 2. im erklärenden Text (Zeilen 105 und 106).

Mir haben in diesem Zusammenhang geholfen:
https://help.ubuntu.com/community/CronHowto
http://itler.net/internetseite-ueber-cronjob-aufrufen-linux-server/
http://www.ubuntu-forum.de/artikel/53169/webseite-%C3%BCber-konsole-als-cronjob-aufrufen.html#post311687

Arduino-Sketch

Zum Schluss noch das erweiterte Arduino-Skript:

/*
 Open Bee Hive Scale
 2014-06 by mois
 Dieser Sketch von mois ist lizensiert unter einer Creative Commons Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 4.0 International Lizenz.
 This code by mois is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 */
// load cell characteristic
 // define here individual values for used load cell type
 //
 // - 11994383 sensor value for "0 kg"
 //   write down the sensor value of the scale with no load and adjust it
 here
 // - 6016676 is the value for a 1 kg weight load
 //   add a load with known weight in kg to the ceall, note the sesor
 value, calculate
 //   the value for a 1 kg load and adjust it here
 long loadCellZeroOffset = 6800000;
 long loadCellKgDivider = 6016676;
// Libraries
 #include <ADS1231.h>
 ADS1231 loadCell;  // create ADS1231 object
 long weightSensorValue;
 float weightKg;
 boolean weightKgTrusted = false;
#include <RunningMedian.h>
 // RunningMedian sample size is 11
 RunningMedian weightSamples = RunningMedian(11);  // create
 RunningMedian object
#include <SPI.h>
 #include <Ethernet.h>
 byte mac[] = {
 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
 IPAddress ip(192,168,178,177);
 EthernetServer server(80);
#include <OneWire.h>
 int pin_number = 2; //DS18S20 Signal pin on digital 2
 OneWire ds(pin_number);
 float temp;
// debug
 long outputLines = 0;
void setup() {
 // initialize serial communication
 Serial.begin(9600);
 // load cell / ADS1231 pin definition: SCL 8, Data 5, PowerDown 9
 loadCell.attach(8,5,9);
 // start the Ethernet connection and the server:
 Ethernet.begin(mac, ip);
 server.begin();
 Serial.print("server is at ");
 Serial.println(Ethernet.localIP());
 }
void loop() {
 temp = getTemperature();
 // ADS1231 ready?
 if (loadCell.check()) {
 delay(1000);
 // read input of ADS1231:
 weightSensorValue = loadCell.readData();
 // calculate weight in kg
 weightKg =1 {
 weightKgTrusted = true;
 }
// print out the weight sensor data and calculated kg
// print header every 20 lines
 if (outputLines % 20 == 0) {
 Serial.println();
 Serial.println("sensor \t\tkg \tGrad C");
 }
 Serial.print(weightSensorValue);
 Serial.print("\t");
 Serial.print(weightKg, 3);
 Serial.print("\t");
 Serial.println(temp, 1);
 //delay(100);
// clear RunningMedian samples array all 35 lines
 if (outputLines % 35 == 0) {
 weightSamples.clear();
 weightKgTrusted = false;
 }
outputLines ++;
// listen for incoming clients
 EthernetClient client = server.available();
 if (client) {
 // an http request ends with a blank line
 boolean currentLineIsBlank = true;
 while (client.connected()) {
 if (client.available()) {
 char c = client.read();
 //  Serial.write(c);
 // if you've gotten to the end of the line (received a newline
 // character) and the line is blank, the http request has ended,
 // so you can send a reply
 if (c == '\n' && currentLineIsBlank) {
 // send a standard http response header
 client.println("HTTP/1.1 200 OK");
 client.println("Content-Type: text/html");
 client.println("Connection: close");  // the connection will
 be closed after completion of the response
 client.println("Refresh: 60");  // refresh the page automatically
 every 60 sec
 client.println();
 client.println("<!DOCTYPE HTML>");
 client.println("<html>");
 //            client.print("<meta http-equiv=\"refresh\"
 content=\"0;URL=http://192.168.178.57/beescale/add_line2.php?kiste1=");
 client.print("<meta http-equiv=\"refresh\"
 content=\"0;URL=http://www.euse.de/honig/beescale/add_line2.php?kiste1=");
 client.print(weightKg, 3);
 client.print("&temp=");
 client.print(temp, 1);
 client.println("\"); ?>");
 client.println("</html>");
 break;
 }
 if (c == '\n') {
 // you're starting a new line
 currentLineIsBlank = true;
 }
 else if (c != '\r') {
 // you've gotten a character on the current line
 currentLineIsBlank = false;
 }
 }
 }
 // give the web browser time to receive the data
 delay(1);
 // close the connection:
 client.stop();
 }
 }
 }
#define DS18S20_ID 0x10
 #define DS18B20_ID 0x28
 boolean getTemperature(){
 byte i;
 byte present = 0;
 byte data[12];
 byte addr[8];
 //find a device
 if (!ds.search(addr)) {
 ds.reset_search();
 return false;
 }
 if (OneWire::crc8( addr, 7) != addr[7]) {
 return false;
 }
 if (addr[0] != DS18S20_ID && addr[0] != DS18B20_ID) {
 return false;
 }
 ds.reset();
 ds.select(addr);
 // Start conversion
 ds.write(0x44, 1);
 // Wait some time...
 delay(850);
 present = ds.reset();
 ds.select(addr);
 // Issue Read scratchpad command
 ds.write(0xBE);
 // Receive 9 bytes
 for ( i = 0; i < 9; i++) {
 data[i] = ds.read();
 }
 // Calculate temperature value
 temp = ( (data[1] << 8) + data[0] )*0.0625;
 return temp;
 }

Den Temperatursensor habe ich mit Hilfe von tushev.org eingebunden.

Wie weiter? Siehe aktualisierte Todo-Seite!

Änderungsprotokoll

7.11.2015
Stoßdämpfer angebaut

12.5.2015
Varroaschublade untergelegt

4.7.2014
Datenübertragung wireless vom Arduino an die Fritzbox

 

Series Navigation<< Durchbruch BienenwaageBienenstockwaage jetzt stabil wireless >>
  1. float)weightSensorValue - loadCellZeroOffset) / loadCellKgDivider; // add data to runnig median sample weightSamples.add(weightKg); // complete sample? if (weightSamples.getCount() == weightSamples.getSize( []

2 Gedanken zu „Bienenwaage: Prototyp im Testlauf (Bauanleitung)“

  1. Statt des Raspi würde ich einen Arduino Yun verwenden, damit kannst du das Skript weiterverwendne, das die Daten einliest aber gleichzeitig den Yun als Webserver nutzen. Einziger Nachteil: Mit dem Linux und Wifi ist wohl ein Batteriebetrieb nur bedingt möglich.

    Weiter würde ich überlegen, ob ich den Arduino tatsächlich vom Server aus auslesen lasse (pull) und nicht umgekehrt: Der Arduino ruft ein Skript auf dem Server auf und übergibt dort die Werte per http request (push). Würde dynDNS und cronjobs überflüssig machen und den ganzen Aufwand deutlich reduzieren, s. etwa http://jleopold.de/2011/03/16/arduino-daten-logger-mysql-php/

  2. Hallo,
    ich bin zufällig auf deinen Seite zum Thema Bienenwaage gestoßen. Ich bin ebenfalls Imker und finde dein Projekt äußerst interessant. Hast du auch eine detaillierte Bauanleitung zu deiner Waage? Wäre dir sehr dankbar.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert