关于自动浇花估计很多Arduino的爱好者都玩过,原理也很简单,就是通过土壤湿度检测来自动给植物浇水。那么今天波波为朋友们分享的原理基本接近,但比之前的更好玩儿。
首先看下波波完工的视频:
准备材料:
1、Arduino开发板,本例采用的是 Arduino uno r3
2、传感器:DH11、DS1302、土壤湿度传感器、红外接收模块、遥控器(可以用家中电视机的都行)
4、其他材料:按键一个、5v继电器一个、5v隔膜小水泵一个、1602显示屏、导线若干。
5、本例中使用了9v1A的太阳能电池板,(这个电池板跟共享单车是一样的)电池板后面需要接一个TPP稳压输入输出电路,保障电池的安全。没有这个电路板电池很可能一天不到就损坏了。
实现功能:
1、按键:按键按下的时候可以切换1602屏幕亮暗状态。平时不用的时候可以让屏幕休眠,节约用电。
2、自动浇水:根据室内当前的温度、湿度、土壤的水分来实现自动浇水。只要电源充足,无需人工干预。
3、装逼模式:这是为了给来家里玩儿的小朋友们演示专门添加的。就是如果内置模式达不到浇水条件的时候,我们可以通过遥控器为花短暂浇水,按下遥控器,1602屏幕亮起,开始浇水。再按一下屏幕熄灭,浇水停止。
在此之前波波曾经是采用播放音乐的方式,但是开发过程中播放音乐的tone()函数与IRremote库产生了冲突,所以去掉了音乐播放,大家在开发过程中可以通过MP3模块来增加音乐播放,而不要采用蜂鸣器。
相关代码:
这是我优化之前的代码,放出来。现在正在用的代码暂时不方便公开。因为还有联网控制,自己写的服务器前后端。
```cpp
#include
#include
#include
#include
#include
#include
#include
LiquidCrystal_I2C lcd(0x27,16,2);//初始化LCD屏幕地址信息
int temprature; //温度
int humi; //湿度
int ohumi; //土壤湿度
uint8_t wendu[8] = {0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};//温度符号
dht11 DHT11;
#define DHT11PIN 12
#define Tu_A0 0 //土壤模拟信号
#define Tu_D0 7 //土壤数字信号
#define speaker 4 //无源蜂鸣器
#define ssrPin 8 //继电器
#define buttonPin 9 //按钮按键
boolean isPlay = false;
boolean isWatering = false;
int buttonStat = 0;
boolean isLightening = false; //Lcd背光状态
const int kCePin = 1;
const int kIoPin = 2;
const int kSclkPin = 3;
ThreeWire myWire(kIoPin,kSclkPin,kCePin); // IO, SCLK, CE
RtcDS1302
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
#define countof(a) (sizeof(a) / sizeof(a[0]))
//音乐节拍
#define D0 -1
#define D1 262
#define D2 293
#define D3 329
#define D4 349
#define D5 392
#define D6 440
#define D7 494
#define M1 523
#define M2 586
#define M3 658
#define M4 697
#define M5 783
#define M6 879
#define M7 987
#define H1 1045
#define H2 1171
#define H3 1316
#define H4 1393
#define H5 1563
#define H6 1755
#define H7 1971
//列出全部D调的频率
#define WHOLE 1
#define HALF 0.5
#define QUARTER 0.25
#define EIGHTH 0.25
#define SIXTEENTH 0.625
int tune[]=
{
M3,M3,M4,M5,
M5,M4,M3,M2,
M1,M1,M2,M3,
M3,M2,M2,
M3,M3,M4,M5,
M5,M4,M3,M2,
M1,M1,M2,M3,
M2,M1,M1,
M2,M2,M3,M1,
M2,M3,M4,M3,M1,
M2,M3,M4,M3,M2,
M1,M2,D5,D0,
M3,M3,M4,M5,
M5,M4,M3,M4,M2,
M1,M1,M2,M3,
M2,M1,M1
};
float durt[]={
1,1,1,1,
1,1,1,1,
1,1,1,1,
1+0.5,0.5,1+1,
1,1,1,1,
1,1,1,1,
1,1,1,1,
1+0.5,0.5,1+1,
1,1,1,1,
1,0.5,0.5,1,1,
1,0.5,0.5,1,1,
1,1,1,1,
1,1,1,1,
1,1,1,0.5,0.5,
1,1,1,1,
1+0.5,0.5,1+1,
};
int mlength;
void setup(){
Serial.begin(115200);
lcd.init();
lcd.backlight();
//lcd.noBacklight();
lcd.clear();
lcd.createChar(0, wendu);
//初始化时间日期
Rtc.Begin();
Rtc.SetIsWriteProtected(true);
//Rtc.SetDateTime(RtcDateTime(2019, 11, 19, 14, 20, 0));
Rtc.SetIsRunning(true);
//土壤模块接口
pinMode(Tu_A0, INPUT);
pinMode(Tu_D0, INPUT);
//蜂鸣器
pinMode(speaker,INPUT);
mlength = sizeof(tune)/sizeof(tune[0]);
//继电器
pinMode(ssrPin,OUTPUT);
//按键按钮
pinMode(buttonPin,INPUT_PULLUP);
// Start the receiver
irrecv.enableIRIn();
}
void loop(){
RtcDateTime now = Rtc.GetDateTime();
//获取DHT11数据
int chk = DHT11.read(DHT11PIN);
temprature = (int)DHT11.temperature;
humi = (int)DHT11.humidity;
//获取时钟数据
const String nowTime = printTime(now);
lcd.setCursor(0,0);
lcd.print(nowTime);
lcd.setCursor(0,1);
lcd.print(String("")+"T:"+temprature);
lcd.write(byte(0));
lcd.setCursor(6,1);
lcd.print(String("")+"H:"+humi+"%");
//获取土壤数据
ohumi = (int)analogRead(Tu_A0);
lcd.setCursor(12,1);
lcd.print(ohumi,DEC);
//按键控制LCD背光
buttonStat = digitalRead(buttonPin);
if(buttonStat == LOW){
delay(80);
if(buttonStat == LOW && !isLightening){
lcd.backlight();
isLightening = true;
}
}else{
lcd.noBacklight();
isLightening = false;
}
//蜂鸣器报警
/*
if(!isPlay && ohumi > 300 && (int)digitalRead(Tu_D0) == 0){
pinMode(speaker,OUTPUT);
playMusic();
}
*/
//浇水设定
if(!isWatering && ohumi > 300 && (int)digitalRead(Tu_D0) == 0){
//goWater();
lcd.backlight();
isWatering = true;
digitalWrite(ssrPin,HIGH);
Serial.println("Watering Start!");
}else if(isWatering && ohumi <= 240 && (int)digitalRead(Tu_D0) == 0){
lcd.noBacklight();
isWatering = false;
digitalWrite(ssrPin,LOW);
Serial.println("Watering Stop!");
}else{
//nothing to do
}
if (irrecv.decode(&results)) {
Serial.println(results.value, HEX);
irrecv.resume();
}
Serial.println(String("")+"OH:"+ohumi+" D0:"+(int)digitalRead(Tu_D0));
delay(200);
}
/*
void playMusic(){
isPlay = true;
Serial.println("Music Start!");
for(int x=0;x tone(speaker,tune[x]); delay(500*durt[x]); noTone(speaker); } pinMode(speaker,INPUT); Serial.println("Music Stop!"); } */ void goWater(){ isWatering = true; while(ohumi > 500 && (int)digitalRead(Tu_D0) == 0){ digitalWrite(ssrPin,HIGH); ohumi = (int)analogRead(Tu_A0); lcd.setCursor(12,1); lcd.print(ohumi,DEC); Serial.println("Watering!"); } } String printTime(const RtcDateTime& dt) { char buf[17]; snprintf_P(buf, countof(buf), PSTR("%04u-%02u-%02u %02u:%02u"), dt.Year(), dt.Month(), dt.Day(), dt.Hour(), dt.Minute() ); return buf; } ``` 这是写的第二版的代码,编译如果报错,注意看文中加粗文字。如果大家想优化的话,可以加入线程控制。这里我就不分享相关代码了。以上内容仅供初学者练手,高手们可以直接飘过。