Arduino项目: 智能窗户
前段时间参加了一个Arduino的比赛,具体内容就是用Arduino设计一个项目出来
我在的队伍的设计的项目就是智能窗户,智能窗户可以采集本地传感器采集到的环境参数,根据参数具有一套内部的逻辑判断,可以对温度,湿度,光强,粉尘等因素实现智能开闭(例如高温开窗通风),还能把这些参数发布到局域网上,用户访问192.168.4.1
就能够看到
此外用户还自己控制开闭,定时开闭等等,考虑未来写一个手机APP来远程控制,在后台搭一个服务器,来在互联网上发布. 还准备训练一个神经网络放到服务器里跑,这样还可以根据采集的数据(例如过去三四天的温湿度光强等参数)预测未来的天气情况(估计是一个简单的分类任务,做起来也容易)
评委最后批评我们的项目没有实用性,但是本来Arduino做的东西就只是个模型,展示功能而已又不是直接拿去用,不知道评委怎么想的,反正最后距离国一 一步之遥,拿了一个国二
现在比赛已经结束,就把代码放出来开源,供大家参考,逻辑部分我删掉了,剩下的多种传感器的驱动方式可以参考下
技术描述
整个项目硬件分两部分,一部分是Arduino,负责底层的舵机执行和参数采集,另外一部分是NodeMCU,负责将数据发布到网上,时间问题NodeMCU用的是AP模式,未来考虑改成Client和服务器通信
两部分之间是软通信明文沟通,未来当然也可以加密数据传输.
代码
Arduino部分
#include <DHT11.h>
#include <Servo.h>
#include <Stepper.h>
#include <SoftwareSerial.h>
//whetherOpen用于判断窗户能否打开
//isOpen用于判断窗户是否已经打开
boolean whetherOpen = true;
boolean isOpen = false;
int servoOpenPin = 3;
int servoCleanPin = 4;
int steps = 120;
float humidity;
float temperature;
float lightIntensity;
long distance;
dht11 DHT11;
Servo servoClean;
Servo servoOpen;
Stepper aStepper(steps, 5, 6, 9, 10);
SoftwareSerial mySerial(2, 3); //实例化软串口,2为RX,3为TX
void setup()
{
Serial.begin(9600); //硬串口设置
mySerial.begin(9600); //软串口设置
mySerial.listen();
//默认状态窗户关闭
isOpen = false;
//延迟一秒便于Debug
//现在release版延迟0.1秒用于稳定系统
delay(100);
}
void loop()
{
//主程序代码遮掉了,下面只是示意一下怎么用各种传感器
}
float GetTemperature()
{
DHT11.read(A0);
temperature = DHT11.temperature;
humidity = DHT11.humidity;
Serial.print(" Temperature(oC) :");
Serial.println(temperature);
delay(100);
return temperature;
}
float GetHumidity()
{
DHT11.read(A0);
humidity = DHT11.humidity;
temperature = DHT11.temperature;
Serial.print(" Humidity(%) :");
Serial.println(humidity);
delay(100);
return humidity;
}
int GetLightIntensity()
{
/*
* GetLightIntensity is used to get the light intensity
* the light intensity sensor pin should be attached to A2
*/
lightIntensity = analogRead(A2);
Serial.print(" Light intensity(%):");
Serial.println(lightIntensity/770*65);
delay(100);
return lightIntensity/770*65;
}
long GetDistance()
{
int trigPin = 19;
int echoPin = 18;
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(20);
digitalWrite(trigPin, LOW);
distance = pulseIn(echoPin, HIGH);
distance = distance / 59;
if (distance > 400 || distance < 0)
{
distance = 300;
}
Serial.print(" Distance(CM):");
Serial.println(distance);
delay(100);
return distance;
}
void OpenWindow()
{
Serial.println(" Called OpenWindow");
if (!servoOpen.attached())
servoOpen.attach(servoOpenPin);
//servo write 87 means open window
servoOpen.write(87);
delay(1000);
if (servoOpen.attached())
servoOpen.detach();
}
void CloseWindow(int directions)
{
/*
* direction==1 : Turn left
* direction==2 : Turn right
*/
Serial.println(" Called CloseWindow");
if (!servoOpen.attached())
servoOpen.attach(servoOpenPin);
if (directions == 1)
{
servoOpen.write(22);
Serial.println(" Turn left");
delay(1000);
}
else if (directions == 2)
{
servoOpen.write(150);
Serial.println(" Turn right");
delay(1000);
}
if (servoOpen.attached())
servoOpen.detach();
}
void LockWindow(int directions)
{
Serial.println(" Called LockWindow");
CloseWindow(directions);
}
//Note Wawe() is for testing use,will be deleted in release version
void Wawe()
{
if (!servoClean.attached())
servoClean.attach(servoCleanPin);
Serial.println(" Wave!");
servoClean.write(95);
delay(1000);
servoClean.write(175);
delay(1000);
if (servoClean.attached())
servoClean.detach();
}
void Wawe(Servo aServo)
{
/*
* Note:
* For cleanServo, 95 is close, 175 is open
*/
Serial.println(" Wave!");
aServo.write(95);
delay(1000);
aServo.write(175);
delay(1000);
}
void CleanWindow()
{
/*
* Note:
* servoClean is attched to servoCleanPin
* default aStepper pin is 5 6 9 10
* aStepper max speed is set to 60
* default steps per circle is 120
* Wait for adding length
*/
Serial.println(" Called CleanWindow");
if (!servoClean.attached())
servoClean.attach(servoCleanPin);
// Serial.print('1')
aStepper.setSpeed(60);
Serial.println(" Steeped!");
int i;
for (i = 0; i < 4; i++)
{
aStepper.step(-960);
Wawe();
}
if (servoClean.attached())
{
servoClean.detach();
}
}
void GoBack()
{
aStepper.setSpeed(60);
Serial.println(" Steeped Back!");
aStepper.step(960 * 4);
}
NodeMCU部分
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <SoftwareSerial.h>
#include <stdlib.h>
//实例化软串口
SoftwareSerial mySerial(D5, D6);
//实例化服务器
ESP8266WebServer server(80); //端口号设置为80
int requireState = 1;
//Buffers用于接受单个数据传输时的所有字节
//Results用于存储接受到的所有数据
char Buffers[10];
float Results[6];
char aNumber[20];
const char *ssid = "IoTWindow"; // 设置WIFI名称
const char *password = "88888888"; // 设置WIFI密码
void GetData()
{
//请求数据
mySerial.write(requireState);
delay(100);
mySerial.write(requireState);
//存储数据
memset(Buffers, 0, sizeof(Buffers));
//记录传来的数据
int i = 0;
for (int j = 0; j < 6; j++)
{
//只要还在传输数据
while (mySerial.available() > 0)
{
//读取传输来的一个字节
char aByte = mySerial.read();
//只要当前数据的字节流未完成
if (aByte != '\n')
{
Buffers[i++] = aByte; //隐式循环
}
else
{
//若当前数据字节流已经完毕,则将其转化为浮点数
Results[j++] = atof(Buffers);
Serial.println(Results[j - 1]);
//重置Buffers
memset(Buffers, 0, sizeof(Buffers));
i = 0;
}
}
}
}
//设置网页内容,重写方法
void handleRoot()
{
//请求数据
mySerial.write(1);
//存储数据
memset(Buffers, 0, sizeof(Buffers));
//记录传来的数据
int i = 0;
for (int j = 0; j < 5; j++)
{
//只要还在传输数据
while (mySerial.available() > 0)
{
//读取传输来的一个字节
char aByte = mySerial.read();
//只要当前数据的字节流未完成
if (aByte != '\n')
{
Buffers[i++] = aByte; //隐式循环
}
else
{
//若当前数据字节流已经完毕,则将其转化为浮点数
Results[j++] = atof(Buffers);
Serial.println(Results[j - 1]);
//重置Buffers
memset(Buffers, 0, sizeof(Buffers));
i = 0;
}
}
}
delay(1500);
//Results内容分别为:
//温度,湿度,光强,是否打开,能否打开
GetData();
String str = "<!doctype HTML><head><meta charset=\"utf-8\" /><title>智能窗户</title></head><body><h1 align=\"center\">智能窗户实时监测</h1>";
str += "<h2 align=\"center\">当前温度为(℃):";
itoa(int(Results[1]), aNumber, 10);
str += aNumber;
str += "</h2><h2 align=\"center\">当前湿度为(%):";
itoa(int(Results[2]), aNumber, 10);
str += aNumber;
str += "</h2><h2 align=\"center\">当前光照强度为(CD):";
itoa(int(Results[3]), aNumber, 10);
str += aNumber;
str += "</h2><h3 align=\"center\">当前窗户";
if (int(Results[4]) == 1)
str += "已经打开</h3><h3 align=\"center\">";
else
str += "没有打开</h3><h3 align=\"center\">";
if (int(Results[5]) == 1)
str += "窗户前没有小孩,窗户可以正常打开</h3>";
else
str += "窗户前有小孩,窗户默认无法开启</h3>";
str += "</body></html>";
server.send(200, "text/html", str);
}
void setup()
{
delay(1000);
Serial.begin(9600);
mySerial.begin(9600);
Serial.println();
Serial.print("Configuring access point...");
//启动AP热点
WiFi.softAP(ssid, password);
Serial.println(ssid);
//显示热点信息
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
//绑定HTTP服务器/目录下所发布的信息,并启动服务
server.on("/", handleRoot);
server.begin();
Serial.println("HTTP server started");
}
//作用:检测软通信是否可用
void loop()
{
Serial.println("In Loop");
server.handleClient();
}