Project in progress
TCP/IP Multisensor

TCP/IP Multisensor © MIT

Arduino based sensor that communicates over TCP/IP. Can be used stand-alone or part of a Raspberry based data logger with a web UI.

  • 3,167 views
  • 2 comments
  • 7 respects

Components and supplies

Abx00014 featured xjsqphgdlv
Arduino MKR Fox 1200
Works as the sensor
×1
Pi 3 02
Raspberry Pi 3 Model B
Provides database for results and web UI to read them.
×1

Necessary tools and machines

Seeed PCB Prototyping
09507 01
Soldering iron (generic)
3drag
3D Printer (generic)

Apps and online services

About this project

Scope

This is a project for creating a sensor (or a sensor interface for commercial sensors) for a Raspberry Pi based data logger, which can also be used as a stand-alone sensor. Project will be based on MKRFOX 1200. The sensor will deliver the measurement result over TCP/IP and it can be read with a GET/POST message directly or by using a standard web browser, for which it delivers the required metadata. This way the measurement result can be accessed through SigFox or embedded on any website.

Current prototype uses Arduino Nano and all the code and HW needs to be updated to use MKRFOX 1200.

Details on the sensor

The sensor has interfaces for 0 - 10 V, 0 - 20 mA analog measurements as well as serial, I2C and 1-wire digital interfaces. Multiple interfaces can be used at once by selecting which port to read over TCP/IP.

The purpose is to connect a commercial sensor that provides the measurement result in one of the forms mentioned earlier and make that result available through web or a local network.

First prototype is using a wired connection. The next prototype will implement MKR 1200 for a wireless connection and more program memory. Also a flash storage is needed and preferrably the wired connection would be left as an option.

Purpose

Goal is to create a sensor platform that can be used to connect a wide range of commercial sensors to a TCP/IP based sensor network or to communicate over the web. Application vary from industrial to personal measurements.

Same platform can be used at either for real time measurements or together with a data logger to keep record of measurements over time.

Prototype 1

First prototype of the sensor uses the ethernet shield and is mounted on a custom PCBA.

Image 1 displays the prototype measuring temperature and humidity with the DHT22 -sensor. Measurements are pre-amplified and filtered for high frequency noise as well as 50 or 60 Hz noise, depending on the mains frequency of country of application. Also an overvoltage and polarity protection is supplied.

Debugging can be done via serial port or viewing the debugging LEDs. Reliable quick connects allow easy installation. Fits in a standard Arduino-enclosure.

Applications

  • Measure humidity over the seasons to ensure a healthy environment to live in.
  • Measure humidity and temperature and control accordingly to prevent structural damage. Optimize temperature control to save energy.
  • Connect sensors in the factory network to be able to display real time diagnostics data, without the need to connect them to logic control system.
  • Connect to a remote measurement sub-network site using mobile 3G connection by creating the network with standard components.
  • Use your company preferred method of VPN/SSH connection for security.

Datalogger (From an earlier project)

To make full use of the sensors capabilities, the result should be stored in a database. Raspberry Pi will service as a data logger with a web interface for the results database.

The web interface can be accessed with all modern browsers from any device. You can configure sensors and measurements through the UI and manage the measurement results.

Story

We are doing to project as a "garage"-project, but with proper equipment. We have good hand soldering equipment and professional soldering microscope, CNC milling machine, electronics measurement equipment etc, that might not be available for every hobbyist.

We work in similar field professionally too and have studied mainly electronics.

We try to focus on one main project and run a smaller side and maintenance project simultaneously, as well as doing research for next projects.

Code

MainArduino
Base sensor functions. Uses several custom header files and public libraries.
#include <SPI.h>
#include <SD.h>
#include <Ethernet.h>
#include "ardu_sensor_init.h"
#include "ardu_eth_functions.h"
#include "ardu_sensor_functions.h"

/* Define debugging level */

#define DEBUG_LEVEL 1

const int _post_interval = 5000;

/***********************************************************************************************************************/
/*                                            Arduino pin definitions                                                  */
/***********************************************************************************************************************/

const int red_led_pin = 5;          //
const int green_led_pin = 6;        //
const int blue_led_pin = 9;         //

/***********************************************************************************************************************/
/*                                                   FUNCTIONS                                                         */
/***********************************************************************************************************************/



/***********************************************************************************************************************/
/*                                                   VARIABLES                                                         */
/***********************************************************************************************************************/

/* Debugging */

long _last_post_time = 0;

/* Serial port variables */


/* Ethernet variables */

byte mac[] = { 0xAE, 0xA5, 0xBE, 0xE6, 0xF6, 0x7E };
byte ip[] = { 192, 168, 1, 190 };

/* Sensor variables */

DHT_Unified dht(DHTPIN, DHTTYPE);
sensor_t sensor;
uint32_t delayMS;

EthernetServer server[4] = { EthernetServer(80),    // 0 - 20 mA sensor
                             EthernetServer(81),    // 0 - 10 V sensor
                             EthernetServer(82),    // DHT21 humidity sensor (AM2302 etc)
                             EthernetServer(83) };  // DHT21 temperature sensor (AM2302 etc)

/***********************************************************************************************************************/
/*                                                   SETUP LOOP                                                        */
/***********************************************************************************************************************/

void setup() {

  /* Pin settings */

  // Ethernet chip select
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);

  // LED configurations
  pinMode(red_led_pin, OUTPUT);
  digitalWrite(red_led_pin, LOW);

  pinMode(green_led_pin, OUTPUT);
  digitalWrite(green_led_pin, HIGH);

  pinMode(blue_led_pin, OUTPUT);
  digitalWrite(blue_led_pin, HIGH);
  
  /* Serial communications setup */
  
  ard_sensor_begin_serial(SERIAL_BAUD_RATE);
  
  /* Ethernet initialization */

  Ethernet.begin(mac, ip);

  for(int i = 0; i < (sizeof(server) / sizeof(server[0])); i++){
    server[i].begin(); 
  }
  
  /* Sensor init */

  // Analog in
  analogReference(EXTERNAL);

  // DHT
  dht.begin();
  dht.temperature().getSensor(&sensor);
  dht.humidity().getSensor(&sensor);
  delayMS = sensor.min_delay / 1000;

  /* Setup complete */

  digitalWrite(red_led_pin, HIGH);
  digitalWrite(green_led_pin, LOW);
  delay(300);
  digitalWrite(green_led_pin, HIGH);
  
}

/***********************************************************************************************************************/
/*                                                   MAIN LOOP                                                         */
/***********************************************************************************************************************/

void loop() {
  
  char clientline[_CLIENTLINE_BUFSIZ];  
  

  for(int i = 0; i < (sizeof(server) / sizeof(server[0])); i++){

  EthernetClient client = server[i].available();

  if(client) {

    while(client.available()) 
    {
        Serial.println("Client connecting...");
        digitalWrite(blue_led_pin, LOW);
        read_clientline(&client, clientline, i);
        
        digitalWrite(blue_led_pin, HIGH);
        client.flush();
    } // while(client.available())
    delay(5);
    client.stop();
    server[i].begin();
    
  } // if(client)

  } // for(int i = 0; i < (sizeof(server) / sizeof(server[0])); i++)

#if DEBUG_LEVEL > 0
  if(_last_post_time + _post_interval < millis())
  {
    Serial.println(Ethernet.localIP());
    Serial.print(mac[0], HEX);
    Serial.print(" ");
    Serial.print(mac[1], HEX);
    Serial.print(" ");
    Serial.print(mac[2], HEX);
    Serial.print(" ");
    Serial.print(mac[3], HEX);
    Serial.print(" ");
    Serial.print(mac[4], HEX);
    Serial.print(" ");
    Serial.println(mac[5], HEX);
    Serial.println(String(ard_sensor_read_voltage()));
    Serial.println(String(ard_sensor_read_current()));
    Serial.println(String(ard_sensor_read_humid()));
    Serial.println(String(ard_sensor_read_temp()));
    _last_post_time = millis();
  }
#endif

} // void loop()
ardu_eth_functions.cppArduino
Custom
#include "ardu_eth_functions.h"
#include "ardu_sensor_functions.h"

#define DEBUG_LEVEL 1

void read_clientline(EthernetClient *_client, char *clientline, int _sensortype)
{
  
  clientline[0] = '\0';
  
  //int client_line_index = 0;

#if DEBUG_LEVEL > 2
    Serial.println("Reading client line");
#endif

  while (_client->available())
  {
    int client_line_index = 0;

    bool line_feed = false;
    bool empty_line = true;
    
    while (_client->available() && !line_feed) {
      clientline[client_line_index] = _client->read();

      if (clientline[client_line_index] == '\n' || clientline[client_line_index] == '\r')
      {
        line_feed = true;
        if (empty_line) 
        {
#if DEBUG_LEVEL > 1
            Serial.println("***EMPTY LINE***");
#endif          
        } else
        {
          clientline[client_line_index] = '\0';
#if DEBUG_LEVEL > 1
            Serial.println(clientline);      
#endif
          if (strstr(clientline, "GET /"))
          {
            parse_ethernet_client_command(_client, &clientline[5], _sensortype);  
          } else if (strstr(clientline, "POST /"))
          {
            parse_ethernet_client_command(_client, &clientline[6], _sensortype);  
          }
          delay(2); // give client time to receive data   
        }
      } else 
      {
        empty_line = false;
      }
      
      if(client_line_index < _CLIENTLINE_BUFSIZ - 1) // toss out data if line is too long for buffer
      {
        client_line_index++;
      }
    }
  }
}

void parse_ethernet_client_command(EthernetClient *_client, char *_clientline, int _sensortype){

#if DEBUG_LEVEL > 1
    Serial.print("Parse cmd: ");
    Serial.println(_clientline);
#endif
  
  if (_clientline[0] == ' ') 
  {  //response to web browsers with empty request
#if DEBUG_LEVEL > 0
    Serial.println("GET request");
#endif    
    // send a standard http response header
    _client->println("HTTP/1.1 200 OK");
    _client->println("Content-Type: text");
    _client->println();
    // actual payload
    sensor_result(_client, _sensortype);

  } else if (strstr(_clientline, "? ") != 0) 
  { //normal usage
#if DEBUG_LEVEL > 0
    Serial.println("Sensor read");
#endif

    sensor_result(_client, _sensortype);
       
  } 
#if DEBUG_LEVEL > 0  
  else{
    Serial.print("INVALID: ");
    Serial.println(_clientline);  
  }
#endif
}

void sensor_result(EthernetClient *_client, int _sensortype){

    if (_sensortype == 0)
    {
      _client->println(String(ard_sensor_read_current()));
    } else if (_sensortype == 1)
    {
      _client->println(String(ard_sensor_read_voltage()));
    } else if (_sensortype == 2)
    {
      _client->println(String(ard_sensor_read_humid()));
    } else if (_sensortype == 3)
    {
      _client->println(String(ard_sensor_read_temp()));
    }
    
}
ardu_sensor_functions.hArduino
#pragma once

#include <Arduino.h>
#include <SPI.h>
#include <Ethernet.h>
#include "ardu_sensor_init.h"

void read_clientline(EthernetClient *_client, char *clientline, int _sensortype); 
void parse_ethernet_client_command(EthernetClient *_client, char *_clientline, int _sensortype);
void sensor_result(EthernetClient *_client, int _sensortype);
ardu_eth_sensor_functions.cppArduino
Custom
#include "ardu_sensor_functions.h"
#include <Arduino.h>

#define ENABLE_50HZ_FILTER 1

#define DEBUG_LEVEL 0

// Arduino ADC sampling time is 10 us and conversion time 100 us

double ard_sensor_read_current()  // 4 - 20 mA sensor
{
  double _result = 77.77;
  
  _result = (double)analogRead(A0) / 1024 * 3.0 / 0.120;                  

#if ENABLE_50HZ_FILTER
  _result += (double)analogRead(A0) / 1024 * 3.0 / 0.120;
  _result /= 2;
#endif

#if DEBUG_LEVEL
  Serial.print("RETURNING: ");
  Serial.println(_result);
#endif
  
  return _result;
}

double ard_sensor_read_voltage()  // 0 - 10 V sensor
{
  double _result = 77.77;
  
  _result = (double)analogRead(A0) / 1024.0 * 3.000000 * 44.0 / 11.0;     
  
#if ENABLE_50HZ_FILTER
  _result += (double)analogRead(A0) / 1024.0 * 3.000000 * 44.0 / 11.0;
  _result /= 2;
#endif

#if DEBUG_LEVEL
  Serial.print("RETURNING: ");
  Serial.println(_result);
#endif

  return _result;
}

double ard_sensor_read_humid()  // DHT humidity reading
{
  double _result = 77.77;

  sensors_event_t event;
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println("Error reading humidity!");
    return 0;
  }
  else {
#if DEBUG_LEVEL > 0    
    Serial.print("RETURNING: ");
    Serial.println(event.relative_humidity);
#endif    
    return (double)event.relative_humidity;
  }
}

double ard_sensor_read_temp()  // DHT temperature reading
{
  double _result = 77.77;

  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(isnan(event.temperature))) {
    Serial.println("Error reading temperature!");
    return 0;
  }
  else {
#if DEBUG_LEVEL > 0    
    Serial.print("RETURNING: ");
    Serial.println(event.temperature);
#endif    
    return (double)event.temperature;
  }
}
ardu_sensor_functions.hArduino
Custom
#pragma once

#include <Arduino.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include "ardu_sensor_init.h"

double ard_sensor_read_current();
double ard_sensor_read_voltage();
double ard_sensor_read_humid();
double ard_sensor_read_temp();
ardu_sensor_init.cppArduino
Custom
#include "ardu_sensor_init.h"

#define DEBUG_LEVEL 2

void ard_sensor_begin_serial(unsigned long _serial_baud_rate)
{

  Serial.begin(_serial_baud_rate);

  while(!Serial){
    ;                                                       // Only needed for Leonardo board
  }  

#if DEBUG_LEVEL > 1
  Serial.println("Serial port opened");
  Serial.print("Serial baud rate: ");
  Serial.print(_serial_baud_rate);
  Serial.println(" bit/s");
#endif
  
}
ardu_sensor_init.hArduino
Custom
#pragma once

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
#include <Ethernet.h>

/* DHT sensor type definitions */
#define DHTPIN            7         // Pin which is connected to the DHT sensor.
#define DHTTYPE           DHT21     // DHT 21 (AM2301)

const unsigned long SERIAL_BAUD_RATE = 115200;
const unsigned int _CLIENTLINE_BUFSIZ = 64;

/* Define sensor type */

extern DHT_Unified dht;
extern sensor_t sensor;
extern uint32_t delayMS;

void ard_sensor_begin_serial(unsigned long _serial_baud_rate); 

Schematics

Schematic
Existing schematic that needs to be updated to MKR 1200

Comments

Similar projects you might like

Carfox: A Device to Find Them All

Project tutorial by Luis Roda Sánchez

  • 6,490 views
  • 2 comments
  • 28 respects

Eco-Thing #1 "Eco-Smart-Container V1.0"

Project tutorial by Alexis Santiago Allende

  • 5,305 views
  • 4 comments
  • 28 respects

IoT Santa Tracker on Colorful World Map

Project tutorial by Bowen Feng

  • 1,228 views
  • 0 comments
  • 2 respects

Remote System Monitor

Project tutorial by Stephen Harrison

  • 7,344 views
  • 1 comment
  • 24 respects

The Fireman is never late again !!!

Project in progress by Team FrostedFocus

  • 5,645 views
  • 6 comments
  • 21 respects
Add projectSign up / Login