“BOXZ mini/zh”的版本间的差异

来自Microduino Wikipedia
跳转至: 导航搜索
实验原理
 
(未显示同一用户的7个中间版本)
第3行: 第3行:
 
|
 
|
 
==概述==
 
==概述==
*项目名称:Microduino机器人小车
+
*项目名称:WiFi气象站
*目的:通过Microduino Joypad来控制BOXZ mini机器人小车
+
*目的:获取身边实时的温度、湿度、光照甚至pm2.5数据
*难度:高级
+
*难度:中
*耗时:3小时
+
*耗时:5小时
*制作者:Microduino Studio-YLB
+
*制作者:
 +
*简介:
 +
它能够获取你身边实时的温度、湿度、光照甚至pm2.5数据,并且在屏幕上显示出来,如果你需要,甚至可以将其接入互联网,只要有一台能上网的手机或者计算机,任何地方、任何时候都能查看到这些数据。而这套系统完全由Microduino来实现,非常简单。
 
==材料清单==
 
==材料清单==
 
*Microduino设备
 
*Microduino设备
第14行: 第16行:
 
|模块||数量||功能
 
|模块||数量||功能
 
|-
 
|-
|[[Microduino-Core/zh]]||1||核心板(Joypad)
+
|[[Microduino-Core+/zh]]||1||核心板
 
|-
 
|-
|[[Microduino-Core+/zh]]||1||核心板(Robot)
+
|[[Microduino-USBTTL/zh]] ||1||下载程序
 
|-
 
|-
|[[Microduino-USBTTL/zh]]||1||下载程序
+
|[[Microduino-WiFi/zh]] ||1||连接网络
 
|-
 
|-
|[[Microduino-nRF24/zh]]||2||无线通讯
+
|[[Microduino-Tem&Hum/zh]] ||1||数字温湿度传感器
 
|-
 
|-
|[[Microduino-Joypad/zh]]||1||遥控
+
|[[Microduino-Air/zh]] ||1||空气质量传感器
 
|-
 
|-
|[[Microduino-TFT/zh]]||1||显示
+
|[[Microduino-Light/zh]] ||1||光照传感器
 
|-
 
|-
|[[Microduino-Motor/zh]]||1||四轴电机驱动
+
|[[Microduino-OLED/zh]] ||1||显示
|-
 
|[[Microduino-Robot/zh]]||1||驱动连接底板
 
 
|}
 
|}
 
*其他设备
 
*其他设备
第35行: 第35行:
 
|模块||数量||功能
 
|模块||数量||功能
 
|-
 
|-
|机器小车机架||1||车体
+
|Micro-USB线||1||下载程序、供电
 
|-
 
|-
|螺丝||18||固定
+
|[[Microduino-USBTTL/zh]] ||1||下载程序
 
|-
 
|-
|螺母||8||固定
+
|GP2Y1010AU0F ||1||pm2.5传感器
 
|-
 
|-
|Micro-USB数据线||1||下载程序
+
|螺丝 ||7||固定模块
 
|-
 
|-
|车轮||1||车体
+
|螺丝刀 ||1||固定螺丝
 
|-
 
|-
|电机||1||驱动车轮
+
|外壳 ||1||
|-
 
|电池||1||供电
 
 
|}
 
|}
 +
[[File:气象站物料.jpg||600px|center|thumb]]
 +
==实验原理==
 +
气象站专用板上安装了多参数传感器,包括数字温湿度传感器(Microduino-Tem&Hum)、光照强度传感器(Microduino-Light)、空气质量传感器(Microduino-Air)和pm2.5传感器(GP2Y1010AU0F)。
 +
每个传感器均与Microduino-Sensorhub连接,由Microduino核心(Microduino Core+)对传感器数据分析处理,以直观的文字提示方式在OLED中显示。
 +
同时通过Microduino CC3000模块(wifi)使Microduino核心连接到网络,与mCotton物联网平台通讯
 +
并以直观的文字和图表信息反馈给用户,用户只需要用通过能上网的手机或者计算机,在任何地方任何时候都能查看到这些数据,用户甚至可以设置传感器值来触发微博,
 +
与大家一起分享你的生活。
 +
总的来说,用户通过气象站可以随时随地感受的身边环境的变化,把无形变有形,去感受大自然的瞬息万变。
 +
[[File:Wifistationtheory.jpg||600px|center|thumb]]
  
==实验原理==
+
本系统由传感器、协调器、网络适配器、OLED显示器、mCotton物联网平台五个部分组成,综合了传感技术、网络通信技术、OLED显示技术和物联网技术。传感器主要完成温度、湿度、光照参数、空气质量的采集,协调器分析处理采集的数据,同时通过网络适配器连接到网络与mCotton物联网平台通信,从而可以在mCotton物联网平台下查看到这些数据。
机器人小车种类比较多,如循迹,壁障,蓝牙遥控小车,电脑鼠等。但是其行走控制方式基本是一样的,无非就是前后左右四个方向运动。当然结构上会有一定区别,不同功能需要采用不同传感器,本次我们主要使用两轮驱动,通过控制两个轮子的旋转方向,实现前进后退,旋转等功能,当然还要加上万向轮,这样才能保持平衡。
+
[[File:Wifistationtheory1.jpg||600px|center|thumb]]
该小车结构简单,主要包括三个方面:车轮、车身、控制系统。
+
*管理平台构成
1)车轮采用两个减速电机,扭力大,可PWN调速,控制简单。
+
管理平台大致可分为两个部分:一是Microduino核心控制,负责采集传感器数据,并且连接到互联网。二是mCotton物联网平台,负责将数据以曲线形式直观显示给用户,用户可以随时随地查看,并且可以设置微博触发,分享你的生活环境。如图2-2所示:
2)车身采用亚克力板,大小:8cm*8cm*8cm。
+
*主要传感器
3)整个控制系统包括四个部分:
+
[[File:Wifistationtheory2.jpg||600px|center|thumb]]
*供电系统
+
下图展示了本系统的处理流程。数据采集系统:主要负责对环境温度、湿度、光照强度等数据的采集。传感器采集的数据上传到Microduino核心,具有扩展方便等优点。
因为BOXZ体积比较小,所以采用锂电池。
+
无线传输系统:该系统主要将设备采集到的数据,通过无线网络传送到服务器上,使用WiFi传输数据。
*中央处理器
+
数据处理系统:该系统负责对采集的数据进行上传存储、直观显示,用户可随时随地通过电脑和手机等终端进行查询。
中央处理器是整个小车的核心,就像电脑的CPU,人的大脑,有一定思维能力,能够处理复杂事件。采用Microduino-Core作为核心。
+
[[File:Wifistationtheory3.jpg||600px|center|thumb]]
*无线通讯
 
小车采用Microduino-nRF24无线通讯方案,通讯速度响应快,控制范围:空阔地域大约100米。
 
*电机控制
 
采用Microduino-Motor直流电机驱动模块,一个模块能够驱动两个电机。同时结合Microduino-Robot底板,将中央处理器和直流电机模块连接起来。
 
  
 
==文档==
 
==文档==
 
==调试过程==
 
==调试过程==
 +
*搭建服务器
 +
气象站既然要连入互联网,一个用来储存和显示的服务器必不可少,首先我们需要搭建好一个网络服务器。
 +
*关于mCotton
 +
目前定位于做一个开放的通用物联网平台,主要提供传感器数据的接入,存储和展现服务,为所有的开源软硬件爱好者、制造型企业,提供一个物联网项目的平台,
 +
使得硬件和制造业者能够在不关心服务器实现细节和运维的情况下,拥有交付物联网化的电子产品的能力。
 +
我们只需在mCotton注册一个账号,它会提供给你一个唯一的API KEY,这个便是用来在服务器里判别唯一身份之用的。
 +
mCotton作为一个开放的公共物联网接入平台,目的是为服务所有所有的爱好者和开发者,使传感器数据的接入、存储和展现变得轻松简单。
 +
下面我们介绍一下如何使用mCotton平台完成您的轻松接入。
 +
*注册
 +
打开mCotton的主页:somvpn.cn:3000,在页面中点击”Sign in/Join”,然后会弹出登录/注册框,再点击“Create account”进入用户注册页面。
 +
[[File:mcottonsign1.jpg||600px|center|thumb]]
 +
在用户注册页面,填写相关信息后点击完成注册
 +
[[File:mcottonsign2.jpg||600px|center|thumb]]
 +
*增加设备
 +
登陆后点击”Projects“进入工程页面
 +
[[File:mcottonsign3.jpg||600px|center|thumb]]
 +
在工程页面中找到”Weather Station”项目,点击其中的“Assemble to My Devices”按钮,可以添加自己的设备
 +
[[File:mcottonsign4.jpg||600px|center|thumb]]
 +
在“Name”中输入自己的设备名称,然后点击“Submit”按钮发布
 +
[[File:mcottonsign5.jpg||600px|center|thumb]]
 +
*获得APIKEY
 +
发布完毕后就可以在“My Garage”页面中看到自己的设备
 +
[[File:mcottonsign6.jpg||600px|center|thumb]]
 +
找到自己发布的气象站设备,可以看到该设备专属的设备ID,记下它
 +
[[File:mcottonsign7.jpg||600px|center|thumb]]
 +
*下载程序
 +
将Microduino-Core+与Microduino-USBTTL叠加(无上下顺序),通过USB数据线与电脑连接起来
 +
[[File:download1.jpg||600px|center|thumb]]
 +
确认你搭建了Microduino的开发环境,否则参考附录1-Arduino IDE安装指导。
 +
[[File:Gettingstarted.jpg||600px|center|thumb]]
 +
打开Arduino IDE编程软件,点击 【文件】->【打开】
 +
[[File:Dl1.jpg||600px|center|thumb]]
 +
浏览到项目程序地址,点击“weatherCC3000.ino”程序打开
 +
[[File:WiFiStationopen.jpg||600px|center|thumb]]
 +
[[File:WiFiStationopen2.jpg||600px|center|thumb]]
 +
在def.h文件中需要设置相应的配置参数:
 +
#define WLAN_SSID   “你要连接的WiFi的网络名”
 +
#define WLAN_PASS   “你要连接的WiFi的密码”
 +
#define WEBSITE   “设置的服务器地址”
 +
#define WEBSITEPORT        “设置的服务器端口号”
 +
#define APP_KIT_ID   “步骤3获得的设备ID号”
 +
[[File:WiFiStationopen3.jpg||600px|center|thumb]]
 +
点击“工具”,在板选项里面选择板卡(Microduino-Core+),在处理器选项里面选择处理器(Atmega644pa@16M,5V),再在端口选项里面选择正确的端口号,然后直接烧录程序
 +
[[File:WiFiStationopen4.jpg||600px|center|thumb]]
 +
把用到的设备叠加起来。
 +
*Microduino-Sensorhub
 +
*Microduino-USBTTL
 +
*Microduino-Core+
 +
*Microduino-WIFI
 +
设置完成后就可以在OLED上看到各个传感器的数据
 +
[[File:气象站步骤.jpg||600px|center|thumb]]
 +
同时在mCotton上设置好的设备上也能看到气象站上传的数据
 +
[[File:WiFiStation10.jpg||600px|center|thumb]]
 +
 
==程序说明==
 
==程序说明==
 +
*主程序部分
 +
<source lang="cpp">
 +
//1,屏幕显示部分=============================
 +
#include"Arduino.h"
 +
#include "U8glib.h"
 +
//2,传感器部分================================
 +
#include <Wire.h>
 +
#include "I2Cdev.h"
 +
#include <AM2321.h>
 +
#include <SoftwareSerial.h>
 +
//3,WIFI部分================================
 +
#include <Adafruit_CC3000.h>
 +
#include <ccspi.h>
 +
#include <SPI.h>
 +
#include <string.h>
 +
#include "utility/debug.h"
 +
//4,自定义部分=============================
 +
#include "def.h"
 +
#include "oled.h"
 +
#include "wifi.h"
 +
#include "sensor.h"
 +
 +
#define INTERVAL_LCD            200        //OLED及传感器刷新时间间隔   
 +
#define INTERVAL_NET            30000      //传感器数据上传时间间隔 
 +
 +
unsigned long lcd_time = millis();          //OLED及传感器更新计时器
 +
unsigned long net_time = millis();          //传感器数据上传更新计时器
 +
 +
void setup(void)
 +
{
 +
    Serial.begin(115200);    //初始化波特率
 +
    setup_wifi();            //初始化WIFI
 +
}
 +
 +
void loop(void)
 +
{
 +
 +
    if (lcd_time > millis()) lcd_time = millis();
 +
    if (millis() - lcd_time > INTERVAL_LCD)
 +
    {
 +
        SensorUpdate();        //更新传感器
 +
        volcd(sensorTemp, sensorHumi, sensorLight, sensorPM25, sensorEtoh);  //更新OLED显示
 +
        lcd_time = millis();    //更新计时器
 +
    }
 +
 +
    if (net_time > millis()) net_time = millis();
 +
    if (millis() - net_time > INTERVAL_NET)
 +
    {
 +
        updateWeatherData(sensorTemp, sensorHumi, sensorLight, sensorPM25, sensorEtoh);  //上传传感器数据
 +
        net_time = millis();    //更新计时器
 +
    }
 +
}
 +
</source>
 +
*用户配置部分
 +
<source lang="cpp">
 +
#define WLAN_SSID      "YourSSID"      //WIFI网络名
 +
#define WLAN_PASS      "YourPassword"    //WIFI密码 
 +
 +
#define WEBSITE "somevpn.cn"        //服务器网址
 +
#define WEBSITEPORT 3000        //服务器端口号
 +
#define APP_KIT    "YourDeviceID"    //设备ID号#define APP_KIT    "YourDeviceID"    //设备ID号
 +
 +
#define WEBPAGE "/api/v1.0/d"
 +
#define WEBUTTONPAGE "/api/v1.0/ce"
 +
</source>
 +
*OLED显示部分
 +
<source lang="cpp">
 +
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);    //设置OLED型号
 +
//-------字体设置,大、中、小
 +
#define setFont_L u8g.setFont(u8g_font_7x13)
 +
#define setFont_M u8g.setFont(u8g_font_fixed_v0r)
 +
#define setFont_S u8g.setFont(u8g_font_chikitar)
 +
 +
//温度计图案
 +
const unsigned char bmp_tem[] U8G_PROGMEM =
 +
{
 +
    0xE0, 0x81, 0x30, 0x83, 0x10, 0x82, 0x10, 0x82, 0x10, 0xFA, 0x10, 0x82,0x10, 0x82, 0x10, 0xFA, 0x10, 0x82, 0xD0, 0x82, 0xD0, 0xFA, 0xD0, 0x82,0xD0,                   
 +
0x82, 0xD0, 0xFA, 0xD0, 0x82, 0xD0, 0x82, 0xD0, 0xFA, 0xD0, 0x82,0xD0, 0x82, 0xD8, 0x86, 0xC4, 0x88, 0xF2, 0x93, 0xFB, 0xB7, 0xF9, 0xA7,0xFD, 0xAF, 0xFD,
 +
0xAF, 0xF9, 0xA7, 0xFA, 0x97, 0xF2, 0x93, 0xC4, 0x88,0x18, 0x86, 0xF0, 0x83
 +
};
 +
 +
//水滴图案
 +
const unsigned char bmp_hum[] U8G_PROGMEM =
 +
{
 +
    0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x80, 0x03, 0x08, 0x80, 0x03, 0x18, 0x80, 0x07, 0x1C, 0xC0, 0x07, 0x3C, 0xC0, 0x07, 0x3E, 0xE0,0x0F, 0x3E,
 +
0xE0, 0x0F, 0x7A, 0xF0, 0x1F, 0x7B, 0xF8, 0x1F, 0x72, 0xF8,0x1F, 0x3E, 0xF8, 0x3F, 0x1C, 0xFC, 0x3F, 0x00, 0xFC, 0x7F, 0x00, 0xFE,0x7F, 0x00, 0xFE, 0x7F,
 +
0x00, 0xFE, 0x7F, 0x00, 0xFF, 0xFF, 0x00, 0xFF,0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xF3, 0xFF, 0x00, 0xF2, 0x7F, 0x00, 0xE6,0x7F, 0x00, 0xC6, 0x7F, 0x00, 0x0E,
 +
0x3F, 0x00, 0x3C, 0x1E, 0x00, 0xF8,0x1F, 0x00, 0xE0, 0x07, 0x00, 0x80, 0x01
 +
};
 +
 +
//显示初始化界面
 +
void osd_setup(int _osd_setup, char *_osd_text)
 +
{
 +
    u8g.firstPage();
 +
    do
 +
    {
 +
        setFont_L;            //设置字体大 、
 +
 +
        u8g.setPrintPos(4, 30);        //设置文字开始坐标
 +
        u8g.print(_osd_text);        //显示文字
 +
        u8g.drawFrame(0, 48, 128, 14);
 +
        if(_osd_setup)                //显示进度条
 +
            u8g.drawBox(0+2, 48+2, map(_osd_setup, 0, 5, 0, 128-4), 14-4);
 +
    }
 +
    while( u8g.nextPage() );
 +
}
 +
 +
//显示函数
 +
void volcd(float temp, float humi, float light, float pm25, float etoh)
 +
{
 +
    u8g.firstPage();
 +
    do
 +
    {
 +
        u8g.setDefaultForegroundColor();
 +
        u8g.drawXBMP( 4, 1, 15, 32, bmp_tem);
 +
        u8g.drawXBMP( 70, 2, 24, 30, bmp_hum);
 +
 +
        setFont_M;                            //设置字体为大
 +
        u8g.setPrintPos(20, 16);        //设置文字开始坐标
 +
        u8g.print("`C ");
 +
        setFont_L;                            //设置字体为大
 +
        u8g.setPrintPos(20, 32);        //设置文字开始坐标
 +
        u8g.print(temp , 1);            //温度
 +
 +
        setFont_M;                            //设置字体为大
 +
        u8g.setPrintPos(100, 16);        //设置文字开始坐标
 +
        u8g.print("%");
 +
        setFont_L;                            //设置字体为大
 +
        u8g.setPrintPos(100, 32);        //设置文字开始坐标
 +
        u8g.print(humi , 0);            //湿度
 +
 +
        setFont_L;                      //设置字体
 +
        u8g.setPrintPos(4, 49);          //设置文字开始坐标
 +
        u8g.print(light , 0);      //光照强度
 +
        setFont_M;                      //设置字体
 +
        u8g.print(" Lux");
 +
 +
        setFont_L;                      //设置字体
 +
        u8g.setPrintPos(4, 63);          //设置文字开始坐标
 +
        u8g.print(pm25 , 0);      //光照强度
 +
        setFont_M;                      //设置字体
 +
        u8g.print(" ug/m3");
 +
 +
 +
        setFont_L;                      //设置字体
 +
        u8g.setPrintPos(80, 49);          //设置文字开始坐标
 +
        u8g.print(etoh , 0);      //光照强度
 +
        setFont_M;                      //设置字体
 +
        u8g.print(" ppm");
 +
 +
        setFont_M;                            //设置字体为大
 +
        u8g.setPrintPos(80, 63);        //设置文字开始坐标
 +
        u8g.print(" LED:");
 +
    }
 +
    while( u8g.nextPage() );
 +
}
 +
 
 +
void volcdsetup(char *zi, unsigned int x, unsigned int y)
 +
{
 +
    //#ifdef OLED
 +
    u8g.firstPage();
 +
    do
 +
    {
 +
        setFont_L;
 +
        u8g.setPrintPos(x, y);
 +
        u8g.print(zi);
 +
    }
 +
    while( u8g.nextPage() );
 +
    //#endif
 +
}
 +
</source>
 +
*传感器数据采集部分
 +
<source lang="cpp">
 +
#include <SoftwareSerial.h>
 +
#include <AM2321.h>
 +
 +
AM2321 am2321;
 +
SoftwareSerial pmSerial(4, 5);        //PM2.5传感器通讯软串口
 +
 +
float sensorTemp;      //温度值
 +
float sensorHumi;      //湿度值
 +
float sensorPM25;      //pm2.5浓度
 +
float sensorLight;      //光照强度
 +
float sensorEtoh;      //空气质量
 +
 +
//读取pm2.5传感器
 +
float PM25()
 +
{
 +
    int data_s = 0;        //串口接收数据
 +
    int num = -1;          //串口接收数据计数
 +
    int sum = 0;          //校验和
 +
    int cal[5];            //接收数据缓存
 +
    float dustDensity = 0;    //PM2.5浓度
 +
 +
    pmSerial.begin(2400);        //首先启动软串口
 +
    pmSerial.flush();              //清空串口缓存
 +
 +
    while(1)
 +
    {
 +
        if(pmSerial.available() > 0)    //串口缓存有数据
 +
        {
 +
            data_s = pmSerial.read();        //读取串口缓存数据
 +
            if(data_s == 0xAA)                //得到数据帧起始位
 +
            {
 +
                num = 0;                        //开始计数
 +
            }
 +
            else if(num >= 0)
 +
            {
 +
                num++;                        //读到数据,计数+1
 +
                cal[num-1] = data_s;    //数据保存到缓存中
 +
                if(num == 6)              //读到数据帧最后一位
 +
                {
 +
                    sum = cal[0] + cal[1] + cal[2] + cal[3];   
 +
//计算校验和
 +
                    if(sum == cal[4] && cal[5] == 0xFF)         
 +
//校验和匹配,数据帧最后一位为0xFF,说明接收的数据帧正常
 +
                    {
 +
                      dustDensity = (cal[0]*256+cal[1])*(5.0/1024)*550;                        //计算PM2.5浓度,单位ug/m3
 +
                    }
 +
                    else            //接收的数据不正常
 +
                    {
 +
                        dustDensity = 0;    //浓度清零
 +
                    }
 +
                    break;
 +
                }
 +
            }
 +
        }
 +
    }
 +
    pmSerial.end();            //关闭软串口
 +
    return dustDensity;    //返回值
 +
}
 +
 +
//更新传感器数据
 +
void SensorUpdate()
 +
{
 +
 +
    //获取pm2.5浓度
 +
    sensorPM25 = PM25();
 +
    //获取温度,湿度
 +
    am2321.read();
 +
    sensorTemp = am2321.temperature / 10.0;
 +
    sensorHumi = am2321.humidity / 10.0;
 +
    //获取光照强度
 +
    sensorLight = map(analogRead(A0), 0, 1023, 0, 255);
 +
    //获取空气质量
 +
    sensorEtoh = map(analogRead(A2), 0, 1023, 0, 30);
 +
}
 +
</source>
 +
*WiFi控制部分
 
<source lang="cpp">
 
<source lang="cpp">
 +
// These are the interrupt and control pins
 +
#define ADAFRUIT_CC3000_IRQ  2  // MUST be an interrupt pin!
 +
// These can be any two pins
 +
#define ADAFRUIT_CC3000_VBAT  9
 +
#define ADAFRUIT_CC3000_CS    10
 +
#define WLAN_SECURITY  WLAN_SEC_WPA2
 +
#define IDLE_TIMEOUT_MS          1000
 +
// Use hardware SPI for the remaining pins
 +
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
 +
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIV2); // you can change this clock speed but DI
 +
 +
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
 +
 +
uint32_t ip;
 +
Adafruit_CC3000_Client www;
 +
/**************************************************************************/
 +
/*!
 +
@brief  Tries to read the IP address and other connection details
 +
*/
 +
/**************************************************************************/ •R");
 +
            Serial.println(F("Failed!"));
 +
            return false;
 +
        }
 +
        else
 +
        {
 +
            Serial.println("\n2/4 connect AP OK");
 +
            return true;
 +
        }
 +
    }
 +
    break;
 +
    case 2:
 +
    {
 +
        Serial.println("\n 3/4 dhcp READY");
 +
        if(!voCC3000_get_dhcp())
 +
        {
 +
            Serial.println("3/4 dhcp ERROR");
 +
            Serial.println(F("Failed!"));
 +
            return false;
 +
        }
 +
        else
 +
        {
 +
            Serial.println("3/4 dhcp OK");
 +
            return true;
 +
        }
 +
 +
    }
 +
    break;
 +
    case 3:
 +
    {
 +
        Serial.println("\n 4/4 server READY");
 +
        if(!voCC3000_get_server_ip())
 +
        {
 +
            Serial.println("4/4 server ERROR");
 +
            Serial.println(F("Failed!"));
 +
            return false;
 +
        }
 +
        else
 +
        {
 +
            Serial.println("4/4 server OK");
 +
            return true;
 +
        }
 +
    }
 +
    break;
 +
    }
 +
}
 +
 +
 +
void setup_wifi()
 +
{
 +
 +
    bool sta;
 +
 +
    osd_setup(1, "INIT WIFI");
 +
    if(voCC3000_init(0))
 +
    {
 +
        osd_setup(2, "CONNECT AP");
 +
        if(voCC3000_init(1))
 +
        {
 +
            osd_setup(3, "GET DHCP");
 +
            if(voCC3000_init(2))
 +
            {
 +
                osd_setup(4, "GET SERVER");
 +
                if(voCC3000_init(3))
 +
                    sta =  true;
 +
                else
 +
                    sta = false;
 +
            }
 +
            else
 +
                sta = false;
 +
        }
 +
        else
 +
            sta = false;
 +
    }
 +
    else
 +
        sta = false;
 +
 +
    if(!sta)
 +
        osd_setup(0, "NET ERROR");
 +
 +
    //----------------------------
 +
    osd_setup(5, "INIT SENSOR");
 +
}
 +
 +
 +
void updateWeatherData(float temp, float humi, float light, float pm25, float etoh)
 +
{
 +
 +
    bool NET_WEBSITE_sta;
 +
 +
    NET_WEBSITE_sta = voCC3000_ping(temp, humi, light, pm25, etoh);
 +
 +
    if(NET_WEBSITE_sta)
 +
    {
 +
        Serial.println("\n ---UPDATA OK---");
 +
 +
        voCC3000_rec();
 +
    }
 +
    else
 +
    {
 +
        Serial.println("\n --UPDATA ERROR--");
 +
 +
        cc3000.reboot();
 +
 +
        freeMem("==============Step A");
 +
        if(voCC3000_init(1))
 +
        {
 +
            freeMem("==============Step B");
 +
            if(voCC3000_init(2))
 +
            {
 +
                freeMem("==============Step C");
 +
                if(voCC3000_init(3))
 +
                    NET_WEBSITE_sta =  true;
 +
                else
 +
                    NET_WEBSITE_sta = false;
 +
            }
 +
            else
 +
                NET_WEBSITE_sta = false;
 +
        }
 +
        else
 +
            NET_WEBSITE_sta = false;
 +
 +
        freeMem("==============Step D");
 +
    }
 +
}
 
</source>
 
</source>
 
==视频==
 
==视频==

2015年11月17日 (二) 04:06的最新版本

概述

  • 项目名称:WiFi气象站
  • 目的:获取身边实时的温度、湿度、光照甚至pm2.5数据
  • 难度:中
  • 耗时:5小时
  • 制作者:
  • 简介:

它能够获取你身边实时的温度、湿度、光照甚至pm2.5数据,并且在屏幕上显示出来,如果你需要,甚至可以将其接入互联网,只要有一台能上网的手机或者计算机,任何地方、任何时候都能查看到这些数据。而这套系统完全由Microduino来实现,非常简单。

材料清单

  • Microduino设备
模块 数量 功能
Microduino-Core+/zh 1 核心板
Microduino-USBTTL/zh 1 下载程序
Microduino-WiFi/zh 1 连接网络
Microduino-Tem&Hum/zh 1 数字温湿度传感器
Microduino-Air/zh 1 空气质量传感器
Microduino-Light/zh 1 光照传感器
Microduino-OLED/zh 1 显示
  • 其他设备
模块 数量 功能
Micro-USB线 1 下载程序、供电
Microduino-USBTTL/zh 1 下载程序
GP2Y1010AU0F 1 pm2.5传感器
螺丝 7 固定模块
螺丝刀 1 固定螺丝
外壳 1

实验原理

气象站专用板上安装了多参数传感器,包括数字温湿度传感器(Microduino-Tem&Hum)、光照强度传感器(Microduino-Light)、空气质量传感器(Microduino-Air)和pm2.5传感器(GP2Y1010AU0F)。 每个传感器均与Microduino-Sensorhub连接,由Microduino核心(Microduino Core+)对传感器数据分析处理,以直观的文字提示方式在OLED中显示。 同时通过Microduino CC3000模块(wifi)使Microduino核心连接到网络,与mCotton物联网平台通讯 并以直观的文字和图表信息反馈给用户,用户只需要用通过能上网的手机或者计算机,在任何地方任何时候都能查看到这些数据,用户甚至可以设置传感器值来触发微博, 与大家一起分享你的生活。 总的来说,用户通过气象站可以随时随地感受的身边环境的变化,把无形变有形,去感受大自然的瞬息万变。

Wifistationtheory.jpg

本系统由传感器、协调器、网络适配器、OLED显示器、mCotton物联网平台五个部分组成,综合了传感技术、网络通信技术、OLED显示技术和物联网技术。传感器主要完成温度、湿度、光照参数、空气质量的采集,协调器分析处理采集的数据,同时通过网络适配器连接到网络与mCotton物联网平台通信,从而可以在mCotton物联网平台下查看到这些数据。

  • 管理平台构成

管理平台大致可分为两个部分:一是Microduino核心控制,负责采集传感器数据,并且连接到互联网。二是mCotton物联网平台,负责将数据以曲线形式直观显示给用户,用户可以随时随地查看,并且可以设置微博触发,分享你的生活环境。如图2-2所示:

  • 主要传感器

下图展示了本系统的处理流程。数据采集系统:主要负责对环境温度、湿度、光照强度等数据的采集。传感器采集的数据上传到Microduino核心,具有扩展方便等优点。 无线传输系统:该系统主要将设备采集到的数据,通过无线网络传送到服务器上,使用WiFi传输数据。 数据处理系统:该系统负责对采集的数据进行上传存储、直观显示,用户可随时随地通过电脑和手机等终端进行查询。

文档

调试过程

  • 搭建服务器

气象站既然要连入互联网,一个用来储存和显示的服务器必不可少,首先我们需要搭建好一个网络服务器。

  • 关于mCotton

目前定位于做一个开放的通用物联网平台,主要提供传感器数据的接入,存储和展现服务,为所有的开源软硬件爱好者、制造型企业,提供一个物联网项目的平台, 使得硬件和制造业者能够在不关心服务器实现细节和运维的情况下,拥有交付物联网化的电子产品的能力。 我们只需在mCotton注册一个账号,它会提供给你一个唯一的API KEY,这个便是用来在服务器里判别唯一身份之用的。 mCotton作为一个开放的公共物联网接入平台,目的是为服务所有所有的爱好者和开发者,使传感器数据的接入、存储和展现变得轻松简单。 下面我们介绍一下如何使用mCotton平台完成您的轻松接入。

  • 注册

打开mCotton的主页:somvpn.cn:3000,在页面中点击”Sign in/Join”,然后会弹出登录/注册框,再点击“Create account”进入用户注册页面。

在用户注册页面,填写相关信息后点击完成注册

  • 增加设备

登陆后点击”Projects“进入工程页面

在工程页面中找到”Weather Station”项目,点击其中的“Assemble to My Devices”按钮,可以添加自己的设备

在“Name”中输入自己的设备名称,然后点击“Submit”按钮发布

  • 获得APIKEY

发布完毕后就可以在“My Garage”页面中看到自己的设备

找到自己发布的气象站设备,可以看到该设备专属的设备ID,记下它

  • 下载程序

将Microduino-Core+与Microduino-USBTTL叠加(无上下顺序),通过USB数据线与电脑连接起来

Download1.jpg

确认你搭建了Microduino的开发环境,否则参考附录1-Arduino IDE安装指导。

打开Arduino IDE编程软件,点击 【文件】->【打开】

Dl1.jpg

浏览到项目程序地址,点击“weatherCC3000.ino”程序打开

在def.h文件中需要设置相应的配置参数:

  1. define WLAN_SSID “你要连接的WiFi的网络名”
  2. define WLAN_PASS “你要连接的WiFi的密码”
  3. define WEBSITE “设置的服务器地址”
  4. define WEBSITEPORT “设置的服务器端口号”
  5. define APP_KIT_ID “步骤3获得的设备ID号”

点击“工具”,在板选项里面选择板卡(Microduino-Core+),在处理器选项里面选择处理器(Atmega644pa@16M,5V),再在端口选项里面选择正确的端口号,然后直接烧录程序

把用到的设备叠加起来。

  • Microduino-Sensorhub
  • Microduino-USBTTL
  • Microduino-Core+
  • Microduino-WIFI

设置完成后就可以在OLED上看到各个传感器的数据

同时在mCotton上设置好的设备上也能看到气象站上传的数据

程序说明

  • 主程序部分
//1,屏幕显示部分============================= 
#include"Arduino.h" 
#include "U8glib.h" 
//2,传感器部分================================ 
#include <Wire.h> 
#include "I2Cdev.h" 
#include <AM2321.h> 
#include <SoftwareSerial.h> 
//3,WIFI部分================================ 
#include <Adafruit_CC3000.h> 
#include <ccspi.h> 
#include <SPI.h> 
#include <string.h> 
#include "utility/debug.h" 
//4,自定义部分============================= 
#include "def.h" 
#include "oled.h" 
#include "wifi.h" 
#include "sensor.h" 
 
#define INTERVAL_LCD             200        //OLED及传感器刷新时间间隔    
#define INTERVAL_NET             30000      //传感器数据上传时间间隔   
 
unsigned long lcd_time = millis();          //OLED及传感器更新计时器 
unsigned long net_time = millis();          //传感器数据上传更新计时器 
 
void setup(void) 
{ 
    Serial.begin(115200);     //初始化波特率 
    setup_wifi();             //初始化WIFI 
} 
 
void loop(void) 
{ 
 
    if (lcd_time > millis()) lcd_time = millis(); 
    if (millis() - lcd_time > INTERVAL_LCD) 
    { 
        SensorUpdate();         //更新传感器 
        volcd(sensorTemp, sensorHumi, sensorLight, sensorPM25, sensorEtoh);   //更新OLED显示 
        lcd_time = millis();    //更新计时器 
    } 
 
    if (net_time > millis()) net_time = millis(); 
    if (millis() - net_time > INTERVAL_NET) 
    { 
        updateWeatherData(sensorTemp, sensorHumi, sensorLight, sensorPM25, sensorEtoh);   //上传传感器数据 
        net_time = millis();    //更新计时器 
    } 
}
  • 用户配置部分
#define WLAN_SSID       "YourSSID"       //WIFI网络名 
#define WLAN_PASS       "YourPassword"    //WIFI密码  
 
#define WEBSITE "somevpn.cn"        //服务器网址 
#define WEBSITEPORT 3000        //服务器端口号 
#define APP_KIT     "YourDeviceID"    //设备ID号#define APP_KIT     "YourDeviceID"    //设备ID号 
 
#define WEBPAGE "/api/v1.0/d" 
#define WEBUTTONPAGE "/api/v1.0/ce"
  • OLED显示部分
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);     //设置OLED型号 
//-------字体设置,大、中、小 
#define setFont_L u8g.setFont(u8g_font_7x13) 
#define setFont_M u8g.setFont(u8g_font_fixed_v0r) 
#define setFont_S u8g.setFont(u8g_font_chikitar) 
 
//温度计图案 
const unsigned char bmp_tem[] U8G_PROGMEM = 
{ 
    0xE0, 0x81, 0x30, 0x83, 0x10, 0x82, 0x10, 0x82, 0x10, 0xFA, 0x10, 0x82,0x10, 0x82, 0x10, 0xFA, 0x10, 0x82, 0xD0, 0x82, 0xD0, 0xFA, 0xD0, 0x82,0xD0,                    
0x82, 0xD0, 0xFA, 0xD0, 0x82, 0xD0, 0x82, 0xD0, 0xFA, 0xD0, 0x82,0xD0, 0x82, 0xD8, 0x86, 0xC4, 0x88, 0xF2, 0x93, 0xFB, 0xB7, 0xF9, 0xA7,0xFD, 0xAF, 0xFD, 
0xAF, 0xF9, 0xA7, 0xFA, 0x97, 0xF2, 0x93, 0xC4, 0x88,0x18, 0x86, 0xF0, 0x83 
}; 
 
//水滴图案 
const unsigned char bmp_hum[] U8G_PROGMEM = 
{ 
    0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x80, 0x03, 0x08, 0x80, 0x03, 0x18, 0x80, 0x07, 0x1C, 0xC0, 0x07, 0x3C, 0xC0, 0x07, 0x3E, 0xE0,0x0F, 0x3E, 
0xE0, 0x0F, 0x7A, 0xF0, 0x1F, 0x7B, 0xF8, 0x1F, 0x72, 0xF8,0x1F, 0x3E, 0xF8, 0x3F, 0x1C, 0xFC, 0x3F, 0x00, 0xFC, 0x7F, 0x00, 0xFE,0x7F, 0x00, 0xFE, 0x7F, 
0x00, 0xFE, 0x7F, 0x00, 0xFF, 0xFF, 0x00, 0xFF,0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xF3, 0xFF, 0x00, 0xF2, 0x7F, 0x00, 0xE6,0x7F, 0x00, 0xC6, 0x7F, 0x00, 0x0E, 
0x3F, 0x00, 0x3C, 0x1E, 0x00, 0xF8,0x1F, 0x00, 0xE0, 0x07, 0x00, 0x80, 0x01 
}; 
 
//显示初始化界面 
void osd_setup(int _osd_setup, char *_osd_text) 
{ 
    u8g.firstPage(); 
    do 
    { 
        setFont_L;            //设置字体大 、

        u8g.setPrintPos(4, 30);        //设置文字开始坐标 
        u8g.print(_osd_text);        //显示文字 
        u8g.drawFrame(0, 48, 128, 14); 
        if(_osd_setup)                //显示进度条 
            u8g.drawBox(0+2, 48+2, map(_osd_setup, 0, 5, 0, 128-4), 14-4); 
    } 
    while( u8g.nextPage() ); 
} 
 
//显示函数 
void volcd(float temp, float humi, float light, float pm25, float etoh) 
{ 
    u8g.firstPage(); 
    do 
    { 
        u8g.setDefaultForegroundColor(); 
        u8g.drawXBMP( 4, 1, 15, 32, bmp_tem); 
        u8g.drawXBMP( 70, 2, 24, 30, bmp_hum); 
 
        setFont_M;                             //设置字体为大 
        u8g.setPrintPos(20, 16);         //设置文字开始坐标 
        u8g.print("`C "); 
        setFont_L;                             //设置字体为大 
        u8g.setPrintPos(20, 32);         //设置文字开始坐标 
        u8g.print(temp , 1);             //温度 
 
        setFont_M;                             //设置字体为大 
        u8g.setPrintPos(100, 16);         //设置文字开始坐标 
        u8g.print("%"); 
        setFont_L;                             //设置字体为大 
        u8g.setPrintPos(100, 32);         //设置文字开始坐标 
        u8g.print(humi , 0);             //湿度 
 
        setFont_L;                       //设置字体 
        u8g.setPrintPos(4, 49);          //设置文字开始坐标 
        u8g.print(light , 0);       //光照强度 
        setFont_M;                       //设置字体 
        u8g.print(" Lux"); 
 
        setFont_L;                       //设置字体 
        u8g.setPrintPos(4, 63);          //设置文字开始坐标 
        u8g.print(pm25 , 0);       //光照强度 
        setFont_M;                       //设置字体 
        u8g.print(" ug/m3"); 
 
 
        setFont_L;                       //设置字体 
        u8g.setPrintPos(80, 49);          //设置文字开始坐标 
        u8g.print(etoh , 0);       //光照强度 
        setFont_M;                       //设置字体 
        u8g.print(" ppm"); 
 
        setFont_M;                             //设置字体为大 
        u8g.setPrintPos(80, 63);         //设置文字开始坐标 
        u8g.print(" LED:"); 
    } 
    while( u8g.nextPage() ); 
} 
  
void volcdsetup(char *zi, unsigned int x, unsigned int y) 
{ 
    //#ifdef OLED 
    u8g.firstPage(); 
    do 
    { 
        setFont_L; 
        u8g.setPrintPos(x, y); 
        u8g.print(zi); 
    } 
    while( u8g.nextPage() ); 
    //#endif 
}
  • 传感器数据采集部分
#include <SoftwareSerial.h> 
#include <AM2321.h> 
 
AM2321 am2321; 
SoftwareSerial pmSerial(4, 5);        //PM2.5传感器通讯软串口 
 
float sensorTemp;       //温度值 
float sensorHumi;       //湿度值 
float sensorPM25;       //pm2.5浓度 
float sensorLight;      //光照强度 
float sensorEtoh;       //空气质量 
 
//读取pm2.5传感器 
float PM25() 
{ 
    int data_s = 0;         //串口接收数据 
    int num = -1;           //串口接收数据计数 
    int sum = 0;           //校验和 
    int cal[5];             //接收数据缓存 
    float dustDensity = 0;    //PM2.5浓度 
 
    pmSerial.begin(2400);        //首先启动软串口 
    pmSerial.flush();              //清空串口缓存 
 
    while(1) 
    { 
        if(pmSerial.available() > 0)    //串口缓存有数据 
        { 
            data_s = pmSerial.read();        //读取串口缓存数据 
            if(data_s == 0xAA)                //得到数据帧起始位 
            { 
                num = 0;                        //开始计数 
            } 
            else if(num >= 0) 
            { 
                num++;                        //读到数据,计数+1 
                cal[num-1] = data_s;    //数据保存到缓存中 
                if(num == 6)              //读到数据帧最后一位 
                { 
                    sum = cal[0] + cal[1] + cal[2] + cal[3];    
//计算校验和 
                    if(sum == cal[4] && cal[5] == 0xFF)           
//校验和匹配,数据帧最后一位为0xFF,说明接收的数据帧正常 
                    { 
                      dustDensity = (cal[0]*256+cal[1])*(5.0/1024)*550;                        //计算PM2.5浓度,单位ug/m3 
                    } 
                    else            //接收的数据不正常 
                    { 
                        dustDensity = 0;    //浓度清零 
                    } 
                    break; 
                } 
            } 
        } 
    } 
    pmSerial.end();            //关闭软串口 
    return dustDensity;    //返回值 
} 
 
//更新传感器数据 
void SensorUpdate() 
{ 
 
    //获取pm2.5浓度 
    sensorPM25 = PM25(); 
    //获取温度,湿度 
    am2321.read(); 
    sensorTemp = am2321.temperature / 10.0; 
    sensorHumi = am2321.humidity / 10.0; 
    //获取光照强度 
    sensorLight = map(analogRead(A0), 0, 1023, 0, 255); 
    //获取空气质量 
    sensorEtoh = map(analogRead(A2), 0, 1023, 0, 30); 
}
  • WiFi控制部分
// These are the interrupt and control pins 
#define ADAFRUIT_CC3000_IRQ   2  // MUST be an interrupt pin! 
// These can be any two pins 
#define ADAFRUIT_CC3000_VBAT  9 
#define ADAFRUIT_CC3000_CS    10 
#define WLAN_SECURITY   WLAN_SEC_WPA2 
#define IDLE_TIMEOUT_MS          1000 
// Use hardware SPI for the remaining pins 
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11 
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIV2); // you can change this clock speed but DI 
 
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2 
 
uint32_t ip; 
Adafruit_CC3000_Client www; 
/**************************************************************************/ 
/*! 
 @brief  Tries to read the IP address and other connection details 
 */ 
/**************************************************************************/ R"); 
            Serial.println(F("Failed!")); 
            return false; 
        } 
        else 
        { 
            Serial.println("\n2/4 connect AP OK"); 
            return true; 
        } 
    } 
    break; 
    case 2: 
    { 
        Serial.println("\n 3/4 dhcp READY"); 
        if(!voCC3000_get_dhcp()) 
        { 
            Serial.println("3/4 dhcp ERROR"); 
            Serial.println(F("Failed!")); 
            return false; 
        } 
        else 
        { 
            Serial.println("3/4 dhcp OK"); 
            return true; 
        } 
 
    } 
    break; 
    case 3: 
    { 
        Serial.println("\n 4/4 server READY"); 
        if(!voCC3000_get_server_ip()) 
        { 
            Serial.println("4/4 server ERROR"); 
            Serial.println(F("Failed!")); 
            return false; 
        } 
        else 
        { 
            Serial.println("4/4 server OK"); 
            return true; 
        } 
    } 
    break; 
    } 
} 
 
 
void setup_wifi() 
{ 
 
    bool sta; 
 
    osd_setup(1, "INIT WIFI"); 
    if(voCC3000_init(0)) 
    { 
        osd_setup(2, "CONNECT AP"); 
        if(voCC3000_init(1)) 
        { 
            osd_setup(3, "GET DHCP"); 
            if(voCC3000_init(2)) 
            { 
                osd_setup(4, "GET SERVER"); 
                if(voCC3000_init(3)) 
                    sta =  true; 
                else 
                    sta = false; 
            } 
            else 
                sta = false; 
        } 
        else 
            sta = false; 
    } 
    else 
        sta = false; 
 
    if(!sta) 
        osd_setup(0, "NET ERROR"); 
 
    //---------------------------- 
    osd_setup(5, "INIT SENSOR"); 
} 
 
 
void updateWeatherData(float temp, float humi, float light, float pm25, float etoh) 
{ 
 
    bool NET_WEBSITE_sta; 
 
    NET_WEBSITE_sta = voCC3000_ping(temp, humi, light, pm25, etoh); 
 
    if(NET_WEBSITE_sta) 
    { 
        Serial.println("\n ---UPDATA OK---"); 
 
        voCC3000_rec(); 
    } 
    else 
    { 
        Serial.println("\n --UPDATA ERROR--"); 
 
        cc3000.reboot(); 
 
        freeMem("==============Step A"); 
        if(voCC3000_init(1)) 
        { 
            freeMem("==============Step B"); 
            if(voCC3000_init(2)) 
            { 
                freeMem("==============Step C"); 
                if(voCC3000_init(3)) 
                    NET_WEBSITE_sta =  true; 
                else 
                    NET_WEBSITE_sta = false; 
            } 
            else 
                NET_WEBSITE_sta = false; 
        } 
        else 
            NET_WEBSITE_sta = false; 
 
        freeMem("==============Step D"); 
    } 
}

视频