website
Skip to content

Blog

Smart Greenhouse Project with PicoBricks

by Robotistan Shopify 02 May 2023
PicoBricks is a versatile robotic platform powered by the Raspberry Pi Pico microcontroller. This platform enables users to build an array of robotic projects by interconnecting various sensors, motors, and other components.

Here are some of the robotic projects that can be created with PicoBricks:

The PicoBricks platform offers a wide range of possibilities for creating various robotic projects. For instance, you can design an automatic irrigation system that uses moisture sensors to measure soil moisture and install a motorized irrigation system to water the plants.

Additionally, PicoBricks can be used to create an autonomous car that uses ultrasonic sensors to detect obstacles and a motor driver to control the car's motors. Another application is a line following robot that moves by following a line on a surface, which can be achieved with the help of PicoBricks.

The platform's PWM signal generation capability can also be used to control the movements of a robotic arm, making it an ideal solution for building a controlled robotic arm.

Moreover, PicoBricks can be used for educational purposes, allowing students to learn STEM subjects and develop their engineering and programming skills by creating their robotic projects.
Creating an automatic irrigation system with PicoBricks is quite easy. Here is a step-by-step guide on how to do it:

Materials:

Raspberry Pi Pico
Soil moisture sensor
DC motor
Watering hose
Breadboard
Jumper cables
Power supply
Transistor

Step 1: Connect the soil moisture sensor

Connect the soil moisture sensor to the breadboard. Connect the VCC pin of the sensor to the 3V3 pin of the Pico, the GND pin to the GND pin of the Pico, and the AO pin to the A0 pin of the Pico.

Step 2: Connect the DC motor

Connect the DC motor to the breadboard. Connect the positive connection of the motor to the Vin pin of the Pico and the negative connection to the emitter of a transistor. Connect the collector of the transistor to the GND pin of the Pico and connect the base of the transistor to a GPIO pin. This GPIO pin will be used to generate the PWM signals to control the motor.

Step 3: Connect the watering hose

Connect the watering hose to the output of the motor.

Step 4: Write the code

Using the Python programming language, write a code to read the data from the soil moisture sensor and turn the motor on and off based on this data. In the code, you will also generate PWM signals to adjust the speed of the motor.

Example cods belows: MicroPython

import utime
import uos
import machine
from machine import Pin, ADC
from picobricks import DHT11
from utime import sleep

dht_sensor = DHT11(Pin(11))
smo_sensor=ADC(27)
m1 = Pin(22, Pin.OUT)
m1.low()

print("Machine: \t" + uos.uname()[4])
print("MicroPython: \t" + uos.uname()[3])

uart0 = machine.UART(0, baudrate=115200)
print(uart0)

def Connect_WiFi(cmd, uart=uart0, timeout=5000):
print("CMD: " + cmd)
uart.write(cmd)
utime.sleep(7.0)
Wait_ESP_Rsp(uart, timeout)
print()

def Rx_ESP_Data():
recv=bytes()
while uart0.any()>0:
recv+=uart0.read(1)
res=recv.decode('utf-8')
return res

def Send_AT_Cmd(cmd, uart=uart0, timeout=2000):
print("CMD: " + cmd)
uart.write(cmd)
Wait_ESP_Rsp(uart, timeout)
print()

def Wait_ESP_Rsp(uart=uart0, timeout=2000):
prvMills = utime.ticks_ms()
resp = b""
while (utime.ticks_ms()-prvMills)<timeout:
if uart.any():
resp = b"".join([resp, uart.read(1)])
print("resp:")
try:
print(resp.decode())
except UnicodeError:
print(resp)

Send_AT_Cmd('AT\r\n') #Test AT startup
Send_AT_Cmd('AT+GMR\r\n') #Check version information
Send_AT_Cmd('AT+CIPSERVER=0\r\n')
Send_AT_Cmd('AT+RST\r\n') #Check version information
Send_AT_Cmd('AT+RESTORE\r\n') #Restore Factory Default Settings
Send_AT_Cmd('AT+CWMODE?\r\n') #Query the WiFi mode
Send_AT_Cmd('AT+CWMODE=1\r\n') #Set the WiFi mode = Station mode
Send_AT_Cmd('AT+CWMODE?\r\n') #Query the WiFi mode again
Send_AT_Cmd('AT+CWJAP="ID","Password"\r\n', timeout=5000) #Connect to AP
utime.sleep(3.0)
Send_AT_Cmd('AT+CIFSR\r\n') #Obtain the Local IP Address
utime.sleep(3.0)
Send_AT_Cmd('AT+CIPMUX=1\r\n')
utime.sleep(1.0)
Send_AT_Cmd('AT+CIPSERVER=1,80\r\n') #Obtain the Local IP Address
utime.sleep(1.0)

while True:
res =""
res=Rx_ESP_Data()
utime.sleep(2.0)
if '+IPD' in res: # if the buffer contains IPD(a connection), then respond with HTML handshake
id_index = res.find('+IPD')

if '/WATERING' in res:
print('Irrigation Start')
m1.high()
utime.sleep(10)
m1.low()
print('Irrigation Finished')
connection_id = res[id_index+5]
print("connectionId:" + connection_id)
print ('! Incoming connection - sending webpage')
uart0.write('AT+CIPSEND='+connection_id+',200'+'\r\n')
utime.sleep(1.0)
uart0.write('HTTP/1.1 200 OK'+'\r\n')
uart0.write('Content-Type: text/html'+'\r\n')
uart0.write('Connection: close'+'\r\n')
uart0.write(''+'\r\n')
uart0.write('<!DOCTYPE HTML>'+'\r\n')
uart0.write('<html>'+'\r\n')
uart0.write('<body><center><H1>CONNECTED...<br/></H1></center>'+'\r\n')
uart0.write('<body><center><H1>Irrigation Complete.<br/></H1></center>'+'\r\n')
uart0.write('<script>class RocketElementorAnimation{constructor(){this.deviceMode=document.createElement("span"),this.deviceMode.id="elementor-device-mode",this.deviceMode.setAttribute("class","elementor-screen-only"),document.body.appendChild(this.deviceMode)}_detectAnimations(){let t=getComputedStyle(this.deviceMode,":after").content.replace(/"/g,"");this.animationSettingKeys=this._listAnimationSettingsKeys(t),document.querySelectorAll(".elementor-invisible[data-settings]").forEach(t=>{const e=t.getBoundingClientRect();if(e.bottom>=0&&e.top<=window.innerHeight)try{this._animateElement(t)}catch(t){}})}_animateElement(t){const e=JSON.parse(t.dataset.settings),i=e._animation_delay||e.animation_delay||0,n=e[this.animationSettingKeys.find(t=>e[t])];if("none"===n)return void t.classList.remove("elementor-invisible");t.classList.remove(n),this.currentAnimation&&t.classList.remove(this.currentAnimation),this.currentAnimation=n;let s=setTimeout(()=>{t.classList.remove("elementor-invisible"),t.classList.add("animated",n),this._removeAnimationSettings(t,e)},i);window.addEventListener("rocket-startLoading",function(){clearTimeout(s)})}_listAnimationSettingsKeys(t="mobile"){const e=[""];switch(t){case"mobile":e.unshift("_mobile");case"tablet":e.unshift("_tablet");case"desktop":e.unshift("_desktop")}const i=[];return["animation","_animation"].forEach(t=>{e.forEach(e=>{i.push(t+e)})}),i}_removeAnimationSettings(t,e){this._listAnimationSettingsKeys().forEach(t=>delete e[t]),t.dataset.settings=JSON.stringify(e)}static run(){const t=new RocketElementorAnimation;requestAnimationFrame(t._detectAnimations.bind(t))}}document.addEventListener("DOMContentLoaded",RocketElementorAnimation.run);</script></body></html>'+'\r\n')
elif '/SERA' in res:
#sleep(1) # It was used for DHT11 to measure.
dht_sensor.measure() # Use the sleep() command before this line.
temp=dht_sensor.temperature
hum=dht_sensor.humidity
smo=round((smo_sensor.read_u16()/65535)*100)
sendStr="\"TEMP\":{}, \"Humidity\":{}, \"S.Moisture\":{}%".format(temp,hum,smo)
sendText="{"+sendStr+"}"
strLen=46+len(sendText)
connection_id = res[id_index+5]
print("connectionId:" + connection_id)
print ('! Incoming connection - sending webpage')
atCmd="AT+CIPSEND="+connection_id+","+str(strLen)
uart0.write(atCmd+'\r\n')
utime.sleep(1.0)
uart0.write('HTTP/1.1 200 OK'+'\r\n')
uart0.write('Content-Type: text/html'+'\r\n')
uart0.write(''+'\r\n')
uart0.write(sendText+'\r\n')

elif '/' in res:

print("resp:")
print(res)
connection_id = res[id_index+5]
print("connectionId:" + connection_id)
print ('! Incoming connection - sending webpage')
uart0.write('AT+CIPSEND='+connection_id+',200'+'\r\n')
utime.sleep(3.0)
uart0.write('HTTP/1.1 200 OK'+'\r\n')
uart0.write('Content-Type: text/html'+'\r\n')
uart0.write('Connection: close'+'\r\n')
uart0.write(''+'\r\n')
uart0.write('<!DOCTYPE HTML>'+'\r\n')
uart0.write('<html>'+'\r\n')
uart0.write('<body><center><H1>CONNECTED.<br/></H1></center>'+'\r\n')
uart0.write('<center><h4>INFO:Get Sensor Data</br>WATERING:Run Water Pump</h4></center>'+'\r\n')
uart0.write('</body></html>'+'\r\n')
utime.sleep(4.0)
Send_AT_Cmd('AT+CIPCLOSE='+ connection_id+'\r\n') # once file sent, close connection
utime.sleep(3.0)
recv_buf="" #reset buffer
print ('Waiting For connection...')

Arduino C Codes

#include <DHT.h>
#define RX 0
#define TX 1

#define LIMIT_TEMPERATURE 30
#define DHTPIN 11
#define DHTTYPE DHT11
#define smo_sensor 27
#define motor 22
#define DEBUG true

DHT dht(DHTPIN, DHTTYPE);
int connectionId;

void setup() {
Serial1.begin(115200);
dht.begin();
pinMode(smo_sensor, INPUT);
pinMode(motor, OUTPUT);

sendData("AT+RST\r\n", 2000, DEBUG); // reset module
sendData("AT+GMR\r\n", 1000, DEBUG); // configure as access point
sendData("AT+CIPSERVER=0\r\n", 1000, DEBUG); // configure as access point
sendData("AT+RST\r\n", 1000, DEBUG); // configure as access point
sendData("AT+RESTORE\r\n", 1000, DEBUG); // configure as access point
sendData("AT+CWMODE?\r\n", 1000, DEBUG); // configure as access point
sendData("AT+CWMODE=1\r\n", 1000, DEBUG); // configure as access point
sendData("AT+CWMODE?\r\n", 1000, DEBUG); // configure as access point
sendData("AT+CWJAP=\"WIFI_ID\",\"WIFI_PASSWORD\"\r\n", 5000, DEBUG); // ADD YOUR OWN WIFI ID AND PASSWORD
delay(3000);
sendData("AT+CIFSR\r\n", 1000, DEBUG); // get ip address
delay(3000);
sendData("AT+CIPMUX=1\r\n", 1000, DEBUG); // configure for multiple connections
delay(1000);
sendData("AT+CIPSERVER=1,80\r\n", 1000, DEBUG); // turn on server on port 80
delay(1000);
}

void loop() {
if (Serial1.find("+IPD,")) {
delay(300);
connectionId = Serial1.read() - 48;
String serialIncoming = Serial1.readStringUntil('\r');
Serial.print("SERIAL_INCOMING:");
Serial.println(serialIncoming);

if (serialIncoming.indexOf("/WATERING") > 0) {
Serial.println("Irrigation Start");
digitalWrite(motor, HIGH);
delay(1000); // 10 sec.
digitalWrite(motor, LOW);
Serial.println("Irrigation Finished");
Serial.println("! Incoming connection - sending WATERING webpage");
String html = "";
html += "<html>";
html += "<body><center><H1>Irrigation Complete.<br/></H1></center>";
html += "</body></html>";
espsend(html);
}
if (serialIncoming.indexOf("/SERA") > 0) {
delay(300);

float smo = analogRead(smo_sensor);
float smopercent = (460-smo)*100.0/115.0 ; //min ve max değerleri değişken.
Serial.print("SMO: %");
Serial.println(smo);

float temperature = dht.readTemperature();
Serial.print("
Temp: ");
Serial.println(temperature);

float humidity = dht.readHumidity();
Serial.print("
Hum: ");
Serial.println(humidity);

Serial.println("
! Incoming connection - sending SERA webpage");
String html = "
";
html += "
<html>";
html += "
<body><center><H1>TEMPERATURE<br/></H1></center>";
html += "
<center><H2>";
html += (String)temperature;
html += "
C<br/></H2></center>";

html += "
<body><center><H1>HUMIDITY<br/></H1></center>";
html += "
<center><H2>";
html += (String)humidity;
html += "
%<br/></H2></center>";

html += "
<body><center><H1>SMO<br/></H1></center>";
html += "
<center><H2>";
html += (String)smopercent;
html += "
%<br/></H2></center>";

html += "
</body></html>";
espsend(html);
}
else
Serial.println("
! Incoming connection - sending MAIN webpage");
String html = "
";
html += "
<html>";
html += "
<body><center><H1>CONNECTED.<br/></H1></center>";
html += "
<center><a href='/SERA'><h4>INFO:Get Sensor Data</a></br><a href='/WATERING'>WATERING:Run Water Pump</a></h4></center>";
html += "</
body></html>";
espsend(html);
String closeCommand = "AT+CIPCLOSE="; /
///////////////close the socket connection////esp command
closeCommand += connectionId; /
/ append connection id
closeCommand += "\r\n";
sendData(closeCommand, 3000, DEBUG);

}

}
/
/////////////////////////////sends data from ESP to webpage///////////////////////////

void espsend(String d)
{
String cipSend = " AT+CIPSEND=";
cipSend += connectionId;
cipSend += ",";
cipSend += d.length();
cipSend += "\r\n";
sendData(cipSend, 1000, DEBUG);
sendData(d, 1000, DEBUG);
}

//////////////gets the data from esp and displays in serial monitor///////////////////////

String sendData(String command, const int timeout, boolean debug)
{
String response = "";
Serial1.print(command);
long int time = millis();
while ( (time + timeout) > millis())
{
while (Serial1.available())
{
char c = Serial1.read(); /
/ read the next character.
response += c;
}
}

if (debug)
{
Serial.print(response); /
/displays the esp response messages in arduino Serial monitor
}
return response;
}

Project Proposal 💡

In the smart greenhouse project, by adding an OLED screen to the greenhouse entrance, you can monitor the humidity and temperature values inside, and by adding sensors such as MQ2 gas sensor, carbon dioxide sensor, air quality sensor, you can monitor the weather inside the greenhouse via WiFi with your mobile phone. In addition, by adding a DC fan and relay to the greenhouse, you can turn the ventilation on and off according to the indoor air quality with a mobile phone via WiFi.
Someone recently bought a
[time] ago, from [location]

Thanks for subscribing!

This email has been registered!

Shop the look

Choose Options

Robotistan
Have Questions?
Back In Stock Notification
this is just a warning
Login
Shopping Cart
0 items