Arduino 温度,湿度,PM检测
作者:阿圣(Sfan) 发布于:2013-4-26 13:20 Friday 分类:计算机
去年就在x宝上买了一套Arduino 的学习套件.一直没做什么东西.
北京的各种"霾",有了要做一个PM2.5检测小装置的想法.收集各种资料之后.X宝买各种工具和粉尘颗粒传感器.
基本结构: Arduino + enc28j60 + Dht11 + GP2Y1010AU0F + nokia 5110 lcd;
材料: 1.Arduino pro mini 2.ENC28j60以太网模块 3. sharp GP2Y1010AU0F 粉尘传感器 4.DHT11数字温/湿度传感器(这个便宜货精度太差) 5.Nokia 5110 液晶屏模块 6.过线塑料盒 7.各种工具杜帮线.
功能如下:
1.读取当前温度,湿度,可入肺颗粒数.并显示出来.
2.插上网线的话.根据网络环境自动获取IP或设置预设固定IP.并把读取的当前环境数据上传到 yeelink 平台
3.显示当前时间,日期(时间从网络UTC时间服务器读取)
4.可以自己定制相关功能.自己烧写程序
上几张图.
启动状态.右上角一个小图标是网络状态的.
温/湿度显示.
PM2.5 显示
上传到yeelink平台数据显示
Enc28j60 ,Arduino pro min ,nokia 5110
夏普 GP2Y1010AU0F
网络接口 和 电源的接口 电源 5V
粉尘传感器 [GP2Y1010AU0F] 外置 用热熔胶粘在后盖上,可当做整个盒子的支架
DHT11 温/湿度传感器 内嵌在盒子一侧 盒子顶端预留下载接口 (亲,别吐槽焊工 - -" ,电铬铁神马的都是刚买的有木有)
相关代码,库,文档: 写的有点乱
#include <EtherCard.h>
#include <dht11.h>
#include <Time.h>
#include <LCD5110_Graph.h>
#define IN
#define OUT
char VERSION[] ="v1.8";
//enc28j60
int dcPin=10;
static byte mymac[]={0x74,0x69,0x2D,0x30,0x31};
static byte myip[]={192,168,80,160};
static byte mymask[]={255,255,255,0};
static byte gwip[]={192,168,80,1};
static byte dnsip[]={8,8,8,8};
byte Ethernet::buffer[270];
boolean getDHCP=true;
boolean dnslookup=true;
//enc28j60
Stash stash;
//dht11
dht11 DHT11;
int dht11ReadPin=4;
//dht11
//GP2Y1010AU0F
int dustPin=0;
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;
int dustVal=0;
int pm_i=0;
float ppm=0;
//char s[32];
float voltage = 0;
static float dustdensity = 0;
float ppmpercf = 0;
int pm2_5=0;
//GP2Y1010AU0F
//yeelink
#define N 3
char website[] PROGMEM="api.yeelink.net";
char APIKey[] PROGMEM = "441033961344aab**************"; //API KEY
char DeviceID[] PROGMEM = "2463";
const uint16_t SensorID[N] = {3277,3278,3279};
char sensorData[N][30];
uint8_t dataLength[N];
//yeelink
uint32_t lastConnectionTime = 0;
const uint16_t PostingInterval = 5000;
//轮流向服务器发送相应传感器变量 0 <= i <N,
uint8_t i=0;//
//time
boolean timeNeedSet = true;
uint16_t timeSetTimer = 0;
#define TIME_SET_TIMER 4000 //about TIME_SET_TIMER*5s
//nokia 5110
LCD5110 myGLCD(5,6,7,8,9);
extern uint8_t SmallFont[];
//extern uint8_t TinyFont[];
extern uint8_t BigNumbers[];
//extern uint8_t arduino_logo[];
uint8_t temperature_ico[] PROGMEM={0x02,0x05,0x7A,0x84,0x84,0x48};//
uint8_t net_ico_S[] PROGMEM={0x00,0x03,0x05,0x7D,0x7D,0x05,0x03,0xB8,0xA8,0xE8,0x00,0x00,0x00};
uint8_t net_ico_D[] PROGMEM={0x00,0x03,0x05,0x7D,0x7D,0x05,0x03,0xF8,0x88,0x88,0x70,0x00,0x00};
uint8_t net_ico_err[] PROGMEM={0x00,0xFF,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0xFF,0x00,0x00};
uint8_t net_ico_cls[] PROGMEM={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t cls[] PROGMEM={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t pm2_5_ico[] PROGMEM={0x00,0x00,0x00,0xF0,0xF8,0x8C,0x8C,0x8C,0x88,0xF0,0x70,0x00,0x00,0xD0,0x50,0x70,
0x00,0x00,0x00,0x70,0x50,0xD0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x3F,0x3F,0x01,0x01,0x39,0x3D,0x08,0x3C,0x08,0x3C,0x39,0x01,0x01,0x00,0x01,
0x00,0x01,0x01,0x01,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,
0x1C,0x10,0x1C,0x00,0x5C,0x54,0x7C,0x00,0x40,0x20,0x1C,0x02,0x39,0x04,0x38,0x04,
0x38,0x04,0x05,0x07,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t sysinit[] PROGMEM={0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x8F,0x1F,0x1F,0x3D,0xF9,0xF9,0xF3,
0xF7,0x1C,0xFC,0xFC,0xF8,0xC0,0xF0,0xFC,0xFC,0x1C,0x3C,0x7C,0x7C,0x7C,0xEC,0xEC,
0xCC,0x80,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0x01,0xF8,0xFC,0xFC,0xFC,0x1C,0x0C,
0xFC,0xFC,0xFC,0x00,0xFC,0xFC,0xFC,0x04,0x0C,0xFF,0xFF,0xFF,0xFF,0x0C,0x8C,0x80,
0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x80,
0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,
0x03,0x03,0x03,0x01,0x01,0x30,0x30,0x3F,0x3F,0x1F,0x0F,0x03,0x00,0x00,0x03,0x03,
0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
0x03,0x03,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x02,0x00,0x01,0x03,0x03,
0x03,0x03,0x03,0x03,0x03,0x01,0x03,0x03,0x03,0x03,0x00,0x03,0x03,0x03,0x00,0x03,
0x03,0x03,0x00,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00};
//nokia 5110
void setup()
{
myGLCD.InitLCD();
myGLCD.setFont(SmallFont);
Serial.begin(115200);
//myGLCD.drawBitmap(0, 0, arduino_logo, 84, 48);
myGLCD.drawLine(0,10,83,10);
myGLCD.drawLine(70,0,70,10);
myGLCD.print("--:-- --/--",2,2);
myGLCD.drawBitmap(0,15, sysinit, 84, 24);
myGLCD.print(VERSION,55,15);
myGLCD.drawBitmap(71,1, net_ico_err, 13, 8);
myGLCD.print("------ By:SFan",0,40);
myGLCD.update();
pinMode(ledPower,OUTPUT);//ledPower GP2Y1010AU0F
Serial.print("Version:");
Serial.println(VERSION);
Serial.println("Ethernet init...");
if(ether.begin(sizeof Ethernet::buffer,mymac,dcPin)==0){
Serial.println("Failed to access Ethernet controller");
}
else{
Serial.println("DHCP");
myGLCD.drawBitmap(71,1, net_ico_D, 13, 8);
myGLCD.update();
if(!ether.dhcpSetup()){
myGLCD.drawBitmap(71,1, net_ico_S, 13, 8);
myGLCD.update();
getDHCP=false;
Serial.println("DHCP failed");
ether.staticSetup(myip,gwip);
ether.copyIp(ether.dnsip,dnsip);
ether.copyIp(ether.mymask,mymask);
}
ether.printIp("My IP:",ether.myip);
// ether.printIp("Netmask:",ether.mymask);
ether.printIp("GW IP:",ether.gwip);
ether.printIp("Dns:",ether.dnsip);
if(!ether.dnsLookup(website)){
myGLCD.drawBitmap(71,1, net_ico_err, 13, 8);
myGLCD.update();
dnslookup=false;
}
ether.printIp("website:",ether.hisip);
}
}
void loop()
{
ether.packetLoop(ether.packetReceive());
// pmLoop();
if( millis() < lastConnectionTime || millis() - lastConnectionTime > PostingInterval){
Serial.println(i);
get_Send_String(i);
if(dnslookup){
send_Data(i);
}else{
lastConnectionTime=millis();
}
i++;
if (i == N) i=0;
}
}
static void dht11Read(){
// Serial.println("\n");
int chk = DHT11.read(dht11ReadPin);
Serial.print("Read sensor: ");
switch (chk)
{
case DHTLIB_OK:
Serial.println("OK");
break;
case DHTLIB_ERROR_CHECKSUM:
Serial.println("Checksum error");
break;
case DHTLIB_ERROR_TIMEOUT:
Serial.println("Time out error");
break;
default:
Serial.println("Unknown error");
break;
}
Serial.print("Humidity (%): ");
Serial.println((float)DHT11.humidity, 2);
Serial.print("Temperature (oC): ");
Serial.println((float)DHT11.temperature-2, 2);
myGLCD.drawBitmap(0,15, cls, 84, 25);
myGLCD.update();
myGLCD.drawBitmap(35, 30, temperature_ico, 6, 8);
myGLCD.setFont(SmallFont);
myGLCD.print("%",73,32);
myGLCD.setFont(BigNumbers);
myGLCD.printNumI(DHT11.temperature-2,5,15);
myGLCD.printNumI(DHT11.humidity,45,15);
myGLCD.update();
}
static void pmData(){
pmLoop();
Serial.println(dustVal);
voltage = ppm/pm_i*0.0049;
dustdensity = 0.17*voltage-0.1;
ppmpercf = (voltage-0.0256)*120000;
if (ppmpercf < 0)
ppmpercf = 0;
if (dustdensity < 0 )
dustdensity = 0;
if (dustdensity > 0.5)
dustdensity = 0.5;
pm_i=0;
ppm=0;
pm2_5=dustdensity*1000;
Serial.print("voltage :");
Serial.println(voltage);
Serial.print("dustdensity :");
Serial.println(dustdensity);
Serial.print("ppmpercf :");
Serial.println(ppmpercf);
myGLCD.drawBitmap(0,15, cls, 84, 25);
myGLCD.update();
myGLCD.drawBitmap(8,15, pm2_5_ico, 30, 24);
myGLCD.setFont(BigNumbers);
myGLCD.printNumI(pm2_5,40,15);
myGLCD.update();
}
void pmLoop(){
pm_i=pm_i+1;
digitalWrite(ledPower,LOW); // power on the LED
delayMicroseconds(delayTime);
dustVal=analogRead(dustPin); // read the dust value
ppm = ppm+dustVal;
delayMicroseconds(delayTime2);
digitalWrite(ledPower,HIGH); // turn the LED off
delayMicroseconds(offTime);
}
void get_Send_String(uint8_t k){
switch(k){
case 0:{
dht11Read();
dataLength[k]=sprintf(sensorData[k],"{\"value\":%d}",DHT11.temperature-2);
break;}
case 1:{
dht11Read();
dataLength[k]=sprintf(sensorData[k],"{\"value\":%d}",DHT11.humidity);
break;}
case 2:{
pmData();
// Serial.println(dustdensity*1000);
dataLength[k]=sprintf(sensorData[k],"{\"value\":%d}",pm2_5);
}
}
}
void send_Data(uint8_t j) {
// Create a Post for yeelink server,
// and send request saving sessionID
Serial.println(sensorData[j]);
Serial.println(SensorID[j]);
Serial.println();
Stash::prepare(PSTR("POST /v1.0/device/$F/sensor/$D/datapoints HTTP/1.1" "\r\n"
"Host: api.yeelink.net" "\r\n"
"U-ApiKey: $F" "\r\n"
"Content-Length: $D" "\r\n"
"Content-Type: application/x-www-form-urlencoded" "\r\n" "\r\n"
"$S" "\r\n"),
DeviceID,SensorID[i],APIKey,dataLength[i],sensorData[i]);
// ether.tcpSend();
if(timeNeedSet){
setupTime();
}
else{
ether.tcpSend();
displayClock();
}
lastConnectionTime = millis();
}
#define REQEST_TIMEOUT 10000
void setupTime(){
uint8_t session_id;
session_id = ether.tcpSend();
uint32_t requestTimer = millis() + REQEST_TIMEOUT;
while(millis() < requestTimer){
ether.packetLoop(ether.packetReceive());
char bufx[21];
const char* reply = ether.tcpReply(session_id);
if(reply !=0){
for(uint8_t I=0;I<21;I++){
bufx[I]=reply[50+I];
}
tmElements_t time1;
timeconvert(bufx,&time1);
time_t second = makeTime(time1);
setTime(second);
adjustTime(8*60*60);
timeNeedSet=false;
break;
}
}
}
void displayClock(){
// digital clock display of the time
timeSetTimer++;
if (timeSetTimer>TIME_SET_TIMER) {
timeSetTimer=0;
timeNeedSet=true;
}
myGLCD.setFont(SmallFont);
int h=hour();
int m=minute();
int mo=month();
int d=day();
int x=2;
if(h<10){
myGLCD.print("0",x,2);
x+=6;
myGLCD.printNumI(h,x,2);
x+=6;
}else{
myGLCD.printNumI(h,x,2);
x+=12;
}
myGLCD.print(":",x,2);
x+=6;
if(m<10){
myGLCD.print("0",x,2);
x+=6;
myGLCD.printNumI(m,x,2);
x+=6;
}else{
myGLCD.printNumI(m,x,2);
x+=12;
}
myGLCD.print(" ",x,2);
x+=6;
if(mo<10){
myGLCD.print("0",x,2);
x+=6;
myGLCD.printNumI(mo,x,2);
x+=6;
}else{
myGLCD.printNumI(mo,x,2);
x+=12;
}
myGLCD.print("/",x,2);
x+=6;
if(d<10){
myGLCD.print("0",x,2);
x+=6;
myGLCD.printNumI(d,x,2);
x+=6;
}else{
myGLCD.printNumI(d,x,2);
x+=12;
}
myGLCD.update();
Serial.print(year());
Serial.print("-");
Serial.print(month());
Serial.print("-");
Serial.print(day());
Serial.print(" ");
Serial.print(hour());
Serial.print(":");
Serial.print(minute());
}
//比较周数,成功返回0-6的数,错误返回7
//p代表周数,取周数前3个字母,如Mon代表周1,以此类推
//改动周几不影响返回的时间值,可以通过改动日期的日数来达到修改时间
//比较月份,成功返回0-11的数,错误返回12
//P 为月份的前三个字母,如Feb代表二月,以此类推
int monthcmp( IN char *p)
{
char *month[]={
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
int i;
for(i=0;i<12;i++){
if(strcmp(p,month[i])==0)
break;
}
if(i==12)
{
return i;
}
return i;
}
//将字串格式的时间转换为结构体,返回距离1970年1月1日0:0:0的秒数,当字符串格式错误或超值时返回0
//BUF 为类似Tue May 15 14:46:02 2007格式的,p为时间结构体
void timeconvert(IN char *buf,OUT tmElements_t *p)
{
char cmonth[4];
int16_t td,th,tm,ts,ty;
sscanf(buf,"%d %s %d %d:%d:%d",&td,cmonth,&ty,&th,&tm,&ts);
//sscanf("2012 Aug " ,"%4d %s",&ty,cmonth);
p->Year = ty - 1970;
p->Month = monthcmp(cmonth) + 1;
p->Day = td;
p->Hour = th;
p->Minute = tm;
p->Second = ts;
}libraries.rar (DHT11,ethercard,LCD5110_Graph 相关库)
标签: Arduino
评论:
2015-05-26 16:24
228
voltage = ppm/pm_i*0.0049;
229
dustdensity = 0.17*voltage-0.1;
230
ppmpercf = (voltage-0.0256)*120000;
231
if (ppmpercf < 0)
232
ppmpercf = 0;
233
if (dustdensity < 0 )
234
dustdensity = 0;
235
if (dustdensity > 0.5)
236
dustdensity = 0.5;
237
pm_i=0;
238
ppm=0;
239
pm2_5=dustdensity*1000;
240
Serial.print("voltage :");
241
Serial.println(voltage);
242
Serial.print("dustdensity :");
243
Serial.println(dustdensity);
244
Serial.print("ppmpercf :");
245
Serial.println(ppmpercf);
246
myGLCD.drawBitmap(0,15, cls, 84, 25);
247
myGLCD.update();
248
myGLCD.drawBitmap(8,15, pm2_5_ico, 30, 24);
249
myGLCD.setFont(BigNumbers);
250
myGLCD.printNumI(pm2_5,40,15);
251
myGLCD.update();
252
}
请问这个算法什么意思
2013-05-23 21:29













2016-03-24 15:13