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

来自Microduino Wikipedia
跳转至: 导航搜索
Joypad程序说明
 
(未显示同一用户的1个中间版本)
第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:Boxz物料.jpg||600px|center|thumb]]
+
[[File:气象站物料.jpg||600px|center|thumb]]
 
==实验原理==
 
==实验原理==
机器人小车种类比较多,如循迹,壁障,蓝牙遥控小车,电脑鼠等。但是其行走控制方式基本是一样的,无非就是前后左右四个方向运动。当然结构上会有一定区别,不同功能需要采用不同传感器,本次我们主要使用两轮驱动,通过控制两个轮子的旋转方向,实现前进后退,旋转等功能,当然还要加上万向轮,这样才能保持平衡。
+
气象站专用板上安装了多参数传感器,包括数字温湿度传感器(Microduino-Tem&Hum)、光照强度传感器(Microduino-Light)、空气质量传感器(Microduino-Air)和pm2.5传感器(GP2Y1010AU0F)。
该小车结构简单,主要包括三个方面:车轮、车身、控制系统。
+
每个传感器均与Microduino-Sensorhub连接,由Microduino核心(Microduino Core+)对传感器数据分析处理,以直观的文字提示方式在OLED中显示。
1)车轮采用两个减速电机,扭力大,可PWN调速,控制简单。
+
同时通过Microduino CC3000模块(wifi)使Microduino核心连接到网络,与mCotton物联网平台通讯
2)车身采用亚克力板,大小:8cm*8cm*8cm。
+
并以直观的文字和图表信息反馈给用户,用户只需要用通过能上网的手机或者计算机,在任何地方任何时候都能查看到这些数据,用户甚至可以设置传感器值来触发微博,
3)整个控制系统包括四个部分:
+
与大家一起分享你的生活。
*供电系统
+
总的来说,用户通过气象站可以随时随地感受的身边环境的变化,把无形变有形,去感受大自然的瞬息万变。
因为BOXZ体积比较小,所以采用锂电池。
+
[[File:Wifistationtheory.jpg||600px|center|thumb]]
*中央处理器
+
 
中央处理器是整个小车的核心,就像电脑的CPU,人的大脑,有一定思维能力,能够处理复杂事件。采用Microduino-Core作为核心。
+
本系统由传感器、协调器、网络适配器、OLED显示器、mCotton物联网平台五个部分组成,综合了传感技术、网络通信技术、OLED显示技术和物联网技术。传感器主要完成温度、湿度、光照参数、空气质量的采集,协调器分析处理采集的数据,同时通过网络适配器连接到网络与mCotton物联网平台通信,从而可以在mCotton物联网平台下查看到这些数据。
*无线通讯
+
[[File:Wifistationtheory1.jpg||600px|center|thumb]]
小车采用Microduino-nRF24无线通讯方案,通讯速度响应快,控制范围:空阔地域大约100米。
+
*管理平台构成
*电机控制
+
管理平台大致可分为两个部分:一是Microduino核心控制,负责采集传感器数据,并且连接到互联网。二是mCotton物联网平台,负责将数据以曲线形式直观显示给用户,用户可以随时随地查看,并且可以设置微博触发,分享你的生活环境。如图2-2所示:
采用Microduino-Motor直流电机驱动模块,一个模块能够驱动两个电机。同时结合Microduino-Robot底板,将中央处理器和直流电机模块连接起来。
+
*主要传感器
 +
[[File:Wifistationtheory2.jpg||600px|center|thumb]]
 +
下图展示了本系统的处理流程。数据采集系统:主要负责对环境温度、湿度、光照强度等数据的采集。传感器采集的数据上传到Microduino核心,具有扩展方便等优点。
 +
无线传输系统:该系统主要将设备采集到的数据,通过无线网络传送到服务器上,使用WiFi传输数据。
 +
数据处理系统:该系统负责对采集的数据进行上传存储、直观显示,用户可随时随地通过电脑和手机等终端进行查询。
 +
[[File:Wifistationtheory3.jpg||600px|center|thumb]]
  
 
==文档==
 
==文档==
 
==调试过程==
 
==调试过程==
将Microduino Core、Microduino USBTTL堆叠在一起.用数据线将写好的程序通过Microduino USBTTL上传到Microduino Core上。
+
*搭建服务器
注意:最好不要将所有模块堆叠在一起之后再上传程序
+
气象站既然要连入互联网,一个用来储存和显示的服务器必不可少,首先我们需要搭建好一个网络服务器。
[[File:download1.jpg||500px|center|thumb]]
+
*关于mCotton
打开Aroduino IDE,若电脑中没有安装,则参照附录中的安装方法,先安装Aicroduino IDE。点击左上【文件】选项→点击【打开】。
+
目前定位于做一个开放的通用物联网平台,主要提供传感器数据的接入,存储和展现服务,为所有的开源软硬件爱好者、制造型企业,提供一个物联网项目的平台,
[[File:Bleopen.jpg||500px|center|thumb]]
+
使得硬件和制造业者能够在不关心服务器实现细节和运维的情况下,拥有交付物联网化的电子产品的能力。
浏览到项目程序地址,点击“Robot_v0.2.ino”程序打开
+
我们只需在mCotton注册一个账号,它会提供给你一个唯一的API KEY,这个便是用来在服务器里判别唯一身份之用的。
[[File:Boxzopen1.jpg||500px|center|thumb]]
+
mCotton作为一个开放的公共物联网接入平台,目的是为服务所有所有的爱好者和开发者,使传感器数据的接入、存储和展现变得轻松简单。
[[File:Boxzopen2.jpg||500px|center|thumb]]
+
下面我们介绍一下如何使用mCotton平台完成您的轻松接入。
之后点击左上角的"√"进行编译,点击上边栏的工具,确认板卡(Microduino-Core)处理器(Atmega328P@16M,5V)和端口号(COMX)。三项都如图确认无误之后点击"→"按钮下载程序到开发板上
+
*注册
 
+
打开mCotton的主页:somvpn.cn:3000,在页面中点击”Sign in/Join”,然后会弹出登录/注册框,再点击“Create account”进入用户注册页面。
[[File:Boxz步骤.jpg||500px|center|thumb]]
+
[[File:mcottonsign1.jpg||600px|center|thumb]]
 
+
在用户注册页面,填写相关信息后点击完成注册
Joypad操作说明
+
[[File:mcottonsign2.jpg||600px|center|thumb]]
[[File:Joypadtest.jpg||300px|center|thumb]]
+
*增加设备
[[File:Joypad物料.jpg||300px|center|thumb]]
+
登陆后点击”Projects“进入工程页面
*左上边是油门控制开关,打开(拨到上面),才能进行控制,你可以摇动摇杆,观察屏幕的变化。
+
[[File:mcottonsign3.jpg||600px|center|thumb]]
*右边开关是精度调整开关,开关拨到上面可以最大幅度控制,否则只能小幅度控制了,小幅度有助于稳定控制。
+
在工程页面中找到”Weather Station”项目,点击其中的“Assemble to My Devices”按钮,可以添加自己的设备
*左边摇杆本次未使用。
+
[[File:mcottonsign4.jpg||600px|center|thumb]]
*右边摇杆在垂直方向上控制前后方向移动,往上向前,往下向后,在水平方向上控制左右方向移动。
+
在“Name”中输入自己的设备名称,然后点击“Submit”按钮发布
Joypad开机设置
+
[[File:mcottonsign5.jpg||600px|center|thumb]]
[[File:Joypadtest1.jpg||300px|center|thumb]]
+
*获得APIKEY
打开遥控器电源开关,按下复位按键(左边USB接口右边那个)进入系统,请在4S内按下【key1】按键,进入遥控器校准和控制选择模式。
+
发布完毕后就可以在“My Garage”页面中看到自己的设备
360度最大幅度旋转两个摇杆,遥控板会读入摇杆的位置数据,摇动至示数不再变化即可
+
[[File:mcottonsign6.jpg||600px|center|thumb]]
[[File:Joypadtest2.jpg||300px|center|thumb]]
+
找到自己发布的气象站设备,可以看到该设备专属的设备ID,记下它
选择控制模式,可以通过【key3】按键来选择是控制四轴飞行器(Quad.)还是机器人(Robot),Robot模式可控制自平衡车和BOXZ mini,黑色表示选中。因此我们需要选择Robot模式。还可以通过【key4】按键来选择是否是体感控制模式,如果选择体感模式,你必须叠加Microduino-10DOF模块,选择“MPU ON”。如果是摇杆控制模式,选择“MPU OFF”。
+
[[File:mcottonsign7.jpg||600px|center|thumb]]
这次搭建没有使用10DOF模块,因此选择MPU OFF模式;
+
*下载程序
[[File:Joypadtest3.jpg||300px|center|thumb]]
+
将Microduino-Core+与Microduino-USBTTL叠加(无上下顺序),通过USB数据线与电脑连接起来
选择完成后,通过【key2】按键退出配置,进入操作
+
[[File:download1.jpg||600px|center|thumb]]
[[File:Joypadtest4.jpg||300px|center|thumb]]
+
确认你搭建了Microduino的开发环境,否则参考附录1-Arduino IDE安装指导。
将左上边控制开关打开(拨到上面),才能进行控制,你可以摇动摇杆,观察屏幕的变化
+
[[File:Gettingstarted.jpg||600px|center|thumb]]
[[File:Joypadtest5.jpg||300px|center|thumb]]
+
打开Arduino IDE编程软件,点击 【文件】->【打开】
右边开关是幅度调节模式,开关拨到上面可以最大幅度控制Robot,否则只能小幅度控制。如果使用小幅度控制小车,右边摇杆拨到最大位置,小车速度也只能小范围变化,这样有助于稳定控制
+
[[File:Dl1.jpg||600px|center|thumb]]
[[File:Joypadtest6.jpg||300px|center|thumb]]
+
浏览到项目程序地址,点击“weatherCC3000.ino”程序打开
当启动小车时,只需要用到右边的摇杆,摇杆的方向和平衡车的方向一致,你可以尝试摇杆控制是否正确。如果发现方向有问题,可以在Robot_v0.2前4行代码更改引脚定义
+
[[File:WiFiStationopen.jpg||600px|center|thumb]]
如果原来的引脚定义如下:
+
[[File:WiFiStationopen2.jpg||600px|center|thumb]]
[[File:Boxzpin1.jpg||300px|center|thumb]]
+
在def.h文件中需要设置相应的配置参数:
而此时左右旋转反了,可以更改为
+
#define WLAN_SSID   “你要连接的WiFi的网络名”
[[File:Boxzpin2.jpg||300px|center|thumb]]
+
#define WLAN_PASS   “你要连接的WiFi的密码”
如果最开始的引脚是情况2,那么方向错了就改成情况1就可以了。
+
#define WEBSITE   “设置的服务器地址”
打开BOXZ_mini小车上Microduino-Robot底板上的电源开关,拨到ON(左边),如果可以看到核心板上的红色led亮,说明供电正常。你可以愉快的玩耍了。
+
#define WEBSITEPORT        “设置的服务器端口号”
 
+
#define APP_KIT_ID   “步骤3获得的设备ID号”
 
+
[[File:WiFiStationopen3.jpg||600px|center|thumb]]
==注意问题==
+
点击“工具”,在板选项里面选择板卡(Microduino-Core+),在处理器选项里面选择处理器(Atmega644pa@16M,5V),再在端口选项里面选择正确的端口号,然后直接烧录程序
*下载程序时候最好只叠加core(core+)和USBTTL,虽然本次搭建涉及的nRF24不会引起冲突,但是别的通信模块有时会造成串口冲突,养成好习惯。
+
[[File:WiFiStationopen4.jpg||600px|center|thumb]]
*锂电池正负极别接错了,否则会烧坏电路。
+
把用到的设备叠加起来。
*调试好后,实际运行时不要使用USB供电,电压不足,请使用电池。
+
*Microduino-Sensorhub
==小车程序说明==
+
*Microduino-USBTTL
<source lang="cpp">
+
*Microduino-Core+
#define motor_pin0A 7  //PWM
+
*Microduino-WIFI
#define motor_pin0B 5
+
设置完成后就可以在OLED上看到各个传感器的数据
#define motor_pin1A 8  //PWM
+
[[File:气象站步骤.jpg||600px|center|thumb]]
#define motor_pin1B 6
+
同时在mCotton上设置好的设备上也能看到气象站上传的数据
 
+
[[File:WiFiStation10.jpg||600px|center|thumb]]
#define FIX_THROTTLE_A 1  //-1 or 1
 
#define FIX_THROTTLE_B -1  //-1 or 1
 
 
 
#define REVERSE_THROTTLE 1      //-1 or 1
 
#define REVERSE_STEERING 1    //-1 or 1
 
 
 
#define MAX_THROTTLE 255 //最大油门 100~255
 
#define MAX_STEERING 200 //最大转向 100~512
 
 
 
//rf=======================================
 
#include <RF24Network.h>
 
#include <RF24.h>
 
#include <SPI.h>
 
 
 
// nRF24L01(+) radio attached using Getting Started board
 
RF24 radio(9, 10);
 
RF24Network network(radio);
 
const uint16_t this_node = 1; //设置本机ID
 
const uint16_t other_node = 0;
 
 
 
//--------------------------------
 
struct send_a //发送
 
{
 
  uint32_t node_ms; //节点运行时间
 
};
 
 
 
unsigned long last_sent = 0; //定时器
 
 
 
//--------------------------------
 
struct receive_a //接收
 
{
 
  uint32_t ms;
 
  uint16_t rf_CH0;
 
  uint16_t rf_CH1;
 
  uint16_t rf_CH2;
 
  uint16_t rf_CH3;
 
  uint16_t rf_CH4;
 
  uint16_t rf_CH5;
 
  uint16_t rf_CH6;
 
  uint16_t rf_CH7;
 
};
 
 
 
unsigned long clock; //主机运行时间
 
int tem_xuan = 0; //主机请求时序
 
 
 
//----------------------------
 
boolean node_STA = false;
 
float throttle;
 
float steering;
 
 
 
unsigned long safe_ms = millis();
 
 
 
void setup()
 
{
 
  Serial.begin(115200);
 
 
 
  pinMode(motor_pin0A, OUTPUT);
 
  pinMode(motor_pin0B, OUTPUT);
 
  pinMode(motor_pin1A, OUTPUT);
 
  pinMode(motor_pin1B, OUTPUT);
 
 
 
  //nRF==============================
 
  SPI.begin(); //初始化SPI总线
 
  radio.begin();
 
  network.begin(/*channel*/ 70  , /*node address*/ this_node);
 
 
 
  Serial.println("===========start===========");
 
}
 
 
 
 
 
int motor_vol[2];
 
// 主循环//////////////////////////////////////////////////////////////////////////
 
void loop()
 
{
 
  //===============================================================
 
  if (nRF(&throttle, &steering))
 
  {
 
    vorobot();
 
    Serial.print(throttle);
 
    Serial.print(",");
 
    Serial.println(steering);
 
  }
 
 
 
  //===============================================================
 
  if (safe_ms > millis()) safe_ms = millis();
 
  if (millis() - safe_ms > 2000)
 
  {
 
    steering = 0;
 
    throttle = 0;
 
 
 
    digitalWrite(motor_pin0A, LOW);
 
    digitalWrite(motor_pin0B, LOW);
 
    digitalWrite(motor_pin1A, LOW);
 
    digitalWrite(motor_pin1B, LOW);
 
  }
 
 
 
}
 
 
 
void vorobot()
 
{
 
  /*
 
  if(node_STA)
 
  {
 
 
 
  }
 
  */
 
 
 
  //===============================================================
 
  int motor_speed = 0;
 
  motor_speed = REVERSE_THROTTLE * throttle;
 
 
 
  motor_vol[0] = motor_speed;
 
  motor_vol[1] = motor_speed;
 
 
 
  //----------------------------------
 
  int motor_steer = 0;
 
  motor_steer = REVERSE_STEERING * steering;
 
 
 
  motor_vol[0] -= motor_steer / 2;
 
  motor_vol[1] += motor_steer / 2;
 
 
 
  for (int a = 0; a < 2; a++)
 
  {
 
    if (motor_vol[a] > MAX_THROTTLE)
 
    {
 
      motor_vol[0] -= (motor_vol[a] - MAX_THROTTLE);
 
      motor_vol[1] -= (motor_vol[a] - MAX_THROTTLE);
 
    }
 
    else if (motor_vol[a] < -MAX_THROTTLE)
 
    {
 
      motor_vol[0] -= (MAX_THROTTLE + motor_vol[a]);
 
      motor_vol[1] -= (MAX_THROTTLE + motor_vol[a]);
 
    }
 
  }
 
 
 
  Serial.print(motor_vol[0]);
 
  Serial.print(",");
 
  Serial.print(motor_vol[1]);
 
  Serial.println("");
 
 
 
  motor_vol[0] *= FIX_THROTTLE_A;
 
  motor_vol[1] *= FIX_THROTTLE_B;
 
 
 
  motor_driver(0, -motor_vol[0]);
 
  motor_driver(1, motor_vol[1]);
 
}
 
 
 
boolean motor_driver(int _motor_driver_num, int _motor_driver_vol)
 
{
 
  switch (_motor_driver_num)
 
  {
 
    case 0:
 
      if (_motor_driver_vol == 0)
 
      {
 
        //Serial.println("0 OFF");
 
        digitalWrite(motor_pin0A, LOW);
 
        digitalWrite(motor_pin0B, LOW);
 
      }
 
      else if (_motor_driver_vol > 0)
 
      {
 
        //Serial.println("0 Z");
 
        analogWrite(motor_pin0A, _motor_driver_vol);
 
        digitalWrite(motor_pin0B, LOW);
 
      }
 
      else
 
      {
 
        //Serial.println("0 F");
 
        analogWrite(motor_pin0A, 255 + _motor_driver_vol);
 
        digitalWrite(motor_pin0B, HIGH);
 
      }
 
      break;
 
    case 1:
 
      if (_motor_driver_vol == 0)
 
      {
 
        //Serial.println("1 OFF");
 
        digitalWrite(motor_pin1A, LOW);
 
        digitalWrite(motor_pin1B, LOW);
 
      }
 
      else if (_motor_driver_vol > 0)
 
      {
 
        //Serial.println("1 Z");
 
        analogWrite(motor_pin1A, _motor_driver_vol);
 
        digitalWrite(motor_pin1B, LOW);
 
      }
 
      else
 
      {
 
        //Serial.println("1 F");
 
        analogWrite(motor_pin1A, 255 + _motor_driver_vol);
 
        digitalWrite(motor_pin1B, HIGH);
 
      }
 
      break;
 
    default :
 
      return false;
 
  }
 
  return true;
 
}
 
 
 
 
 
boolean nRF(float * _speed, float * _turn)
 
{
 
  network.update();
 
  // Is there anything ready for us?
 
  while ( network.available() )
 
  {
 
    // If so, grab it and print it out
 
    RF24NetworkHeader header;
 
    receive_a rec;
 
    network.read(header, &rec, sizeof(rec));
 
 
 
    clock = rec.ms;    //接收主机运行时间赋值
 
    float * _i = _speed;
 
    _i[0] = map(rec.rf_CH1, 1000, 2000, -MAX_THROTTLE, MAX_THROTTLE);
 
    _i = _turn;
 
    _i[0] = map(rec.rf_CH0, 1000, 2000, -MAX_STEERING, MAX_STEERING);
 
 
 
    node_STA = (rec.rf_CH7 > 1500 ? true : false);    //接收请求时序赋值
 
 
 
    {
 
      //Serial.print("Sending...");
 
      send_a sen = {
 
        millis()
 
      };  //把这些数据发送出去,对应前面的发送数组
 
 
 
      RF24NetworkHeader header(0);
 
      boolean ok = network.write(header, &sen, sizeof(sen));
 
      safe_ms = millis();
 
      if (ok)
 
      {
 
        return true;
 
        //Serial.println("ok.");
 
      }
 
      else
 
      {
 
        return false;
 
        //Serial.println("failed.");
 
      }
 
    }
 
 
 
    safe_ms = millis();
 
  }
 
}
 
</source>
 
  
 
==程序说明==
 
==程序说明==
 
+
*主程序部分
==Joypad程序及说明==
 
Joypad_RC.ino
 
 
<source lang="cpp">
 
<source lang="cpp">
#include "Arduino.h"
+
//1,屏幕显示部分=============================  
#include "def.h"
+
#include"Arduino.h"
#include "time.h"
+
#include "U8glib.h"
#include "bat.h"
+
//2,传感器部分================================  
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
+
#include <Wire.h>  
#include "mpu.h"
+
#include "I2Cdev.h"
#endif
+
#include <AM2321.h>  
#include "joy.h"
+
#include <SoftwareSerial.h>  
#include "key.h"
+
//3,WIFI部分================================  
#include "data.h"
+
#include <Adafruit_CC3000.h>  
#include "nrf.h"
+
#include <ccspi.h>  
#include "mwc.h"
+
#include <SPI.h>
#include "tft.h"
+
#include <string.h>
#include "eep.h"
+
#include "utility/debug.h"  
 
+
//4,自定义部分=============================  
#if defined(__AVR_ATmega128RFA1__)
+
#include "def.h"  
#include <ZigduinoRadio.h>
+
#include "oled.h"  
#endif
+
#include "wifi.h"  
 
+
#include "sensor.h"  
//joypad================================
+
#include <Joypad.h>
+
#define INTERVAL_LCD            200        //OLED及传感器刷新时间间隔   
//eeprom================================
+
#define INTERVAL_NET            30000      //传感器数据上传时间间隔 
#include <EEPROM.h>
+
//TFT===================================
+
unsigned long lcd_time = millis();         //OLED及传感器更新计时器
#include <Adafruit_GFX.h>    // Core graphics library
+
unsigned long net_time = millis();         //传感器数据上传更新计时器
#include <Adafruit_ST7735.h> // Hardware-specific
+
#include <SPI.h>
+
void setup(void)  
//rf====================================
+
{  
#include <RF24Network.h>
+
     Serial.begin(115200);    //初始化波特率
#include <RF24.h>
+
     setup_wifi();             //初始化WIFI
 
+
}  
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
+
//MPU===================================
+
void loop(void)  
#include "Wire.h"
+
{  
#include "I2Cdev.h"
+
   
#include "MPU6050_6Axis_MotionApps20.h"
+
     if (lcd_time > millis()) lcd_time = millis();  
#endif
+
    if (millis() - lcd_time > INTERVAL_LCD)  
 
+
    {  
//spi===================================
+
        SensorUpdate();         //更新传感器
#include <SPI.h>
+
        volcd(sensorTemp, sensorHumi, sensorLight, sensorPM25, sensorEtoh);   //更新OLED显示
 
+
        lcd_time = millis();   //更新计时器
void setup()
+
    }
{
+
  // initialize serial communication at 115200 bits per second:
+
    if (net_time > millis()) net_time = millis();  
 
+
    if (millis() - net_time > INTERVAL_NET)  
#ifdef Serial_DEBUG
+
    {  
  Serial.begin(115200);
+
        updateWeatherData(sensorTemp, sensorHumi, sensorLight, sensorPM25, sensorEtoh);  //上传传感器数据
  delay(100);
+
        net_time = millis();    //更新计时器
  Serial.println("========hello========");
+
    }  
#endif
+
}  
 
 
  //---------------
 
  key_init();
 
 
 
  //---------------
 
#ifdef Serial_DEBUG
 
  Serial.println("\n\r EEPROM READ...");
 
#endif
 
  eeprom_read();
 
 
 
  //---------------
 
#ifdef Serial_DEBUG
 
  Serial.println("\n\r TFT INIT...");
 
#endif
 
  TFT_init(true, tft_rotation);
 
 
 
  //---------------
 
#ifdef Serial_DEBUG
 
  Serial.println("\n\r TFT BEGIN...");
 
#endif
 
  TIME1 = millis();
 
  while (millis() - TIME1 < interval_TIME1)
 
  {
 
    TFT_begin();
 
 
 
    if (!Joypad.readButton(CH_SWITCH_1))
 
    {
 
#ifdef Serial_DEBUG
 
      Serial.println("\n\rCorrect IN...");
 
#endif
 
 
 
      //---------------
 
#ifdef Serial_DEBUG
 
      Serial.println("\n\r TFT INIT...");
 
#endif
 
      TFT_init(false, tft_rotation);
 
 
 
      while (1)
 
      {
 
        if (!TFT_config())
 
          break;
 
      }
 
#ifdef Serial_DEBUG
 
      Serial.println("\n\rCorrect OUT...");
 
#endif
 
 
 
      //---------------
 
#ifdef Serial_DEBUG
 
      Serial.println("\n\r EEPROM WRITE...");
 
#endif
 
      eeprom_write();
 
    }
 
  }
 
 
 
  //---------------
 
#ifdef Serial_DEBUG
 
  Serial.println("\n\r TFT CLEAR...");
 
#endif
 
  TFT_clear();
 
 
 
  //---------------
 
#ifdef Serial_DEBUG
 
  Serial.println("\n\r TFT READY...");
 
#endif
 
  TFT_ready();
 
 
 
  //---------------.l
 
  if (mode_protocol)   //Robot
 
  {
 
     SPI.begin(); //初始化SPI总线
 
    radio.begin();
 
     network.begin(/*channel*/ nrf_channal, /*node address*/ this_node);
 
  }
 
  else          //QuadCopter
 
  {
 
    unsigned long _channel;
 
#if !defined(__AVR_ATmega128RFA1__)
 
     switch (mwc_channal)
 
    {
 
      case 0:
 
        _channel = 9600;
 
        break;
 
      case 1:
 
        _channel = 19200;
 
        break;
 
      case 2:
 
        _channel = 38400;
 
        break;
 
      case 3:
 
        _channel = 57600;
 
        break;
 
      case 4:
 
        _channel = 115200;
 
        break;
 
    }
 
#else if
 
    _channel = mwc_channal;
 
#endif
 
    mwc_port.begin(_channel);
 
  }
 
 
 
  //---------------
 
#ifdef Serial_DEBUG
 
  Serial.println("===========start===========");
 
#endif
 
 
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
  if (mode_mpu) initMPU(); //initialize device
 
#endif
 
}
 
 
 
void loop()
 
{
 
  // unsigned long time = millis();
 
 
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
  //MPU--------------------------------
 
  if (mode_mpu)
 
     getMPU();
 
#endif
 
 
 
  //DATA_begin------------------------------
 
  data_begin();
 
 
 
  //DATA_send-------------------------------
 
  if (millis() < time2) time2 = millis();
 
  if (millis() - time2 > interval_time2)
 
  {
 
    if (mode_protocol) nrf_send();   //Robot
 
    else data_send();           //QuadCopter
 
 
 
    time2 = millis();
 
  }
 
 
 
  //节点查错-------------------------------
 
  vodebug();
 
 
 
  //BAT--------------------------------
 
  if (time3 > millis()) time3 = millis();
 
  if (millis() - time3 > interval_time3)
 
  {
 
    vobat();
 
    time3 = millis();
 
  }
 
 
 
   //TFT------------------------------------
 
  TFT_run();
 
 
 
  //===================================
 
  //  time = millis() - time;
 
 
 
  //  Serial.println(time, DEC);    //loop time
 
}
 
</cpp>
 
BAT.h
 
<source lang="cpp">
 
int8_t _V_bat = _V_min;
 
 
 
boolean mcu_voltage = true; // 5.0 or 3.3
 
#define _V_fix 0.2  //fix battery voltage
 
#define _V_math(Y) (_V_fix+((Y*analogRead(PIN_bat)/1023.0f)/(33.0f/(51.0f+33.0f))))
 
 
 
void vobat()
 
{
 
  //_V_bat=10*((voltage*analogRead(PIN_bat)/1023.0f)/(33.0f/(51.0f+33.0f)));
 
  _V_bat = _V_math(mcu_voltage ? 50 : 33);
 
  _V_bat = constrain(_V_bat, _V_min, _V_max);
 
 
 
#ifdef Serial_DEBUG
 
  Serial.print("_V_bat: ");
 
  Serial.println(_V_bat);
 
#endif
 
}
 
 
</source>
 
</source>
data.h
+
*用户配置部分
 
<source lang="cpp">
 
<source lang="cpp">
#include "Arduino.h"
+
#define WLAN_SSID      "YourSSID"       //WIFI网络名
 
+
#define WLAN_PASS      "YourPassword"    //WIFI密码 
byte inBuf[16];
+
 
+
#define WEBSITE "somevpn.cn"        //服务器网址
int16_t outBuf[8] =
+
#define WEBSITEPORT 3000        //服务器端口号
{
+
#define APP_KIT     "YourDeviceID"    //设备ID号#define APP_KIT     "YourDeviceID"    //设备ID号
  Joy_MID, Joy_MID, Joy_MID, Joy_MID, Joy_MID, Joy_MID, Joy_MID, Joy_MID
+
   
};
+
#define WEBPAGE "/api/v1.0/d"
 
+
#define WEBUTTONPAGE "/api/v1.0/ce"
boolean AUX[4] = {0, 0, 0, 0};
 
//======================================
 
void data_begin()
 
{
 
  Joy();
 
 
 
  if (mode_protocol)  //Robot
 
  {
 
     if (!sw_l)
 
    {
 
      Joy_x = Joy_MID;
 
      Joy_y = Joy_MID;
 
      Joy1_x = Joy_MID;
 
      Joy1_y = Joy_MID;
 
    }
 
  }
 
  else        //QuadCopter
 
  {
 
     if (!sw_l)
 
      Joy_y = Joy_MID - Joy_maximum;
 
  }
 
 
 
  //but---------------------------------
 
  for (uint8_t a = 0; a < 4; a++)
 
  {
 
    if (key_get(a, 1)) AUX[a] = !AUX[a];
 
  }
 
 
 
  outBuf[0] = Joy1_x;
 
  outBuf[1] = Joy1_y;
 
  outBuf[2] = Joy_x;
 
  outBuf[3] = Joy_y;
 
  outBuf[4] = map(AUX[0], 0, 1, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
  outBuf[5] = map(AUX[1], 0, 1, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
  outBuf[6] = map(AUX[2], 0, 1, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
  outBuf[7] = map(AUX[3], 0, 1, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
}
 
 
 
 
</source>
 
</source>
def.h
+
*OLED显示部分
 
<source lang="cpp">
 
<source lang="cpp">
#include "Arduino.h"
+
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;            //设置字体大 、
  
//DEBUG-----------
+
        u8g.setPrintPos(4, 30);        //设置文字开始坐标
#define Serial_DEBUG
+
        u8g.print(_osd_text);        //显示文字
 
+
        u8g.drawFrame(0, 48, 128, 14);
//MWC-------------
+
        if(_osd_setup)                //显示进度条
uint8_t mwc_channal = 11; //RF channel
+
            u8g.drawBox(0+2, 48+2, map(_osd_setup, 0, 5, 0, 128-4), 14-4);
 
+
    }
#if defined(__AVR_ATmega32U4__)
+
    while( u8g.nextPage() );  
#define mwc_port Serial1    //Serial1 is D0 D1
+
}
#elif defined(__AVR_ATmega128RFA1__)
+
#define mwc_port ZigduinoRadio    //RF
+
//显示函数
#else
+
void volcd(float temp, float humi, float light, float pm25, float etoh)
#define mwc_port Serial    //Serial is D0 D1
+
{
#endif
+
    u8g.firstPage();
 
+
    do
//nRF-------------
+
    {
#define interval_debug  2000  //节点查错间隔
+
        u8g.setDefaultForegroundColor();
uint8_t nrf_channal = 70;  //0~125
+
        u8g.drawXBMP( 4, 1, 15, 32, bmp_tem);
 
+
        u8g.drawXBMP( 70, 2, 24, 30, bmp_hum);
//Battery---------
+
   
#define PIN_bat A7 //BAT
+
        setFont_M;                            //设置字体为大
 
+
        u8g.setPrintPos(20, 16);        //设置文字开始坐标
#define _V_max 41 //锂电池满电电压4.2V
+
        u8g.print("`C ");
#define _V_min 36 //锂电池没电电压3.7V
+
        setFont_L;                            //设置字体为大
 
+
        u8g.setPrintPos(20, 32);        //设置文字开始坐标
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
+
        u8g.print(temp , 1);            //温度
//MPU-------------
+
#define MPU_maximum 70
+
        setFont_M;                            //设置字体为大
#endif
+
        u8g.setPrintPos(100, 16);        //设置文字开始坐标
 
+
        u8g.print("%");
 
+
        setFont_L;                            //设置字体为大
//Time------------
+
        u8g.setPrintPos(100, 32);        //设置文字开始坐标
#define interval_TIME1 2000    //setup delay
+
        u8g.print(humi , 0);             //湿度
#define interval_time2 40      //send interval
+
   
#define interval_time3 1000    //battery interval
+
        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>
eep.h
+
*传感器数据采集部分
 
<source lang="cpp">
 
<source lang="cpp">
#include "Arduino.h"
+
#include <SoftwareSerial.h>
 
+
#include <AM2321.h>  
#include <EEPROM.h>
+
 
+
AM2321 am2321;  
#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
+
SoftwareSerial pmSerial(4, 5);       //PM2.5传感器通讯软串口
#define EEPROM_read(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}
+
 
+
float sensorTemp;       //温度值
struct config_type
+
float sensorHumi;       //湿度值
{
+
float sensorPM25;       //pm2.5浓度
  int16_t eeprom_correct_min[4];
+
float sensorLight;     //光照强度
  int16_t eeprom_correct_max[4];
+
float sensorEtoh;       //空气质量
  uint8_t eeprom_Joy_deadzone_val;
+
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
+
//读取pm2.5传感器
  boolean eeprom_mode_mpu;
+
float PM25()  
#endif
+
{  
  boolean eeprom_mode_protocol;
+
     int data_s = 0;         //串口接收数据
  uint8_t eeprom_mwc_channal;
+
     int num = -1;           //串口接收数据计数
  uint8_t eeprom_nrf_channal;
+
    int sum = 0;           //校验和
  boolean eeprom_tft_theme;
+
     int cal[5];             //接收数据缓存
  boolean eeprom_tft_rotation;
+
     float dustDensity = 0;   //PM2.5浓度
  boolean eeprom_mcu_voltage;
+
};
+
    pmSerial.begin(2400);       //首先启动软串口
 
+
    pmSerial.flush();             //清空串口缓存
//======================================
+
   
void eeprom_read()
+
    while(1)  
{
+
    {  
  //EEPROM读取赋值
+
        if(pmSerial.available() > 0)   //串口缓存有数据
  config_type config_readback;
+
        {  
  EEPROM_read(0, config_readback);
+
            data_s = pmSerial.read();       //读取串口缓存数据
 
+
            if(data_s == 0xAA)               //得到数据帧起始位
  for (uint8_t a = 0; a < 4; a++)
+
            {  
  {
+
                num = 0;                       //开始计数
     joy_correct_min[a] = config_readback.eeprom_correct_min[a];
+
            }
     joy_correct_max[a] = config_readback.eeprom_correct_max[a];
+
            else if(num >= 0)  
  }
+
            {  
  Joy_deadzone_val = config_readback.eeprom_Joy_deadzone_val;
+
                num++;                       //读到数据,计数+1
 
+
                cal[num-1] = data_s;   //数据保存到缓存中
  mode_protocol = config_readback.eeprom_mode_protocol;
+
                if(num == 6)             //读到数据帧最后一位
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
+
                {  
  mode_mpu = config_readback.eeprom_mode_mpu;
+
                    sum = cal[0] + cal[1] + cal[2] + cal[3];   
#endif
+
//计算校验和
 
+
                    if(sum == cal[4] && cal[5] == 0xFF)          
  mwc_channal = config_readback.eeprom_mwc_channal;
+
//校验和匹配,数据帧最后一位为0xFF,说明接收的数据帧正常
  nrf_channal = config_readback.eeprom_nrf_channal;
+
                    {  
  tft_theme = config_readback.eeprom_tft_theme;
+
                      dustDensity = (cal[0]*256+cal[1])*(5.0/1024)*550;                       //计算PM2.5浓度,单位ug/m3
  tft_rotation = config_readback.eeprom_tft_rotation;
+
                    }  
  mcu_voltage = config_readback.eeprom_mcu_voltage;
+
                    else           //接收的数据不正常
}
+
                    {  
 
+
                        dustDensity = 0;   //浓度清零
void eeprom_write()
+
                    }
{
+
                    break;  
  // 定义结构变量config,并定义config的内容
+
                }  
  config_type config;
+
            }  
 
+
        }
  for (uint8_t a = 0; a < 4; a++)
+
    }
  {
+
     pmSerial.end();           //关闭软串口
     config.eeprom_correct_min[a] = joy_correct_min[a];
+
     return dustDensity;   //返回值
     config.eeprom_correct_max[a] = joy_correct_max[a];
+
}
  }
+
   
  config.eeprom_Joy_deadzone_val = Joy_deadzone_val;
+
//更新传感器数据
 
+
void SensorUpdate()  
  config.eeprom_mode_protocol = mode_protocol;
+
{
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
+
  config.eeprom_mode_mpu = mode_mpu;
+
    //获取pm2.5浓度
#endif
+
     sensorPM25 = PM25();
 
+
     //获取温度,湿度
  config.eeprom_mwc_channal = mwc_channal;
+
     am2321.read();  
  config.eeprom_nrf_channal = nrf_channal;
+
    sensorTemp = am2321.temperature / 10.0;  
  config.eeprom_tft_theme = tft_theme;
+
     sensorHumi = am2321.humidity / 10.0;
  config.eeprom_tft_rotation = tft_rotation;
+
     //获取光照强度
  config.eeprom_mcu_voltage = mcu_voltage;
+
     sensorLight = map(analogRead(A0), 0, 1023, 0, 255);  
 
+
    //获取空气质量
  // 变量config存储到EEPROM,地址0写入
+
    sensorEtoh = map(analogRead(A2), 0, 1023, 0, 30);  
  EEPROM_write(0, config);
+
}  
}
 
</source>
 
joy.h
 
<source lang="cpp">
 
#include "Arduino.h"
 
 
 
#include <Joypad.h>
 
 
 
//Joy-------------
 
//1000~2000
 
uint8_t Joy_deadzone_val = 10;
 
#define Joy_s_maximum 200 //MAX 300
 
#define Joy_maximum 450 //MAX 500
 
#define Joy_MID 1500 //1500
 
 
 
boolean mode_mpu, mode_protocol;  //{(0: 0 is mwc, 1 is nrf),(1: 0 is mpu, 1 is no mpu)}
 
 
 
int16_t joy_correct_max[4], joy_correct_min[4];
 
int16_t Joy_x, Joy_y, Joy1_x, Joy1_y;
 
 
 
int16_t s_lig, s_mic;
 
 
 
boolean Joy_sw, Joy1_sw;
 
 
 
boolean but1, but2, but3, but4;
 
 
 
boolean sw_l, sw_r;
 
 
 
//======================================
 
int16_t Joy_dead_zone(int16_t _Joy_vol)
 
{
 
  if (abs(_Joy_vol) > Joy_deadzone_val)
 
    return ((_Joy_vol > 0) ? (_Joy_vol - Joy_deadzone_val) : (_Joy_vol + Joy_deadzone_val));
 
  else
 
    return 0;
 
}
 
 
 
int16_t Joy_i(int16_t _Joy_i, boolean _Joy_b, int16_t _Joy_MIN, int16_t _Joy_MAX)
 
{
 
  int16_t _Joy_a;
 
  switch (_Joy_i)
 
  {
 
    case 0:
 
      _Joy_a = Joy_dead_zone(Joypad.readJoystickX());
 
      break;
 
    case 1:
 
      _Joy_a = Joypad.readJoystickY();    //throt
 
      break;
 
    case 2:
 
      _Joy_a = Joy_dead_zone(Joypad.readJoystick1X());
 
      break;
 
    case 3:
 
      _Joy_a = Joy_dead_zone(Joypad.readJoystick1Y());
 
      break;
 
  }
 
 
 
  if (_Joy_b)
 
  {
 
    if (_Joy_a < 0)
 
      _Joy_a = map(_Joy_a, joy_correct_min[_Joy_i], 0, _Joy_MAX, Joy_MID);
 
    else
 
      _Joy_a = map(_Joy_a, 0, joy_correct_max[_Joy_i], Joy_MID, _Joy_MIN);
 
 
 
    if (_Joy_a < _Joy_MIN) _Joy_a = _Joy_MIN;
 
    if (_Joy_a > _Joy_MAX) _Joy_a = _Joy_MAX;
 
  }
 
  return _Joy_a;
 
}
 
 
 
void Joy()
 
{
 
  sw_l = Joypad.readButton(CH_SWITCH_L);
 
  sw_r = Joypad.readButton(CH_SWITCH_R);
 
 
 
  //------------------------------------
 
  //s_lig=Joypad.readLightSensor();
 
  //s_mic=Joypad.readMicrophone();
 
 
 
  //------------------------------------
 
  Joy_sw = Joypad.readButton(CH_JOYSTICK_SW);
 
  Joy1_sw = Joypad.readButton(CH_JOYSTICK1_SW);
 
 
 
  //------------------------------------
 
  but1 = Joypad.readButton(CH_SWITCH_1);
 
  but2 = Joypad.readButton(CH_SWITCH_2);
 
  but3 = Joypad.readButton(CH_SWITCH_3);
 
  but4 = Joypad.readButton(CH_SWITCH_4);
 
 
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
  //====================================
 
  int16_t y[3];        //MPU---------------------------------
 
  if (mode_mpu)     //MPU---------------------------------
 
  {
 
    for (uint8_t a = 0; a < 3; a++)
 
    {
 
      y[a] = ypr[a] * 180 / M_PI;
 
      if (y[a] > MPU_maximum) y[a] = MPU_maximum;
 
      if (y[a] < -MPU_maximum) y[a] = -MPU_maximum;
 
    }
 
  }
 
#endif
 
 
 
  if (Joypad.readButton(CH_SWITCH_R))
 
  {
 
    Joy_x = Joy_i(0, true, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
    Joy_y = Joy_i(1, true, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
 
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
    if (mode_mpu)    //MPU---------------------------------
 
    {
 
      Joy1_x = map(y[2], -MPU_maximum, MPU_maximum, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
      Joy1_y = map(y[1], -MPU_maximum, MPU_maximum, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
    }
 
    else
 
#endif
 
    {
 
      Joy1_x = Joy_i(2, true, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
      Joy1_y = Joy_i(3, true, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
    }
 
  }
 
  else
 
  {
 
     Joy_x = Joy_i(0, true, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum);
 
     Joy_y = Joy_i(1, true, mode_protocol ? Joy_MID - Joy_s_maximum : Joy_MID - Joy_maximum, mode_protocol ? Joy_MID + Joy_s_maximum : Joy_MID + Joy_maximum); //  Robot,QuadCopter
 
 
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
     if (mode_mpu)    //MPU---------------------------------
 
     {
 
      Joy1_x = map(y[2], -MPU_maximum, MPU_maximum, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum);
 
      Joy1_y = map(y[1], -MPU_maximum, MPU_maximum, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum);
 
     }
 
     else
 
#endif
 
     {
 
      Joy1_x = Joy_i(2, true, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum);
 
      Joy1_y = Joy_i(3, true, Joy_MID - Joy_s_maximum, Joy_MID + Joy_s_maximum);
 
    }
 
  }
 
}
 
 
 
 
</source>
 
</source>
key.h
+
*WiFi控制部分
 
<source lang="cpp">
 
<source lang="cpp">
#include "arduino.h"
+
// These are the interrupt and control pins
 
+
#define ADAFRUIT_CC3000_IRQ  2  // MUST be an interrupt pin!
uint8_t key_pin[4] = {CH_SWITCH_1, CH_SWITCH_2, CH_SWITCH_3, CH_SWITCH_4}; //按键1 2 3 4
+
// These can be any two pins
 
+
#define ADAFRUIT_CC3000_VBAT  9
boolean key_status[4]; //按键
+
#define ADAFRUIT_CC3000_CS    10
boolean key_cache[4]; //检测按键松开缓存
+
#define WLAN_SECURITY  WLAN_SEC_WPA2
 
+
#define IDLE_TIMEOUT_MS          1000
void key_init()
+
// Use hardware SPI for the remaining pins
{
+
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
  for (uint8_t a = 0; a < 4; a++)
+
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
  {
+
    key_status[a] = LOW;
+
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
    key_cache[a] = HIGH;
+
  }
+
uint32_t ip;
}
+
Adafruit_CC3000_Client www;  
 
+
/**************************************************************************/
boolean key_get(uint8_t _key_num, boolean _key_type)
+
/*!
{
+
@brief  Tries to read the IP address and other connection details
  key_cache[_key_num] = key_status[_key_num]; //缓存作判断用
+
*/
 
+
/**************************************************************************/ •R");
  key_status[_key_num] = !Joypad.readButton(key_pin[_key_num]); //触发时
+
            Serial.println(F("Failed!"));
 
+
            return false;
  switch (_key_type)
+
        }
  {
+
        else
     case 0:
+
        {
      if (!key_status[_key_num] && key_cache[_key_num]) //按下松开后
+
            Serial.println("\n2/4 connect AP OK");
         return true;
+
            return true;
      else
+
        }
         return false;
+
    }
      break;
+
    break;
    case 1:
+
    case 2:
      if (key_status[_key_num] && !key_cache[_key_num]) //按下松开后
+
    {
        return true;
+
        Serial.println("\n 3/4 dhcp READY");
      else
+
        if(!voCC3000_get_dhcp())
         return false;
+
        {
      break;
+
            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>
mpu.h
 
<source lang="cpp">
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
#include "Wire.h"
 
#include "I2Cdev.h"
 
#include "MPU6050_6Axis_MotionApps20.h"
 
 
MPU6050 mpu;
 
 
//MPU-------------
 
#define MPU_maximum 70
 
 
// MPU control/status vars
 
boolean dmpReady = false;  // set true if DMP init was successful
 
uint8_t mpuIntStatus;  // holds actual interrupt status byte from MPU
 
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
 
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
 
uint16_t fifoCount;    // count of all bytes currently in FIFO
 
uint8_t fifoBuffer[64]; // FIFO storage buffer
 
 
// orientation/motion vars
 
Quaternion q;          // [w, x, y, z]        quaternion container
 
VectorInt16 aa;        // [x, y, z]            accel sensor measurements
 
VectorFloat gravity;    // [x, y, z]            gravity vector
 
float ypr[3];          // [yaw, pitch, roll]  yaw/pitch/roll container and gravity vector
 
 
void initMPU()
 
{
 
  Wire.begin();
 
#ifdef Serial_DEBUG
 
  Serial.println(F("Initializing I2C devices..."));
 
#endif
 
  mpu.initialize();
 
  // verify connection
 
#ifdef Serial_DEBUG
 
  Serial.println(F("Testing device connections..."));
 
#endif
 
  if (mpu.testConnection())
 
  {
 
#ifdef Serial_DEBUG
 
    Serial.println("MPU6050 connection successful");
 
#endif
 
  }
 
#ifdef Serial_DEBUG
 
  else
 
    Serial.println(F("MPU6050 connection failed"));
 
#endif
 
 
  // load and configure the DMP
 
#ifdef Serial_DEBUG
 
  Serial.println(F("Initializing DMP..."));
 
#endif
 
  devStatus = mpu.dmpInitialize();
 
 
  // make sure it worked (returns 0 if so)
 
  if (devStatus == 0) {
 
    // turn on the DMP, now that it's ready
 
#ifdef Serial_DEBUG
 
    Serial.println(F("Enabling DMP..."));
 
#endif
 
    mpu.setDMPEnabled(true);
 
 
    mpuIntStatus = mpu.getIntStatus();
 
 
    // set our DMP Ready flag so the main loop() function knows it's okay to use it
 
    //    Serial.println(F("DMP ready! Waiting for first interrupt..."));
 
    dmpReady = true;
 
 
    // get expected DMP packet size for later comparison
 
    packetSize = mpu.dmpGetFIFOPacketSize();
 
  }
 
  else {
 
    // ERROR!
 
    // 1 = initial memory load failed
 
    // 2 = DMP configuration updates failed
 
    // (if it's going to break, usually the code will be 1)
 
#ifdef Serial_DEBUG
 
    Serial.print(F("DMP Initialization failed (code "));
 
    Serial.print(devStatus);
 
    Serial.println(F(")"));
 
#endif
 
  }
 
}
 
 
void getMPU()
 
{
 
  if (!dmpReady) return;
 
  {
 
    // reset interrupt flag and get INT_STATUS byte
 
    mpuIntStatus = mpu.getIntStatus();
 
 
    // get current FIFO count
 
    fifoCount = mpu.getFIFOCount();
 
 
    // check for overflow (this should never happen unless our code is too inefficient)
 
    if ((mpuIntStatus & 0x10) || fifoCount == 1024)
 
    {
 
      // reset so we can continue cleanly
 
      mpu.resetFIFO();
 
#ifdef Serial_DEBUG
 
      Serial.println(F("FIFO overflow!"));
 
#endif
 
      // otherwise, check for DMP data ready interrupt (this should happen frequently)
 
    }
 
    else if (mpuIntStatus & 0x02)
 
    {
 
      // wait for correct available data length, should be a VERY short wait
 
      while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
 
 
      // read a packet from FIFO
 
      mpu.getFIFOBytes(fifoBuffer, packetSize);
 
 
      // track FIFO count here in case there is > 1 packet available
 
      // (this lets us immediately read more without waiting for an interrupt)
 
      fifoCount -= packetSize;
 
 
      // display ypr angles in degrees
 
      mpu.dmpGetQuaternion(&q, fifoBuffer);
 
      mpu.dmpGetGravity(&gravity, &q);
 
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
 
 
      //Serial.print("ypr\t");
 
      //Serial.print(ypr[0] * 180/M_PI);
 
      //Serial.print("\t");
 
      //Serial.print(ypr[1] * 180/M_PI);
 
      //Serial.print("\t");
 
      // Serial.println(ypr[2] * 180/M_PI);
 
    }
 
  }
 
}
 
 
#endif
 
</source>
 
mwc.h
 
<source lang="cpp">
 
#include "Arduino.h"
 
 
#if defined(__AVR_ATmega128RFA1__)
 
#include <ZigduinoRadio.h>
 
#endif
 
 
int16_t RCin[8], RCoutA[8], RCoutB[8];
 
 
int16_t p;
 
uint16_t read16()
 
{
 
  uint16_t r = (inBuf[p++] & 0xFF);
 
  r += (inBuf[p++] & 0xFF) << 8;
 
  return r;
 
}
 
 
uint16_t t, t1, t2;
 
uint16_t write16(boolean a)
 
{
 
  if (a)
 
  {
 
    t1 = outBuf[p++] >> 8;
 
    t2 = outBuf[p - 1] - (t1 << 8);
 
    t = t1;
 
  }
 
  else
 
    t = t2;
 
  return t;
 
}
 
 
typedef  unsigned char byte;
 
byte getChecksum(byte length, byte cmd, byte mydata[])
 
{
 
  //三个参数分别为: 数据长度  ,  指令代码  ,  实际数据数组
 
  byte checksum = 0;
 
  checksum ^= (length & 0xFF);
 
  checksum ^= (cmd & 0xFF);
 
  for (uint8_t i = 0; i < length; i++)
 
  {
 
    checksum ^= (mydata[i] & 0xFF);
 
  }
 
  return checksum;
 
}
 
 
void data_rx()
 
{
 
  //  s_struct_w((int*)&inBuf,16);
 
  p = 0;
 
  for (uint8_t i = 0; i < 8; i++)
 
  {
 
    RCin[i] = read16();
 
    /*
 
    Serial.print("RC[");
 
    Serial.print(i+1);
 
    Serial.print("]:");
 
 
    Serial.print(inBuf[2*i],DEC);
 
    Serial.print(",");
 
    Serial.print(inBuf[2*i+1],DEC);
 
 
    Serial.print("---");
 
    Serial.println(RCin[i]);
 
    */
 
    //    delay(50);        // delay in between reads for stability
 
  }
 
}
 
 
void data_tx()
 
{
 
  p = 0;
 
  for (uint8_t i = 0; i < 8; i++)
 
  {
 
    RCoutA[i] = write16(1);
 
    RCoutB[i] = write16(0);
 
 
    /*
 
    Serial.print("RC[");
 
    Serial.print(i+1);
 
    Serial.print("]:");
 
 
    Serial.print(RCout[i]);
 
 
    Serial.print("---");
 
 
    Serial.print(RCoutA[i],DEC);
 
    Serial.print(",");
 
    Serial.print(RCoutB[i],DEC);
 
 
    Serial.println("");
 
    */
 
    //    delay(50);        // delay in between reads for stability
 
  }
 
}
 
 
/*
 
if Core RF
 
[head,2byte,0xAA 0xBB] [type,1byte,0xCC] [data,16byte] [body,1byte(from getChecksum())]
 
Example:
 
AA BB CC 1A 01 1A 01 1A 01 2A 01 3A 01 4A 01 5A 01 6A 01 0D **
 
*/
 
void data_send()
 
{
 
  data_tx();
 
 
#if !defined(__AVR_ATmega128RFA1__)
 
  static byte buf_head[3];
 
  buf_head[0] = 0x24;
 
  buf_head[1] = 0x4D;
 
  buf_head[2] = 0x3C;
 
#endif
 
 
#define buf_length 0x10  //16
 
#define buf_code 0xC8    //200
 
 
  static byte buf_data[buf_length];
 
  for (uint8_t a = 0; a < (buf_length / 2); a++)
 
  {
 
    buf_data[2 * a] = RCoutB[a];
 
    buf_data[2 * a + 1] = RCoutA[a];
 
  }
 
 
  static byte buf_body;
 
  buf_body = getChecksum(buf_length, buf_code, buf_data);
 
 
  //----------------------
 
#if defined(__AVR_ATmega128RFA1__)
 
  mwc_port.beginTransmission();
 
  mwc_port.write(0xaa);
 
  mwc_port.write(0xbb);
 
  mwc_port.write(0xcc);
 
#else
 
  for (uint8_t a = 0; a < 3; a++) {
 
    mwc_port.write(buf_head[a]);
 
  }
 
  mwc_port.write(buf_length);
 
  mwc_port.write(buf_code);
 
#endif
 
  for (uint8_t a = 0; a < buf_length; a++) {
 
    mwc_port.write(buf_data[a]);
 
  }
 
  mwc_port.write(buf_body);
 
#if defined(__AVR_ATmega128RFA1__)
 
  mwc_port.endTransmission();
 
#endif
 
}
 
</source>
 
nrf.h
 
<source lang="cpp">
 
#include "Arduino.h"
 
 
#include <RF24Network.h>
 
#include <RF24.h>
 
#include <SPI.h>
 
 
// nRF24L01(+) radio attached using Getting Started board
 
RF24 radio(9, 10);  //ce,cs
 
RF24Network network(radio);
 
 
#define this_node  0 //设置本机ID
 
#define other_node 1
 
 
//--------------------------------
 
struct send_a //发送
 
{
 
  uint32_t ms;
 
  uint16_t rf_CH0;
 
  uint16_t rf_CH1;
 
  uint16_t rf_CH2;
 
  uint16_t rf_CH3;
 
  uint16_t rf_CH4;
 
  uint16_t rf_CH5;
 
  uint16_t rf_CH6;
 
  uint16_t rf_CH7;
 
};
 
 
struct receive_a //接收
 
{
 
  uint32_t node_ms;
 
};
 
 
//--------------------------------
 
unsigned long node_clock, node_clock_debug, node_clock_cache = 0; //节点运行时间、节点响应检查时间、节点时间缓存
 
 
//debug--------------------------
 
boolean node_clock_error = false; //节点响应状态
 
unsigned long time_debug = 0; //定时器
 
 
 
//======================================
 
void vodebug()
 
{
 
  if (millis() - time_debug > interval_debug)
 
  {
 
    node_clock_error = boolean(node_clock == node_clock_debug); //一定时间内,节点返回的运行时间若不变则有问题
 
 
    node_clock_debug = node_clock;
 
 
    time_debug = millis();
 
  }
 
}
 
 
 
void nrf_send()
 
{
 
#ifdef Serial_DEBUG
 
  Serial.print("Sending...");
 
#endif
 
 
  send_a sen = {
 
    millis(), outBuf[0], outBuf[1], outBuf[2], outBuf[3], outBuf[4], outBuf[5], outBuf[6], outBuf[7]
 
  }; //把这些数据发送出去,对应前面的发送数组
 
  RF24NetworkHeader header(other_node);
 
  if (network.write(header, &sen, sizeof(sen)))
 
  {
 
#ifdef Serial_DEBUG
 
    Serial.print("Is ok.");
 
#endif
 
 
    delay(50);
 
    network.update();
 
    // If it's time to send a message, send it!
 
    while ( network.available() )
 
    {
 
      // If so, grab it and print it out
 
      RF24NetworkHeader header;
 
      receive_a rec;
 
      network.read(header, &rec, sizeof(rec));
 
 
      node_clock = rec.node_ms; //运行时间赋值
 
    }
 
  }
 
#ifdef Serial_DEBUG
 
  else
 
    Serial.print("Is failed.");
 
 
  Serial.println("");
 
#endif
 
}
 
</source>
 
tft.h
 
<source lang="cpp">
 
#include "Arduino.h"
 
 
#include <Adafruit_GFX.h>    // Core graphics library
 
#include <Adafruit_ST7735.h> // Hardware-specific library
 
#include <SPI.h>
 
 
Adafruit_ST7735 tft = Adafruit_ST7735(5, 4, -1);    //cs,dc,rst
 
//-------字体设置,大、中、小
 
#define setFont_M tft.setTextSize(2)
 
#define setFont_S tft.setTextSize(0)
 
 
#define tft_width  128
 
#define tft_height 160
 
 
boolean tft_theme = false;  //0 is white,1 is black
 
boolean tft_rotation = 1;
 
 
#define TFT_TOP ST7735_BLACK
 
#define TFT_BUT ST7735_WHITE
 
 
uint16_t  tft_colorA = TFT_BUT;
 
uint16_t  tft_colorB = TFT_TOP;
 
uint16_t  tft_colorC = 0x06FF;
 
uint16_t  tft_colorD = 0xEABF;
 
 
#define tft_bat_x 24
 
#define tft_bat_y 12
 
#define tft_bat_x_s 2
 
#define tft_bat_y_s 6
 
 
#define tft_font_s_height 8
 
#define tft_font_m_height 16
 
#define tft_font_l_height 24
 
 
#define _Q_x 33
 
#define _Q_y 36
 
#define _W_x 93
 
#define _W_y 5
 
 
#define _Q_font_x 2
 
#define _Q_font_y (_Q_y - 1)
 
 
int8_t tft_cache = 1;
 
 
//======================================
 
void TFT_clear()
 
{
 
  tft.fillScreen(tft_colorB);
 
}
 
 
void TFT_init(boolean _init, boolean _rot)
 
{
 
  tft_colorB = tft_theme ? TFT_TOP : TFT_BUT;
 
  tft_colorA = tft_theme ? TFT_BUT : TFT_TOP;
 
 
  if (_init) {
 
    tft.initR(INITR_BLACKTAB);  // initialize a ST7735S chip, black tab
 
    //  Serial.println("init");
 
    tft.fillScreen(tft_colorB);
 
 
    if (_rot)
 
      tft.setRotation(2);
 
  }
 
 
  tft.fillRect(0, 0, tft_width, 40, tft_colorA);
 
  tft.setTextColor(tft_colorB);
 
  setFont_M;
 
  tft.setCursor(26, 6);
 
  tft.print("Joypad");
 
  setFont_S;
 
  tft.setCursor(32, 24);
 
  tft.print("Microduino");
 
  tft.fillRect(0, 40, tft_width, 120, tft_colorB);
 
}
 
 
void TFT_begin()
 
{
 
  setFont_S;
 
 
  tft.setTextColor(tft_colorA);
 
  tft.setCursor(_Q_font_x, 44);
 
  tft.println("[key1] enter config");
 
 
  setFont_M;
 
  tft.setCursor(4, 150);
 
  for (uint8_t a = 0; a < (millis() - TIME1) / (interval_TIME1 / 10); a++) {
 
    tft.print("-");
 
  }
 
}
 
 
int8_t menu_num_A = 0;
 
int8_t menu_num_B = 0;
 
int8_t menu_sta = 0;
 
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
char *menu_str_a[5] = {
 
  "Joystick Config", "Protocol Config", "System Config", "Gyroscope Config", "Exit"
 
};
 
#else
 
char *menu_str_a[4] = {
 
  "Joystick Config", "Protocol Config", "System Config", "Exit"
 
};
 
#endif
 
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
char *menu_str_b[4][3] = {
 
  {"Joystick Correct.", "Dead Zone config"},
 
  {"Mode", "Quadrotor Channel", "nRF24 Channel"},
 
  {"TFT Theme", "TFT Rotation", "MCU Voltage"},
 
  {"Gyroscope OFF", "Gyroscope ON"}
 
};
 
#else
 
char *menu_str_b[3][3] = {
 
  {"Joystick Correct.", "Dead Zone config"},
 
  {"Mode", "Quadrotor Channel", "nRF24 Channel"},
 
  {"TFT Theme", "TFT Rotation", "MCU Voltage"},
 
};
 
#endif
 
 
void TFT_menu(int8_t _num, char *_data)
 
{
 
  tft.drawRect(7, 49 + 15 * _num, 114, 16, tft_colorA);
 
  tft.setCursor(10, 54 + 15 * _num);
 
  tft.print(_data);
 
}
 
 
void TFT_menu(int8_t _num, int16_t _data)
 
{
 
  tft.drawRect(7, 49 + 15 * _num, 114, 16, tft_colorA);
 
  tft.setCursor(10, 54 + 15 * _num);
 
  tft.print(_data);
 
}
 
 
void TFT_cursor(int8_t _num)
 
{
 
  tft.drawLine(1, 51 + 15 * _num, 4, 56 + 15 * _num, tft_colorA);
 
  tft.drawLine(4, 57 + 15 * _num, 1, 62 + 15 * _num, tft_colorA);
 
  tft.drawLine(1, 51 + 15 * _num, 1, 62 + 15 * _num, tft_colorA);
 
}
 
 
boolean return_menu = false;
 
 
boolean TFT_config()
 
{
 
  tft.setTextColor( tft_colorA);
 
 
  if (key_get(0, 1)) {
 
    menu_sta --;
 
    tft_cache = 1;
 
 
    if (menu_sta <= 0)
 
      menu_num_B = 0; //zero
 
  }
 
  if (key_get(1, 1)) {
 
    if (return_menu)
 
      menu_sta --;
 
    else
 
      menu_sta ++;
 
    tft_cache = 1;
 
  }
 
 
  if (menu_sta > 2)
 
    menu_sta = 2;
 
  if (menu_sta < 0)
 
    menu_sta = 0;
 
 
  return_menu = false;
 
  //-------------------------------
 
  if (tft_cache)
 
    tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
 
  if (menu_sta == 2) {
 
    switch (menu_num_A) {
 
      case 0: {
 
          switch (menu_num_B) {
 
            case 0: {
 
                if (tft_cache)
 
                {
 
                  for (uint8_t a = 0; a < 4; a++)
 
                  {
 
                    joy_correct_min[a] = 0;
 
                    joy_correct_max[a] = 0;
 
                  }
 
                }
 
                for (uint8_t a = 0; a < 4; a++) {
 
                  tft.setCursor(2, 120);
 
                  tft.print("Move Joystick MaxGear");
 
                  int16_t _c = Joy_i(a, false, Joy_MID - Joy_maximum, Joy_MID + Joy_maximum);
 
                  if (_c > joy_correct_max[a]) {
 
                    tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                    joy_correct_max[a] = _c;
 
                  }
 
                  //                  joy_correct_max[a] = constrain(joy_correct_max[a], 0, Joy_maximum);
 
                  if (_c < joy_correct_min[a]) {
 
                    tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                    joy_correct_min[a] = _c;
 
                  }
 
                  //                  joy_correct_min[a] = constrain(joy_correct_min[a], -Joy_maximum, 0);
 
                }
 
 
                for (uint8_t d = 0; d < 2; d++) {
 
                  tft.drawFastHLine(12 + 70 * d, 80, 33, tft_colorA);
 
                  tft.drawFastVLine(28 + 70 * d, 64, 33, tft_colorA);
 
                  //                tft.fillRect(2, 90-4, 20, 12, tft_colorB);
 
                  tft.drawCircle(44 + 70 * d, 80, map(joy_correct_min[0 + 2 * d], 0, -512, 1, 10), tft_colorA);
 
                  tft.drawCircle(12 + 70 * d, 80, map(joy_correct_max[0 + 2 * d], 0, 512, 1, 10), tft_colorA);
 
                  tft.drawCircle(28 + 70 * d, 64, map(joy_correct_min[1 + 2 * d], 0, -512, 1, 10), tft_colorA);
 
                  tft.drawCircle(28 + 70 * d, 96, map(joy_correct_max[1 + 2 * d], 0, 512, 1, 10), tft_colorA);
 
                }
 
                return_menu = true;
 
              }
 
              break;
 
            case 1: {
 
                if (key_get(2, 1)) {
 
                  Joy_deadzone_val--;
 
                  tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                }
 
                if (key_get(3, 1)) {
 
                  Joy_deadzone_val++;
 
                  tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                }
 
                Joy_deadzone_val = constrain(Joy_deadzone_val, 0, 25);
 
 
                TFT_menu(0, Joy_deadzone_val);
 
                TFT_cursor(0);
 
                return_menu = true;
 
              }
 
              break;
 
          }
 
        }
 
        break;
 
 
      case 1: {
 
          switch (menu_num_B) {
 
            case 0: {
 
                char *menu_str_c[2] = { "Quadro.", "nRF24"};
 
                if (key_get(2, 1) || key_get(3, 1)) {
 
                  mode_protocol = !mode_protocol;
 
                  tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                }
 
                for (uint8_t c = 0; c < 2; c++) {
 
                  TFT_menu(c, menu_str_c[c]);
 
                }
 
 
                TFT_cursor(mode_protocol);
 
                return_menu = true;
 
              }
 
              break;
 
            case 1: {
 
#if !defined(__AVR_ATmega128RFA1__)
 
                char *menu_str_c[5] = {"9600", "19200", "38400", "57600", "115200"};
 
#endif
 
                if (key_get(2, 1)) {
 
                  mwc_channal--;
 
                  tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                }
 
                if (key_get(3, 1)) {
 
                  mwc_channal++;
 
                  tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                }
 
 
#if !defined(__AVR_ATmega128RFA1__)
 
                mwc_channal = constrain(mwc_channal, 0, 4);
 
                TFT_menu(0, menu_str_c[mwc_channal]);
 
#else
 
                mwc_channal = constrain(mwc_channal, 11, 26);
 
                TFT_menu(0, mwc_channal);
 
#endif
 
                TFT_cursor(0);
 
                return_menu = true;
 
              }
 
              break;
 
 
            case 2: {
 
                if (key_get(2, 1)) {
 
                  nrf_channal--;
 
                  tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                }
 
                if (key_get(3, 1)) {
 
                  nrf_channal++;
 
                  tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                }
 
                nrf_channal = constrain(nrf_channal, 0, 125);
 
 
                TFT_menu(0, nrf_channal);
 
                TFT_cursor(0);
 
                return_menu = true;
 
              }
 
              break;
 
          }
 
        }
 
        break;
 
      case 2: {
 
          switch (menu_num_B) {
 
            case 0: {
 
                tft_theme = !tft_theme;
 
                TFT_init(true, tft_rotation);
 
                tft_cache = 1;
 
                tft.setTextColor(tft_colorA);
 
                menu_sta --;
 
              }
 
              break;
 
            case 1: {
 
                tft_rotation = !tft_rotation;
 
                TFT_init(true, tft_rotation);
 
                tft_cache = 1;
 
                tft.setTextColor(tft_colorA);
 
                menu_sta --;
 
              }
 
              break;
 
            case 2: {
 
                char *menu_str_c[2] = { "3.3V", "5.0V"};
 
                return_menu = true;
 
 
                if (key_get(2, 1) || key_get(3, 1)) {
 
                  mcu_voltage = !mcu_voltage;
 
                  tft.fillRect(0, 40, tft_width, 100, tft_colorB);
 
                }
 
 
                TFT_cursor(mcu_voltage);
 
 
                for (uint8_t c = 0; c < 2; c++) {
 
                  TFT_menu(c, menu_str_c[c]);
 
                }
 
                //                tft.fillRect(0, 40, tft_width, 100,tft_colorB);
 
              }
 
              break;
 
          }
 
 
        }
 
        break;
 
 
#if !(defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__))
 
      case 3: { //mpu
 
          mode_mpu = menu_num_B;
 
          tft_cache = 1;
 
          menu_sta = 0; //back main menu
 
          menu_num_B = 0; //zero
 
        }
 
        break;
 
#endif
 
    }
 
  }
 
 
  /*
 
    Serial.print(menu_sta);
 
    Serial.print(",");
 
    Serial.print(menu_num_A);
 
    Serial.print(",");
 
    Serial.println(menu_num_B);
 
  */
 
  //----------------------------
 
  if (menu_sta == 1) {
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
    int8_t meun_b_max[5] = {1, 2, 2, 1, 0};
 
#else
 
    int8_t meun_b_max[4] = {1, 2, 2, 0};
 
#endif
 
    if (!meun_b_max[menu_num_A])
 
      return false;
 
    else {
 
      if (key_get(2, 1)) {
 
        tft.fillRect(0, 40, 5, 100, tft_colorB);
 
        menu_num_B--;
 
      }
 
      if (key_get(3, 1)) {
 
        tft.fillRect(0, 40, 5, 100, tft_colorB);
 
        menu_num_B++;
 
      }
 
      menu_num_B = constrain(menu_num_B, 0, meun_b_max[menu_num_A]);
 
 
      TFT_cursor(menu_num_B);
 
 
      if (tft_cache) {
 
        for (uint8_t b = 0; b < (meun_b_max[menu_num_A] + 1); b++) {
 
          TFT_menu(b, menu_str_b[menu_num_A][b]);
 
        }
 
      }
 
    }
 
  }
 
 
  //main menu
 
  if (menu_sta == 0) {
 
    //custer
 
    if (key_get(2, 1)) {
 
      tft.fillRect(0, 40, 5, 100, tft_colorB);
 
      menu_num_A--;
 
    }
 
    if (key_get(3, 1)) {
 
      tft.fillRect(0, 40, 5, 100, tft_colorB);
 
      menu_num_A++;
 
    }
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
    menu_num_A = constrain(menu_num_A, 0, 4);
 
#else
 
    menu_num_A = constrain(menu_num_A, 0, 3);
 
#endif
 
 
    TFT_cursor(menu_num_A);
 
 
    if (tft_cache) {
 
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega128RFA1__)
 
      for (uint8_t a = 0; a < 5; a++) {
 
#else
 
      for (uint8_t a = 0; a < 4; a++) {
 
#endif
 
        TFT_menu(a, menu_str_a[a]);
 
      }
 
    }
 
  }
 
 
  if (tft_cache) {
 
    //BACK
 
    tft.fillCircle(12, 149, 8, tft_colorA);
 
    tft.drawLine(11, 145, 7, 149, tft_colorB);
 
    tft.drawLine(7, 149, 11, 153, tft_colorB);
 
    tft.drawLine(7, 149, 17, 149, tft_colorB);
 
    //ENTER
 
    tft.fillCircle(12 + 20, 149, 8, tft_colorA);
 
    tft.drawLine(10 + 20, 146, 7 + 20, 149, tft_colorB);
 
    tft.drawLine(7 + 20, 149, 10 + 20, 152, tft_colorB);
 
    tft.drawLine(7 + 20, 149, 15 + 20, 149, tft_colorB);
 
    tft.drawLine(15 + 20, 146, 15 + 20, 149, tft_colorB);
 
    //PREV
 
    tft.fillCircle(127 - 12, 149, 8, tft_colorA);
 
    tft.drawLine(127 - 12, 153, 127 - 8, 149, tft_colorB);
 
    tft.drawLine(127 - 12, 153, 127 - 16, 149, tft_colorB);
 
    tft.drawLine(127 - 12, 153, 127 - 12, 145, tft_colorB);
 
    //NEXT
 
    tft.fillCircle(127 - 32, 149, 8, tft_colorA);
 
    tft.drawLine(127 - 32, 145, 127 - 28, 149, tft_colorB);
 
    tft.drawLine(127 - 32, 145, 127 - 36, 149, tft_colorB);
 
    tft.drawLine(127 - 32, 145, 127 - 32, 153, tft_colorB);
 
  }
 
  tft_cache --;
 
  if (tft_cache < 0)  tft_cache = 0;
 
 
  return true;
 
}
 
 
//------------------
 
#define _C_x_S  (_Q_x + 1)
 
#define _C_x_M  (_Q_x + ((_W_x + 1) / 2))
 
#define _C_x_E  (_Q_x + _W_x - 1)
 
 
char *NAME[8] = {
 
  "ROLL", "PITCH", "YAW", "THROT", "AUX1", "AUX2", "AUX3", "AUX4"
 
};
 
 
void TFT_ready()
 
{
 
  tft.fillRect(0, 0, 128, 26, tft_colorA);
 
 
  tft.drawRect(tft_width - tft_bat_x - tft_bat_x_s - 2, 2, tft_bat_x, tft_bat_y, tft_colorB);
 
  tft.drawRect(tft_width - tft_bat_x_s - 2, 2 + (tft_bat_y - tft_bat_y_s) / 2, tft_bat_x_s, tft_bat_y_s, tft_colorB);
 
 
  tft.setTextColor(tft_colorB);
 
  setFont_S;
 
 
  tft.setCursor(_Q_font_x, 3);
 
  tft.print(mode_protocol ? "nRF24" : "Quadr");
 
  tft.print(" CHAN.");
 
  tft.print(mode_protocol ? nrf_channal : mwc_channal);
 
  tft.setCursor(_Q_font_x, 16);
 
  tft.print("Time:");
 
 
  tft.setTextColor(tft_colorA);
 
  for (uint8_t a = 0; a < 8; a++) {
 
    tft.setCursor(_Q_font_x, _Q_font_y + a * 15);
 
    tft.print(NAME[a]);
 
    //------------------------------------------
 
    tft.drawRect(_Q_x, _Q_y + a * 15, _W_x, _W_y, tft_colorA);
 
  }
 
}
 
 
boolean _a = false, _b = false;
 
void TFT_run()
 
{
 
  if (outBuf[3] > (Joy_MID - Joy_maximum)) {
 
    if (_a) {
 
      Joy_time[0] = millis() - Joy_time[1];
 
      _a = false;
 
    }
 
    Joy_time[1] = millis() - Joy_time[0];
 
  }
 
  else
 
    _a = true;
 
 
  if (!_b && ((Joy_time[1] / 1000) % 2)) {
 
    _b = !_b;
 
    tft.fillRect(_Q_font_x + 30, 16, 50, 7, tft_colorA);
 
    tft.setTextColor(tft_colorB);
 
    tft.setCursor(_Q_font_x + 30, 16);
 
    tft.print((Joy_time[1] / 1000) / 60);
 
    tft.print("m");
 
    tft.print((Joy_time[1] / 1000) % 60);
 
    tft.print("s");
 
  }
 
  _b = boolean((Joy_time[1] / 1000) % 2);
 
 
  //battery------------------
 
  tft.fillRect(tft_width - tft_bat_x - 3, 3, map(_V_bat, _V_min, _V_max, 0, tft_bat_x - 2) , tft_bat_y - 2, tft_colorB);
 
  tft.fillRect(tft_width - tft_bat_x - 3 + map(_V_bat, _V_min, _V_max, 0, tft_bat_x - 2), 3, map(_V_bat, _V_min, _V_max, tft_bat_x - 2, 0) , tft_bat_y - 2, tft_colorA);
 
 
  for (uint8_t a = 0; a < 8; a++) {
 
    int8_t _C_x_A0, _C_x_B0, _C_x_A, _C_x_B, _C_x_A1, _C_x_B1;
 
    int8_t _C_x;
 
 
    if (outBuf[a] < Joy_MID) {
 
      _C_x = map(outBuf[a], Joy_MID - Joy_maximum, Joy_MID, _C_x_S, _C_x_M);
 
 
      _C_x_A0 = _C_x_S;
 
      _C_x_B0 = _C_x - _C_x_S;
 
 
      _C_x_A = _C_x;
 
      _C_x_B = _C_x_M - _C_x;
 
 
      _C_x_A1 = _C_x_M;
 
      _C_x_B1 = _C_x_E - _C_x_M;
 
    } else if (outBuf[a] > Joy_MID) {
 
      _C_x = map(outBuf[a], Joy_MID, Joy_MID + Joy_maximum, _C_x_M, _C_x_E);
 
 
      _C_x_A0 = _C_x_S;
 
      _C_x_B0 = _C_x_M - _C_x_S;
 
 
      _C_x_A = _C_x_M;
 
      _C_x_B = _C_x - _C_x_M;
 
 
      _C_x_A1 = _C_x;
 
      _C_x_B1 = _C_x_E - _C_x;
 
    } else {
 
      _C_x_A0 = _C_x_S;
 
      _C_x_B0 = _C_x_M - _C_x_S;
 
 
      _C_x_A = _C_x_M;
 
      _C_x_B = 0;
 
 
      _C_x_A1 = _C_x_M;
 
      _C_x_B1 = _C_x_E - _C_x_M;
 
    }
 
    tft.fillRect(_C_x_A0,  _Q_y + a * 15 + 1, _C_x_B0, _W_y - 2, tft_colorB);
 
    tft.fillRect(_C_x_A,  _Q_y + a * 15 + 1, _C_x_B, _W_y - 2, tft_colorC);
 
    tft.fillRect(_C_x_A1,  _Q_y + a * 15 + 1, _C_x_B1, _W_y - 2, tft_colorB);
 
 
    tft.fillRect(_C_x_M,  _Q_y + a * 15 - 1, 1, _W_y + 2, tft_colorD);
 
  }
 
  //netsta------------------
 
  tft.fillRect(0, 158, 128, 2, node_clock_error ? tft_colorD : tft_colorC);
 
}
 
</source>
 
time.h
 
<source lang="cpp">
 
#include "Arduino.h"
 
 
//unsigned long time;
 
unsigned long TIME1;            //setup delay
 
unsigned long time2; //send data
 
unsigned long time3; //battery
 
unsigned long Joy_time[2] = {0, 0}; //joy
 
</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"); 
    } 
}

视频