Datalogging with Arduino over HAMNET

Aus DL8RDS Wiki
Wechseln zu: Navigation, Suche

1 Scope

This project is the master project and the preliminary endpoint of several other projects:

And it issued from the question how we can monitor the ATV relay DB0MHB over a long period and log all the activity as well as environmental data such as weather etc. In fact is it not so easy to implement datalogging if a relay project has been exclusively analog up to now (except for the controller).

2 Architecture

  • The first goal was the HAMNET connectivity. Without a data transport capability it would only have been possible to log data on-site, but we wanted to provide permanent and instant insights in the relay's status. So data connectivity was to be the first goal. We reached that by connecting DB0MHB and DB0BUL.
  • The second goal was to record the voltage of various station components and battery systems and provide the data over the network. We implemented this with an Arduino in combination with the Ethernet Shield.
  • The third goal was to create a CSV file out of the minutely data readings. The goal was reached by a simple perl script.
  • The fourth goal was to evaluate the CSV file with the charting package GNUPlot. We are using it to turn the CSV file into charts wo make the recent week(s) understandable in a chart.
  • The fifth goal was to present these pictures overa network for browser-enabled clients. This was done with a small Linux machine and the Apache web server.

3 Implementation of the Sensor Server

The sensor server is a standard Arduino Duemillanove with a recent Ethernet Shield:

ArduinoDuemillanove.jpg ArduinoEthernetShield.jpg

These two in combination make up the hardware for a Webserver that consumes only 1,3 Watts input. The trick is the WizNet 5100 chip on the Ethernet shield that implements everything up to the TCP protocol. The microcontroller can thus concentrate on the essential activities: Grab the data, prepare the web site and send it to the chip. Here's the chip's datasheet:

Since Arduino can handle the I2C protocol, I attached a LM75 temperature sensor and a high precision Analog Digital Converter from Gravitech to the BUS:

Here's some more pictures:

SensorServer1.jpg SensorServerExtADC.jpg

Voltage regulation for the 5V devices was done in a very overdimensioned way (as I like it) with a Cosel ZUS 25 1205 DC DC converter:

4 Implementation of the Current Sensor

This device was built by my friend Bernd DJ6PA:


  • LEM HAIS 50P, a DC current transformer
  • a 741 OpAmp
  • some smaller stuff

5 Update 2018

New Arduino Code:

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(44,225,41,6);
IPAddress gateway(44, 225, 41, 1);
IPAddress dnsserver(44, 130, 60, 100);
IPAddress subnet(255, 255, 255, 240);

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);

// variables used for timing
unsigned long	previous_timer;
byte timer100msec;

int thistime = 0;

#define MESSUNGEN 20

int debug = 0;

short einzelmessungen[12][MESSUNGEN];
short averages[12];

short messung_count = 0;
short messindex = 0;
short max_messungen = MESSUNGEN;

short twelvebit(byte i) {
  const int I2C_address = 0x48;  // I2C write address 
  const byte DAT[8] = {
    0x8C,0xCC,0x9C,0xDC,0xAC,0xEC,0xBC,0xFC    };

  byte Adval_High = 0;
  byte Adval_Low = 0;
  int out = 0;
  Adval_High = 0;
  Adval_Low = 0;

  Wire.write(DAT[i]);        // Configure the device to read each CH  

  // Read A/D value
  Wire.requestFrom(I2C_address, 2);
  Adval_High =;   // Receive A/D high byte
  Adval_Low =;    // Receive A/D low byte 

  out = 0;
  out = Adval_High << 8;
  out = out | Adval_Low;
  Serial.println(out, BIN);
  return out;

int tenbit(byte index) {
  int tenout = analogRead(index);
  if (tenout < 30) {
    return 0;
  } else {
    return tenout;

int gettemperature() {
  const int tmpaddress = 0x4C;  // I2C write address 
  const byte value = 0;


  Wire.requestFrom(tmpaddress, 1);
  int temperature = 0;
  if (Wire.available()) {
    temperature =;

  // sensor produziert hohe Werte bei negativen Temperaturen
  if (temperature > 127) {
    temperature = temperature - 256; 

  return temperature;

void setup() {
 // Open serial communications and wait for port to open:
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only

  // I2C Bus

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, dnsserver, subnet);
  Serial.print("server is at ");

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char 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: 5");  // refresh the page automatically every 5 sec
            client.println("<!DOCTYPE HTML>");
            client.println("<body><h3>DB0MHB data readout</h3>\r\n"); 


            client.print("<tr><td>Spannung 1 </td><td><val type=\"onboard\" index=\"0\">");
            client.print(tenbit(0), DEC);

            client.print("<tr><td>Spannung 2 </td><td><val type=\"onboard\" index=\"1\">");
            client.print(tenbit(1), DEC);

            client.print("<tr><td>Spannung 3 </td><td><val type=\"onboard\" index=\"2\">");
            client.print(tenbit(2), DEC);

            client.print("<tr><td>Spannung 4 </td><td><val type=\"onboard\" index=\"3\">");
            client.print(tenbit(3), DEC);

            client.print("<tr><td>I2C ADC Value 1 (0 - 4095)</td><td><val type=\"i2c\" index=\"0\">");
            client.print(twelvebit(0), DEC);

            client.print("<tr><td>I2C ADC Value 2 (0 - 4095)</td><td><val type=\"i2c\" index=\"1\">");
            client.print(twelvebit(1), DEC);

            client.print("<tr><td>I2C ADC Value 3 (0 - 4095)</td><td><val type=\"i2c\" index=\"2\">");
            client.print(twelvebit(2), DEC);

            client.print("<tr><td>I2C ADC Value 4 (0 - 4095)</td><td><val type=\"i2c\" index=\"3\">");
            client.print(twelvebit(3), DEC);

            client.print("<tr><td>I2C ADC Value 5 (0 - 4095)</td><td><val type=\"i2c\" index=\"4\">");
            client.print(twelvebit(4), DEC);

            client.print("<tr><td>I2C ADC Value 6 (0 - 4095): </td><td><val type=\"i2c\" index=\"5\">");
            client.print(twelvebit(5), DEC);

            client.print("<tr><td>I2C ADC Value 7 (0 - 4095): </td><td><val type=\"i2c\" index=\"6\">");
            client.print(twelvebit(6), DEC);

            client.print("<tr><td>I2C ADC Value 8 (0 - 4095): </td><td><val type=\"i2c\" index=\"7\">");
            client.print(twelvebit(7), DEC);

            client.print("<tr><td>Temperature: </td><td><val type=\"temp\">"); 
            client.print(gettemperature(), DEC);




        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
    // close the connection:
    Serial.println("client disonnected");
  } else {
    messindex += 1;
    if (messindex == MESSUNGEN) {
        messindex = 0; 

We kicked out the blue sensors and introduced ACS712 based sensors. Accordingly the connections changed.


  • Port 1 Verbrauchsstrom
  • Port 2 Notstrom Entnahme
  • Port 3 Aggregat Ladestrom
  • Port 4 Solarstrom

Notes for the formulas:

  • Verbrauchsstrom
3,75V <-> 45,5 A
2,46V <-> 0A
3,24V <-> 27A
  • Notstrom Entnahme
5V <-> 5A
2,46V <-> 0A
  • Aggregat Ladestrom:
3,20V <-> 70A
2,46V <-> 0A
  • Solarstrom
5,0V <-> 55A
2,46V <-> 0A

6 Results


... and if you're happy and I have not yet redone it, you can chech the real values here: