Lesson 10 - Temperature Monitored Greenhouse

From Sensors in Schools
Jump to navigation Jump to search

Temperature Monitored Mini-Greenhouse

  • The aim of this experiment is to install a onewire temperature sensor to a mini-greenhouse to monitor temperature.
  • The temperature sensor is connected to an Arduino.
  • The Arduino sends data to a Raspberry Pi connected to the greenhouse.
  • This Raspberry Pi sends the temperature data to the internet via a dweet.
  • Students in the class can receive the temperature data using python code to download the latest dweet.

Connecting Raspberry Pi computer to a Telstra 4G Wireless Router

  • Students need to connect their Raspberry Pi computers to the internet.
  • They do this my connecting to a local Telstra 4G router.
  • The router name is TPW4G_Cj7G2J.
  • Available WiFi networks are shown by clicking the mouse on the WiFi symbol on the top right of the Desktop.

  • Hovering over the WiFi symbol will reveal the IP address associated with each Raspberry Pi computer.
  • The IP address for my computer is 192.168.0.167
  • Every other computer on the same network will have a different address - starting with 192.168.0 and ending with a different number from 1 to 254.

Installing dweepy library

  • Before the students can receive dweets (data tweets) then need to install a software library.
  • Open up the Terminal.

  • Adjust the font size if necessary.
  • Click on Edit > Preferences
  • Click on Font
  • Change the font size to 16.
  • Click on Select
  • Commit the changes by clicking on OK

  • Enter the command pip3 install dweepy to install the dweepy library.
  • The version of dweepy is 0.3.0

Python code to get Dweet

  • Open Thonny
  • Type in the following code.
    • dweepy.get_latest_dweet_for - gets the latest dweet named MPPS-temperature-greenhouse-3754. The information from the dweet is assigned to the variable named url
    • print(url) - prints the variable url
import dweepy

url = dweepy.get_latest_dweet_for('MPPS-temperature-greenhouse-3754')

print(url)
  • The output in printed in the Python Shell (bottom section of Thonny)
  • Key pieces of information in the dweet are:
    • The name of the dweet (or thing) - MPPS-temperature-greenhouse-3754
    • date created
    • content - specifically Temperature: 20.5

Arduino code to send data to Raspberry Pi - code

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 4   // Data wire is conntected to the Arduino digital pin 4
OneWire oneWire(ONE_WIRE_BUS);  // Setup a oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature sensor

float temperature;

void setup() {
  Serial.begin(9600);
  // Start up the library
  sensors.begin();
}

void loop() {
  sensors.requestTemperatures(); 
  Serial.println(sensors.getTempCByIndex(0)); // Send data to Raspberry Pi

  delay(10000); // 300000 = Five minute delay, 10000 = 10 second delay
}


Dweet python code - full

The provided Python code is a script that reads data from a serial port (specifically, /dev/ttyUSB0) at a baud rate of 9600. Let's break down the code:

  • if __name__ == '__main__':: This line checks if the script is being run as the main program (i.e., not imported as a module into another script). This is a common practice to ensure that the following code block is executed only when the script is run directly.
  • ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1): This line initializes a serial connection using the serial library. It creates a serial object named ser that communicates with the device located at /dev/ttyUSB0 (a USB-to-serial converter, for example) with a baud rate of 9600. The timeout=1 parameter sets the timeout for reading operations to 1 second. If no data is received within this timeout, the read operation will return.
  • ser.reset_input_buffer(): This line resets the input buffer of the serial port, clearing any previously received data that might still be in the buffer.
  • while True:: This initiates an infinite loop that continuously reads data from the serial port.
  • time.sleep(0.1): Within each iteration of the loop, the script pauses for 0.1 seconds using the time.sleep() function. This slight delay allows time for new data to be received and stored in the input buffer.
  • if ser.in_waiting > 0:: This line checks if there is data available in the input buffer of the serial port. If there is data waiting to be read, the condition evaluates to True.
  • print("Data in"): If there is data available in the input buffer (i.e., ser.in_waiting > 0 is true), this line prints the message "Data in" to the console. This is just a notification to indicate that there is incoming data.
  • line = ser.readline().decode('utf-8').rstrip(): This line reads the data from the serial port. It performs the following steps:
    • ser.readline(): Reads a line of data from the serial port. The readline() method will read all the data until it encounters a newline character ('\n') or until the timeout expires (1 second in this case).
    • decode('utf-8'): Converts the bytes read from the serial port into a string using the UTF-8 encoding. This assumes that the data transmitted through the serial port is encoded as UTF-8.
    • rstrip(): Removes any trailing newline characters ('\n') and whitespace from the end of the string. This step is useful to clean up the data and remove unwanted characters.
#!/usr/bin/env python3
# dweet data
import serial
import datetime
import time
import requests

if __name__ == '__main__':
    ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
    ser.reset_input_buffer()
    while True:
        time.sleep(0.1)
        if ser.in_waiting > 0:
            print("Data in")
            air_temp = ser.readline().decode('utf-8').rstrip()

            now = datetime.datetime.now()
            date_stamp = now.strftime("%Y-%m-%d %H:%M:%S")

            data = str(air_temp) + "," + date_stamp + "\n"
            print(f'The data is =  {data}')
   
            try:
                print("Preparing dweet")
                dweet_dict = {}
                dweet_dict.update({"air_temperature": str(air_temp)}) 
                dweet_dict.update({"latest_result": str(date_stamp)})
                url = "https://dweet.io/dweet/for/<My_Dweet_address>?"
                x = requests.post(url, json=dweet_dict)
                print(x.text)
            except:
                print("Dweet failed")
            # check dweet with - https://dweet.io/get/latest/dweet/for/<My_Dweet_address>

Python code to Print Temperature data

  • Now that we can Get a Dweet we can process the Dweet to extract data.
  • In this example we will extract Temperature data.

Copy Python code

import dweepy

url = dweepy.get_latest_dweet_for('MPPS-temperature-greenhouse-3754')

print(url)

dict = url[0]

temperature = dict['content'][('Temperature')]

print(f'The temperature is {temperature}')

Python code to Save Temperature data

This Python code performs the following actions:

  • f = open('/home/pi/temp-greenhouse/greenhouse_data.txt', 'a'): It opens a file named "greenhouse_data.txt" in append mode. The file is located in the "/home/pi/temp-greenhouse/" directory. The 'a' mode indicates that data will be appended to the end of the file, and if the file does not exist, it will be created.
  • f.write(temperature): It writes the contents of the temperature variable to the file. The content written to the file will be whatever is stored in the temperature variable at the time this code is executed. The variable temperature should be a string or any data type that can be represented as a string.
  • f.close(): It closes the file after writing the data. This is an essential step to ensure that all data is properly saved and that the file is ready for other operations.
  • print("Data saved"): It prints the message "Data saved" to the console. This message informs the user that the data has been successfully written to the file.

Copy Python code

import dweepy

url = dweepy.get_latest_dweet_for('MPPS-temperature-greenhouse-3754')
print(url)

dict = url[0]
temperature = dict['content'][('Temperature')]
print(f'The temperature is {temperature}')

temperature = str(temperature) + '\n'
f = open('/home/pi/auto-greenhouse/greenhouse_data.txt','a')
f.write(temperature)
f.close()
print("Data saved")

Python code for Datetime Stamp

The following Python code uses the datetime module to get the current date and time and then formats it into a string representation. Let's break down the code step by step:

import datetime: This line imports the datetime module, which provides classes and methods to work with dates and times in Python. now = datetime.datetime.now(): This line creates a datetime object named now, representing the current date and time. It uses the datetime.now() method to get the current date and time from the system clock.

date_stamp = now.strftime("%Y-%m-%d %H:%M:%S"): This line formats the now datetime object into a string representation. * The strftime() method is used to format the date and time according to a specified format string. In this case, the format string "%Y-%m-%d %H:%M:%S" is used, which represents the date and time in the format "YYYY-MM-DD HH:MM:SS". Here's what each part of the format string means:

    • %Y: Year with century as a decimal number (e.g., 2023)
    • %m: Month as a zero-padded decimal number (e.g., 01, 02, ..., 12)
    • %d: Day of the month as a zero-padded decimal number (e.g., 01, 02, ..., 31)
    • %H: Hour (24-hour clock) as a zero-padded decimal number (e.g., 00, 01, ..., 23)
    • %M: Minute as a zero-padded decimal number (e.g., 00, 01, ..., 59)
    • %S: Second as a zero-padded decimal number (e.g., 00, 01, ..., 59)
  • The strftime() method returns the formatted string representation, which is assigned to the variable date_stamp.
  • print(f'The date_stamp is = {date_stamp}'): This line prints the formatted date and time string to the console. It uses an f-string (formatted string literal) to insert the value of the date_stamp variable into the string for printing.

When you run this code, it will display the current date and time in the "YYYY-MM-DD HH:MM:SS" format, showing the year, month, day, hour, minute, and second of the current system time.

import datetime

now = datetime.datetime.now()
date_stamp = now.strftime("%Y-%m-%d %H:%M:%S")

print(f'The date_stamp is = {date_stamp}')

Send Dummy temperature data

Full code

import dweepy

#https://github.com/paddycarey/dweepy - Reference

dweet_dict = {}
dweet_dict.update({"Temperature": '20.5'})

dweepy.dweet_for('MPPS-temperature-greenhouse-3754', dweet_dict)

url = dweepy.get_latest_dweet_for('MPPS-temperature-greenhouse-3754')
print(url)

dict = url[0]

temperature = dict['content'][('Temperature')]
print(f'The temperature is {temperature}')

Exploring Datetime Stamp

import dweepy
import datetime

now = datetime.datetime.now()
date_stamp = now.strftime("%Y-%m-%d %H:%M:%S")

print(f'The now is =  {now}')


url = dweepy.get_latest_dweet_for('MPPS-temperature-greenhouse-3754')
print(url)


dict = url[0]
longdate = dict['created']
print(longdate)

temperature = dict['content'][('Temperature')]
print(f'The temperature is {temperature}')


Saving Data

import dweepy
import datetime

now = datetime.datetime.now()
date_stamp = now.strftime("%Y-%m-%d %H:%M:%S")
print(f'The current time is =  {date_stamp}')

url = dweepy.get_latest_dweet_for('MPPS-temperature-greenhouse-3754')
print(url)

soil_temp = dict['content']['soil_temp']
print(f'The temperature is {soil_temp}')

data = date_stamp + "," + soil_temp + "\n"
print(f'The data is =  {data}')

f = open('/home/pi/auto-greenhouse/greenhouse_data.txt','a')
f.write(data)
f.close()
print("Data saved")


Save All Data

import dweepy
import datetime

now = datetime.datetime.now()
date_stamp = now.strftime("%Y-%m-%d %H:%M:%S")
print(f'The current time is =  {date_stamp}')

url = dweepy.get_latest_dweet_for('MPPS-temperature-greenhouse-3754')
print(url)

soil_temp = dict['content']['soil_temp']
print(f'The soil temperature is {soil_temp}')

humidity = dict['content']['humid']
print(f'The humidity of the mini-greenhouse is {humidity}')

air_temp = dict['content']['air_temp']
print(f'The air temperature of the mini-greenhouse is {air_temp}')

data = date_stamp + "," + str(soil_temp) + "," + str(humidity) + "," + str(air_temp) + "\n"
print(f'The data is =  {data}')

f = open('/home/pi/auto-greenhouse/greenhouse_data.txt','a')
f.write(data)
f.close()
print("Data saved")

Arduino DHT22 Temp and Humidity and Onewire Temperature Sensor

* How to use the DHT-22 temperature and humidity sensor
   and Onewire temperature sensor with Arduino Uno
*/

//Libraries
#include <DHT.h>;
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is conntec to the Arduino digital pin 4
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature soil_temp(&oneWire);

//Constants
#define DHTPIN 7     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE); //// Initialize DHT sensor for normal 16mhz Arduino


//Variables
float hum;  //Stores humidity value
float air_temp; //Stores temperature value

void setup()
{
  Serial.begin(9600);
  dht.begin();
  soil_temp.begin();
  pinMode(13, OUTPUT);
}

void loop()
{
    delay(2000);  //Delay 2 seconds
    // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
    soil_temp.requestTemperatures(); 
    Serial.print("Soil temperature: ");
    Serial.print(soil_temp.getTempCByIndex(0)); 
    Serial.println(" Celsius");
    Serial.print(",");
    
    //Read data and store it to variables hum and temp
    hum = dht.readHumidity();
    air_temp = dht.readTemperature();


    Serial.print("Humidity: ");
    Serial.print(hum);
    Serial.print(" %");
    Serial.print(",");
    Serial.print("Air Temp: ");
    Serial.print(air_temp);
    Serial.println(" Celsius");
   
}

Arduino - sending Onewire and DHT22 data to the Raspberry Pi

* How to use the DHT-22 temperature and humidity sensor
   and Onewire temperature sensor with Arduino Uno
*/

//Libraries
#include <DHT.h>;
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is conntec to the Arduino digital pin 4
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature soil_temp(&oneWire);

//Constants
#define DHTPIN 7     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE); //// Initialize DHT sensor for normal 16mhz Arduino


//Variables
float hum;  //Stores humidity value
float air_temp; //Stores temperature value

void setup()
{
  Serial.begin(9600);
  dht.begin();
  soil_temp.begin();
  pinMode(13, OUTPUT);
}

void loop()
{
    delay(2000);  //Delay 2 seconds
    // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
    soil_temp.requestTemperatures(); 
    Serial.print(soil_temp.getTempCByIndex(0)); 
    Serial.print(",");
    
    //Read data and store it to variables hum and temp
    hum = dht.readHumidity();
    air_temp = dht.readTemperature();
    Serial.print(hum);
    Serial.print(",");
    Serial.println(air_temp);

}

Arduino Fan Control above 25 degC

/* How to use the DHT-22 temperature and humidity sensor
   and Onewire temperature sensor with Arduino Uno
*/

//Libraries
#include <DHT.h>;
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is conntec to the Arduino digital pin 4
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature soil_temp(&oneWire);

//Constants
#define DHTPIN 7     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE); //// Initialize DHT sensor for normal 16mhz Arduino


//Variables
float hum;  //Stores humidity value
float air_temp; //Stores temperature value

void setup()
{
  Serial.begin(9600);
  dht.begin();
  soil_temp.begin();
  pinMode(13, OUTPUT);
}

void loop()
{
    delay(2000);  //Delay 2 seconds
    // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
    soil_temp.requestTemperatures(); 
    Serial.print(soil_temp.getTempCByIndex(0)); 
    Serial.print(",");
    
    //Read data and store it to variables hum and temp
    hum = dht.readHumidity();
    air_temp = dht.readTemperature();
    Serial.print(hum);
    Serial.print(",");
    Serial.println(air_temp);

    if (air_temp > 25.0) {
      //turn on fan to cool greenhouse
      digitalWrite(13, HIGH);  // turn fan ON
    }
    else {
      digitalWrite(13, LOW);  // turn fan OFF
    }
    delay(300000);
}

Python code to extract Arduino data

#!/usr/bin/env python3
# dweet data
import serial
import datetime
import plotly
import plotly.graph_objects as go
import pandas
import time
import requests

if __name__ == '__main__':
    ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
    ser.reset_input_buffer()
    while True:
        time.sleep(0.1)
        if ser.in_waiting > 0:
            line = ser.readline().decode('utf-8').rstrip()
            print(f"Data separated using commas {line.split(',')}")
            mylist = line.split(',')
            try:
                soil_temp = float(mylist[0])
                humid = float(mylist[1])
                air_temp = float(mylist[2])
            except:
                soil_temp = 0.0
                humid = 0.0
                air_temp = 0.0

            time.sleep(1)
            now = datetime.datetime.now()
            datetime_stamp = now.strftime("%Y-%m-%d %H:%M:%S")

            data = datetime_stamp + "," + str(soil_temp) + "," + str(humid) + "," + str(air_temp) + "\n"
            print(f'The data is =  {data}')

            f = open('/home/pi/auto-greenhouse/greenhouse_data.txt','a')
            f.write(data)
            f.close()
            print("Data saved")
            
            # import and plot data text file
            df = pandas.read_csv('/home/pi/auto-greenhouse/greenhouse_data.txt')

            fig = go.Figure(data = go.Scatter(mode='markers',
                                                x=df.date_time,
                                                y=df.air_temp,
                                                marker=dict(
                                                    color="LightSkyBlue",
                                                    size=20)
                                                )
                                        )
            fig.update_layout(title="Air Temperature in Greenhouse",
                                xaxis_title = 'Time',
                                yaxis_title = 'Air temperature',
                                font=dict(
                                    size=20,
                                    color="RebeccaPurple"
                                )
                            )

            plotly.offline.plot(fig,
                                filename="/home/pi/auto-greenhouse/air_temperature_plot.html",
                                auto_open=False)

            print("Air temperature data plotted")
            
            
            fig = go.Figure(data = go.Scatter(mode='markers',
                                                x=df.date_time,
                                                y=df.soil_temp,
                                                marker=dict(
                                                    color="LightSkyBlue",
                                                    size=20)
                                                )
                                        )
            fig.update_layout(title="Soil Temperature in Greenhouse",
                                xaxis_title = 'Time',
                                yaxis_title = 'Temperature',
                                font=dict(
                                    size=20,
                                    color="RebeccaPurple"
                                )
                            )

            plotly.offline.plot(fig,
                                filename="/home/pi/auto-greenhouse/soil_temperature_plot.html",
                                auto_open=False)

            print("Soil Temperature data plotted")
            
            try:
                print("Preparing dweet")
                dweet_dict = {}
                dweet_dict.update({"soil_temp": str(soil_temp)})
                dweet_dict.update({"humidity": str(humid)})
                dweet_dict.update({"air_temp": str(air_temp)})
                dweet_dict.update({"latest_result": str(datetime_stamp)})

                url = "https://dweet.io/dweet/for/MPPS-auto-greenhouse-Aug2023?"
                # Dweet address1 - MPPS-temperature-greenhouse-3754
                # Dweet address2 - MPPS-auto-greenhouse-Aug2023
                x = requests.post(url, json=dweet_dict)
                print(x.text)
            except:
                print("Dweet failed")
            # check dweet with - https://dweet.io/get/latest/dweet/for/<dweet-name-here>