Arduino als Uhr

Mit CSharp initialisiert man im Arduino Uhrzeit und Tagesdatum

Noch immer arbeite ich an meinem Fernziel, dem vollautomatisierten Treibhäuschen. Doch aktuell beschäftige ich mich v.a. mit der Überwachung von verschiedenen Sensorwerten. Im folgenden bringe ich nur ein ganz kleines Bruchstück daraus: Noch immer fehlt mir ja eine Realtime Clock, da ich diese Komponente durch unsachgemässe Behandlung zerstört habe. Das hat mich dazu gebracht, mich etwas näher mit dem Thema “Arduino und Zeit” zu beschäftigen. Dabei ist mir klar geworden, dass eine Realtime Clock gar nicht notwendig ist, solange man die Stromversorgung des Arduino nicht unterbricht.

Mit der Library “Time” funktioniert der Arduino nämlich selbst als Uhr. Man muss das Board einzig mit der aktuellen Zeit initialisieren, z.B. über die serielle Schnittstelle. Den Code dazu stelle ich in diesem Artikel vor. Allerdings wird die aktuelle Uhrzeit nicht manuell über die serielle Schnittstelle eingegeben (was zwar möglich, aber nicht sehr genau ist), sondern über CSharp.

Die Übergabe der aktuellen Zeit erfolgt mit einem String genau definierter Länge, bzw. für Arduino mit einem Array of Char. Das CSharp-Programm muss deshalb die Uhrzeit genau so formatieren, wie Arduino sie erwartet. Denken Sie daran, dass ein Array of Char in Arduino immer ein Zeichen zusätzlich für das Endzeichen benötigt. Und arbeiten Sie nicht mit Println, sondern mit Print, denn sonst wird der aufbereitete String um das (oder die) Endzeichen länger!

Der Arduino-Code besteht aus einer abgewandelten Version des Beispielprogramms, das in der Time-Library dabei ist. Ergänzt wurde es um ein paar Zeilen Code, welche die Zeit mit einem String aus der seriellen Schnittstelle auslesen.

Nachtrag am 10.02.2013: Inzwischen gibt es ein Update dieses Projekts mit RTC und Anzeige der Uhrzeit in einem LED-Display.

Projektziel

Arduino mithilfe der Time-Library und der seriellen Schnittstelle mit dem Tagesdatum und der aktuellen Zeit initialisieren, so dass Arduino als Uhr fungiert, und später beliebige Sensorwerte mit Datum und Zeit ergänzt werden können.

Komponenten

Die Dokumentation und der Link zum Download der Time Library finden sich auf dem Arduino Playground.

  • 1 Arduino beliebigen Typs
  • 1 Computer mit installierter Arduino IDE, Time-Library und Entwicklungsumgebung für CSharp (z.B. VS Express)
  • 1 USB-Kabel zur Verbindung von Arduino und PC
  • 1 externe Stromversorgung für den Arduino, z.B. über 1 9V-Batterie mit zugehörigem Kabel

Bestückungsplan

Ein Bestückungsplan entfällt, da es sich um ein reines Codebeispiel handelt. Wichtig ist bei der Verkabelung einzig, dass die Stromversorgung nicht mehr unterbrochen wird, sobald man die Uhrzeit initialisiert hat! Bevor man also den Arduino vom PC abhängt, muss man ihn mit einem externen Netzteil oder mit einer 9V-Batterie mit Strom versorgen.

Code

Das Beispiel enthält zwei Teile: den Arduino-Code und den CSharp-Code.
Zwei wichtige Tipps noch:

  • Man kann nicht gleichzeitig den seriellen Monitor in Arduino geöffnet haben und von CSharp aus die Zeit initialisieren. Deshalb muss man zuerst den seriellen Monitor schliessen, bevor man das CSharp-Programm startet.
  • Ausserdem wird bei den meisten Arduino-Boards die Setup-Routine aufgerufen, wenn man den Serial Monitor startet (Quelle). Also darf man nach der Zeit-Initialisierung den Monitor nicht mehr öffnen, sonst wird die Uhrzeit auf 0 zurückgesetzt.

CSharp-Code

Hier der CSharp-Code, der die aktuelle Zeit an den Arduino schickt:

using System;
using System.IO.Ports;
using System.Configuration;
using ch.ecotronics.arduino.time.Properties;

/*
 * Arduino als Uhr
 * Aktuelle Zeit und Tagesdatum an serielle Schnittstelle senden
 * Autorin: Silvia Rothen, rothen ecotronics, Bern, Switzerland
 * https://blog.ecotronics.ch/wordpress/2012/arduino-als-uhr/
 *
 */
namespace ch.ecotronics.arduino.time {
  class ArduinoTimeSetter {

    static void Main(string[] args) {
      Settings settings = new Settings();
      SerialPort port = new SerialPort(settings.port, 9600);
      DateTime now = DateTime.Now;
      port.Open();
      //die Zeit wird für Arduino passend formatiert
      String arduinoTime = String.Format("{0:HHmmssddMMyyyy}", DateTime.Now);
      Console.WriteLine(arduinoTime);
      //hier wird die Zeit an die serielle Schnittstelle geschickt
      port.Write(arduinoTime);
      while (true) {
        Console.WriteLine("From Arduino " + port.ReadLine());
      }
    }
  }
}

Die serielle Schnittstelle wird übrigens in die Konfigurationsdatei ausgelagert, damit man die serielle Schnittstelle auch auf einen anderen Port hängen kann, ohne das CSharp-Programm neu kompilieren zu müssen.
In App.config steht

<?xml version="1.0"?>
<configuration>
    <configSections>
        <sectionGroup name="applicationSettings" 
          type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="ch.ecotronics.arduino.time.Properties.Settings" 
              type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
              requirePermission="false" />
        </sectionGroup>
    </configSections>
    <startup> 
        
    <supportedRuntime version="v2.0.50727"/></startup>
    <applicationSettings>
        <ch.ecotronics.arduino.time.Properties.Settings>
            <setting name="port" serializeAs="String">
                <value>COM9</value>
            </setting>
        </ch.ecotronics.arduino.time.Properties.Settings>
    </applicationSettings>
</configuration>

Arduino-Code

Und hier der Arduino-Code, der die Zeit einliest:

/*
 * Arduino als Uhr
 * Weiterentwicklung des mit der Time Library mitgelieferten Beispiels
 * Autorin: Silvia Rothen, rothen ecotronics, Bern, Switzerland
 * https://blog.ecotronics.ch/wordpress/2012/arduino-als-uhr/
 *
 */

#include <Time.h>
char incoming[15] = {}; //wegen Endzeichen
int led = 13; 

void setup() {
  Serial.begin(9600);
}

void loop() {
  int i = 0;
 
  //Zeit aus der seriellen Schnittstelle auslesen
  if (Serial.available() > 0) {
    //Array of Char leeren
    memset(incoming, 0, sizeof(incoming));
    //Zeit wird geliefert als HHmmssddMMyyyy, z.B. 23120027112012
    while (Serial.available() > 0 && i < sizeof(incoming) - 1) {
      incoming[i] = Serial.read();
      i++;
      delay(3);
    }
    
    //in Zeit umwandeln
    char hr[3] = {};
    char min[3] = {};
    char sec[3] = {};
    char day[3] = {};
    char month[3] = {};
    char yr[5] = {};
    hr[0] = incoming[0];
    hr[1] = incoming[1];
    min[0] = incoming[2];
    min[1] = incoming[3];
    sec[0] = incoming[4];
    sec[1] = incoming[5];
    day[0] = incoming[6];
    day[1] = incoming[7];
    month[0] = incoming[8];
    month[1] = incoming[9];
    yr[0] = incoming[10];
    yr[1] = incoming[11];
    yr[2] = incoming[12];
    yr[3] = incoming[13];
    setTime(atoi(hr), atoi(min), atoi(sec), 
      atoi(day), atoi(month), atoi(yr));
    Serial.println("!new Time set");
  }
 
  //Zeit anzeigen
  digitalClockDisplay();
  //1 Sekunde warten
  delay(1000);
}

void digitalClockDisplay(){
  // Digitalanzeige der Zeit
  printDigits(hour(), "");
  printDigits(minute(), ":");
  printDigits(second(), ":");
  printDigits(day(), " ");
  printDigits(month(), ".");
  Serial.print(".");
  Serial.print(year());
  Serial.println();
}

void printDigits(int digits, char trennzeichen[2] ){
  // Hilfsfunktion zur Uhrendarstellung: Gibt vorstehenden Doppelpunkt und führende 0 aus
  Serial.print(trennzeichen);
  if(digits < 10) {
    Serial.print('0');
  }
  Serial.print(digits);
}

Demo

Arduino als Uhr

Viel zu sehen gibt es nicht bei diesem Projekt, hier trotzdem ein Screenshot der Uhrzeit, die über die serielle Schnittstelle angezeigt wird.

Comments are closed.