Connecting sensors to the internet using an arduino and a raspberry pi

As part of the PlantBot project, I wanted a way to look at sensor data over the internet. These sensors are moisture, light and pressure. The main one is moisture, the other two were just added in because I had the parts lying around.
Here is a block diagram outlining each of the steps to go from reading the analog sensor values to graphing them on a webpage:

internet-connected-sensor-block-diagram

internet-connected-sensor-block-diagram

Step 1: Reading sensor values with arduino and sending them over UART:

Sensors used:
-LDR
-MPX4115A Pressure Sensor
-Moisture Sensor

I made the moisture sensor using some galvanised nails. First just solder some wires to the top of the nails. Then cover most of the nail with heatshrink, just leaving the tips exposed.

IMG_20160110_152054[1]
IMG_20160110_152033[1]

The arduino nano has a USB-Serial converter on board so it can be plugged directly into the pi via usb and start sending serial data.

Code:

This arduino program waits to receive a serial character from the pi. Once received it will read all of the sensors and send back the sensor values to the pi via uart.

Step 2: Reading sensor values with Python and placing them in a MySQL database:

#!/usr/bin/python

import serial 
import MySQLdb
import time

db = MySQLdb.connect(host="66.147.244.233",    
                     user="wattnoti_user",        
                     passwd="fakepass123", 
                     db="wattnoti_plantbot")        

cur = db.cursor()


port = serial.Serial("/dev/ttyUSB0", baudrate = 9600,timeout=None)
port.flushInput()	   

PressureVal = 0;
MoistureVal = 0;
LightVal = 0;

vals = []

while (port.inWaiting()==0):  #keep sending char until arduino replies
	port.write("*")
	time.sleep(1)
	
vals = (port.readline()).split(',')
print vals
PressureVal = int(vals[0])
LightVal    =  int(vals[1])
MoistureVal = int(vals[2])
cur.execute("insert into sens_vals(Pressure,Light,Moisture) values(" + str(PressureVal) + "," + str(LightVal) +
									"," + str(MoistureVal) + ")" ) #put adc values in mysql db
	

cur.execute("SELECT * from sens_vals")

#dataset = cur.fetchall()  for debugging - print mysql rows to check sensor values were added	
#for row in dataset:	
#	print row
	

db.close()
	
	

The MySQL database was made using the terminal on the pi. Here are some pictures of the database format:

mysql-fields

mysql-fields

sens-vals-table

sens-vals-table

On the Pi, a cronjob is used to run the python script every 30 mins. To edit the crontab, I used sudo crontab -e and entered the following:

*/30 * * * * python /home/pi/plantbot/serial2db.py

This means that every 30 mins the sensors are read and their values placed in the MySQL database.

Step 3 : Running PHP on the server to graph values from MySQL database:

<?php // content="text/plain; charset=utf-8"

define('__ROOT__', dirname(dirname(__FILE__))); 
require_once ('../tools/jpgraph/src/jpgraph.php');
require_once ('../tools/jpgraph/src/jpgraph_line.php');
require_once ('../tools/jpgraph/src/jpgraph_error.php');
require_once ('../tools/jpgraph/src/jpgraph_date.php');

$dates= array();
$light = array();
$pressure = array();
$moisture = array();
$i = 0;

$con=mysqli_connect("66.147.244.233","wattnoti_user","physics","wattnoti_plantbot");
 //Check connection
if (mysqli_connect_errno()) {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
 
mysqli_query($con,"set time_zone = '+00:00'");
$result = mysqli_query($con,"(SELECT * FROM sens_vals ORDER BY id DESC LIMIT 25) ORDER BY id ASC");

while($row = mysqli_fetch_array($result)) {
	$dates[$i] = strtotime($row["date"]);
	$light[$i] =  $row["Light"];
	$pressure[$i] =  $row["Pressure"];
	$moisture[$i] =  $row["Moisture"];
	$i++;
	
}


mysqli_close($con);


$graph = new Graph(800,500);
$graph->img->SetMargin(40,40,40,40);	
$graph->img->SetAntiAliasing();
$graph->SetScale("datlin");
$graph->SetShadow();
$graph->title->Set("PlantBot Sensor Readings");
$graph->title->SetFont(FF_FONT1,FS_BOLD);
// Ensure anti-aliasing is off. If it is not, you can SetWeight() all day and nothing will change.
$graph->img->SetAntiAliasing(false);
$graph->xaxis->SetLabelAngle(45);
$graph->xaxis->scale->SetDateFormat('Y:M:d:D:H:i');
$graph->legend->SetPos(0.37,0.07,'right','center');
$graph->legend->SetFrameWeight(2);
$graph->legend->SetColor('black','black');
$graph->xgrid->Show(true,false);
// Use 20% "grace" to get slightly larger scale then min/max of
// data
$graph->yscale->SetGrace(0);

$graph->yaxis->title->Set("ADC Value");
$graph->yaxis->SetTitleMargin(-700);

$p1 = new LinePlot($light,$dates);
$p1->SetColor("blue");
$p1->SetCenter();
$p1->SetLegend("light");

$p2 = new lineplot($pressure,$dates);
$p2->setColor("orange");
$p2->SetLegend("pressure");

$p3 = new lineplot($moisture,$dates);
$p3->setColor("yellow");
$p3->SetLegend("moisture");

$graph->Add($p1);
$graph->Add($p2);
$graph->Add($p3);

$p1->SetWeight(3);
$p2->SetWeight(3);
$p3->SetWeight(3);

$graph->Stroke();


?>

This PHP program looks kinda bulky but most of it is just jpgraph stuff to make the graph look nice. Lines 1-34 is where the MySQL db is accessed and the sensor values read in PHP arrays.

Graph Produced (Real time image):

I’m still working out some of the kinks with jpgraph so while it’s not perfect, you get the idea.
The html page I’ll be displaying all of the real time data on is located at http://wattnotions.com/html_stuff/PlantBotNet.html
As I’m writing this post now (10th January 2016), all it contains is a picture of the graph – I’ll be adding to it in the near future.

Update 1 : (10th Jan 2016)
IMG_20160110_162350[1]
Just planted some cress seeds in part of this plantbox I have – will manually water it (uh effort) for the next few days/weeks or however long it takes for cress seeds to grow. This will be automated soon enough by Plantbot. Stay tuned!

This entry was posted in Arduino, Atmel, how to, Microcontrollers, PHP, Projects, Python and tagged , , . Bookmark the permalink.

4 Responses to Connecting sensors to the internet using an arduino and a raspberry pi

  1. Sam says:

    Hi Shane,
    Nice little project! I was just wondering if there was a specific reason for not using the Pi to read the sensors? Is it due to the lack of built-in ADC? Would a PCF8591 be cheaper than using an arduino?
    Cheers,
    Sam

    • wattnotions says:

      Hey Sam, Thanks! Pretty much the only reason I used an arduino nano is because I had it laying around…. I got it from china for 2 euro, not sure how much a PCF8591 costs :)

  2. Craig says:

    I’m using a pi 3 and struggling to get the raspberry pi to read from usb serial

    • wattnotions says:

      Try googling your problem and if that doesn’t work post to an Arduino/Raspi forum. Best of luck with it.

Leave a Reply