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