1. 简介

TinkerNode NB-IoT物联网开发板是ESP32平台(WiFi+Bluetooth4.0)的具有NB-IoT低功耗蜂窝通信和GPS/BeiDou双星精确定位功能的四模低功耗物联网开发硬件平台,为广大创客和软硬件开发者提供NB-IoT项目开发与制作的全方位支持,一板玩转物联网。

开发板在不到一半手掌大的面积上集成了ESP32主控模组、NB-IoT/GNSS通信模组、RGB指示灯、按钮、电源管理系统等功能,并通过过孔焊盘引出如IIC、SPI、UART等所有常用的IO、通信接口和电源管脚,性能强悍,扩展性极强。最难得的是,在开发板集成了专用的太阳能电源管理芯片和多电源管理电路,可直接使用5V太阳能板给3.7V锂电池充电和系统供电,同时支持MPPT,最大化太阳能板的输出效率,实现系统在户外应用场景的不间断供电,免去定期充电维护的麻烦。而对于之前已经使用过ESP32平台(如:FireBeetle、掌控、乐鑫官方开发板等)的用户,可以方便地将之前的Arduino程序移植到这块新主控板,在尽享ESP32主控模组所有的强大功能和低功耗能力之余,还能根据我们所提供的丰富示例代码和不断更新的配套项目教程,加入NB-IoT通信和GNSS定位导航相关的代码,快速掌握与实现户外物联网项目的搭建。

2. 物联网与NB-IoT简介

物联网(The Internet of things,IoT)顾名思义,就是物与物相连的互联网。这有两层意思:第一,物联网的核心和基础仍然是互联网,是在互联网基础上的延伸和扩展的网络;第二,其用户端延伸和扩展到了任何物品与物品之间,进行信息交换和通信。

窄带物联网(Narrow Band Internet of Things,NB-IoT)是物联网领域一个新兴的技术,主要用于低移动性、小数据量、对时延不敏感的连接服务,其支持低功耗设备在网络中的数据传输,因此也是一种低功耗广域网(Low Power Wide Area Network,LPWAN)通信技术。相对于被逐渐淘汰的2G通信,NB-IoT具有三大优势:

3. 特性

4. 应用场景

NB-IoT原型开发

户外物联网(NB-IoT+GPS/BeiDou)

室内物联网(WiFi+BT4.0)

5. 技术规格

主控制器 乐鑫ESPRESSIF ESP32

NB-IoT通信模组 移远QUECTEL BC20

IO接口

电源管理

其它功能与特性

  • 注1:采用恒定电压比例MPPT算法,与DFR0559 太阳能电源管理模块5V使用相同主芯片方案,当使用太阳能板供电时,可最大化太阳能板的输出效率。

6. 接口说明

7. 系统原理框图

8. 快速使用

8.1 硬件连接


注意

  • PCB天线背后有3M双面胶,撕开保护层后可贴附于非金属表面,在非金属箱体中使用,如:水质监控站或太阳能气象站的塑料防水盒,项目制作常用的亚克力表面。但是不能贴附于金属表面在金属箱体中使用,否则会严重影响信号质量。

注意

  • 蓝色导热硅胶垫(带双面3M胶)作为双面胶使用(并非用于散热),用于固定陶瓷天线,贴于天线背部金属屏蔽壳与固定物表面之间。

8.2 安装开发板驱动


注意

  • 若安装驱动后,设备管理器中提示Windows 无法验证此设备所需的驱动程序的数字签名点击查看解决方案












8.3 运行出厂默认程序

1.RGB七彩变换:上电默认运行。板载RGB灯进行七彩变换,可验证RGB灯是否正常显示。

2.NB-IoT信号测试:RGB指示灯白色。自动尝试连接NB-IoT网络,并串口打印各类联网信息和当前NB-IoT信号强度(单位:dBm),同时通过RGB灯的闪烁频率来表示三种信号强度。


3.NB-IoT AT指令串口透传:RGB指示灯紫色。用户可使用Arduino IDE自带的串口监视器或第三方的串口助手向开发板输入AT指令,该指令将会通过ESP32透传至NB-IoT通信模组BC20,可使用注释中提供的常用AT指令对BC20进行测试。完整的AT指令可参考该文档最后的附件BC20软硬件开发资料包中的相关用户手册。


4.WiFi信号扫描:RGB指示灯黄色。每隔5s扫描并打印当前环境的WiFi信号及其相应的信号强度。


5.WiFi连接:RGB指示灯绿色。用户可根据提示,在串口监视器,输入WiFi SSID(WiFi名称)和密码以连接相应的WiFi信号,若SSID或密码任一输入错误,连接会超时,程序会要求重新输入SSID或密码。若WiFi成功连接,ESP32会利用网络服务器校准RTC,并每秒打印一次日期和时间。


6.蓝牙BLE透传:RGB指示灯蓝色。程序广播TinkerNode NB-IoT(0xXXXX)蓝牙信号,其中XXXX为随机的十六进制数,用于与其它蓝牙信号作区别。用户可使用第三方的手机APPBLE蓝牙串口助手连上该蓝牙信号,即可与开发板通过蓝牙进行串口透传通信。当开发板收到字符“1”时,指示灯L点亮;收到字符“0”时,指示灯L熄灭,接收到的其它字符将会打印到串口监控器上。


注意

  • 使用手机系统自带的蓝牙信号搜索功能无法搜出蓝牙信号。

7.GNSS定位:RGB指示灯青色。程序通过串口打印所有GNSS定位和卫星信息,如当地时间,经纬度,所使用的卫星等信息。首次获取GNSS定位信号通常需要30s以上,请耐心等待。

注意

  • GPS/BeiDou陶瓷有源天线的陶瓷面应该面向天空,尽可能在室外使用,否则无法获取有效的定位信息。

PDOP,HDOP和VDOP三者有如下关系: HDOP^2+VDOP^2=PDOP^2


注意

  • 每次按SET切换到下一个功能,该功能都默认处于关闭状态(无论之前是否打开过),需要再长按SET才能开启该功能。

  • 如果需要重新烧录该程序,可以在菜单栏的文件->示例->DFRobot_NBIOT->Default_Run中找到该程序。

9. 详细说明

9.1 电源管理

开发板支持四种供电方式:太阳能(SOLAR)、锂电池(BAT)、USB、6-24V外部供电(VIN),提供安全、高效、灵活的全方位电源管理(详情可参考系统原理框图),具有以下特性:

注意

  • 受限于低功耗设计,只有当使用到外部供电或USB为系统供电时,标有5V的过孔焊盘输出5V,RGB指示灯可用。否则仅使用太阳能或电池供电时,标有5V的过孔焊盘输出约为4.2V或电池电压,RGB指示灯不可用

  • 只能使用标称电压为5V的太阳能板接入太阳接线端,更大额定电压的太阳能板极有可能永久损坏充电芯片。

  • 当使用太阳能板为系统供电时,强烈建议同时连上锂电池。因为太阳能受天气与光照不稳定影响,供电的也会变得不稳定,极有可能导致系统无法正常启动或稳定工作。使用锂电池供电作为缓冲,可解决这个问题。

9.2 天线

开发板的WiFi和Bluetooth通信使用PCB板载天线,而NB-IoT通信和GNSS定位功能需要外接天线。用户可使用产品包装中所提供的天线,也可额外购买兼容的外接天线以进一步增强收发信号的能力或缩小天线占用的空间。

NB-IoT天线

频段 中心频率 上行频率 下行频率 运营商
B5 850 MHz 824 MHz ~ 849 MHz 869 MHz ~ 894 MHz 中国电信
B8 900MHz 880 MHz ~ 915 MHz 925 MHz ~ 960 MHz 中国移动、中国联通

GNSS天线

定位系统 接收频段
GPS L1 C/A 1575.42 MHz
BeiDou(北斗) B1 C/A 1561.098 MHz

GNSS通信频段

9.3 SIM卡

NB-IoT通信需要专用的NB-IoT物联网SIM卡,如手机SIM卡,4G物联网卡等其它类型的SIM卡无法代替。目前产品包装内包含有一张中国联通NB-IoT物联网专用SIM卡,包含一份年度基础套餐,插入NB-IoT开发板或通信模组内即可使用,若流量满足不了使用需求,可通过充值月度流量包增加当月流量。后续将会推出更多运营商的NB-IoT物联网专用SIM卡供用户选择。

联通NB-IoT SIM卡资费情况如下表:

套餐 流量 有效期 资费 备注
年度基础套餐(续费,必需) 30 MB/月×12=360MB 360天 12元 1.有效期自激活之日(首次成功通信)起开始计算,共360天。
2.每30天为一个月度结算周期,每月流量不累计到下个月,超量停机,直到下个月度结算周期或充值月度流量包恢复。
3.360天到期后自动停机,续费年度基础套餐自动恢复开通。
4.有效期结束前续费年度基础套餐,下一年可不停机无缝继续使用。
月度流量包(可选) 30M/个 30天 3元 1.有效期自充值当天开始计算
2.随充随用,可无限叠加。
3.仅在年度基础套餐有效期内使用。
NB-IoT物联网专用SIM卡(补卡) 30 MB/月×12=360MB 360天 15元 1.需要联系客服核实信息方可购买,不单独销售。

注意

  • 根据国家工业和信息化部等六部门要求,为有效防范和打击通讯信息诈骗,所有NB-IoT物联网专用SIM卡均具有机卡绑定功能,不可取消
  • SIM卡插入设备,首次上电(与基站)成功通信即视为激活且与通信模组绑定(机卡绑定),开始年度计费周期(360天)
  • 2G/3G/4G手机SIM卡或大流量物联网卡无法代替用于NB-IoT设备。
  • 物联网SIM卡不能用于手机、平板、2G/3G/4G模组等非NB-IoT设备,否则会导致SIM卡停机
  • 已机卡绑定的SIM卡若被插入其它设备内进行通信会导致SIM卡停机
  • 物联网SIM卡仅能数据传输,无语音通信和短信功能

流量查询与充值

注意

  • 微信公众号DF物联网目前处于建设和测试状态,部分页面可能不完善,但不影响SIM卡的流量查询与充值功能。

9.4 通信接口

开发板通过左右两侧的10P过孔焊盘引出外部通信和供电的接口,便于用户的项目制作与原型开发,各管脚功能详见接口说明图


通用IO

#define PIN_IO 2        //使用物理管脚号
//#define PIN_IO D4     //使用Arduino兼容的管脚号

void setup() {
  pinMode(PIN_IO, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}

注意

  • 除D0~D4外的IO在作为通用IO调用时,只能使用物理管脚号进行调用。
  • A0(IO36)和A1(IO39)作为通用IO调用时,仅能作为输入,不能输出。

模拟输入

//使用A0或A1调用模拟输入管脚
#define ANALOG_IN_PIN0    A0
#define ANALOG_IN_PIN1    A1
#define VREF              3.3     //参考电压为3.3V
#define ADC_RESOLUTION    4096    //与Arduino UNO10位ADC不同,ESP32主控ADC为12位

uint16_t analogVal0, analogVal1;
float  volt0, volt1;

void setup() {
  Serial.begin(115200);
}

void loop() {
  //使用anlogRead函数读取模拟管脚
  analogVal0 = analogRead(ANALOG_IN_PIN0);
  analogVal1 = analogRead(ANALOG_IN_PIN1);

  volt0 = VREF / ADC_RESOLUTION * analogVal0;
  volt1 = VREF / ADC_RESOLUTION * analogVal1;

  Serial.print("A0 ADC Val:");
  Serial.println(analogVal0);
  Serial.print("A0 Voltage:");
  Serial.print(volt0);
  Serial.println(" V");

  Serial.print("A1 ADC Val:");
  Serial.println(analogVal1);
  Serial.print("A1 Voltage:");
  Serial.print(volt1);
  Serial.println(" V");

  Serial.println();

  delay(1000);
}

数字通信接口

void setup() {
  //与PC通信通过USB转UART,使用Serial进行调用
  Serial.begin(115200);
  //开发板上标有TXD和RXD的串口UART使用Serial2进行调用
  Serial2.begin(115200);
}

void loop() {
  if (Serial.available()) {
    Serial2.write(Serial.read());
  }
  if (Serial2.available()) {
    Serial.write(Serial2.read());
  }
}

9.5 微型U盘与Flash

开发板利用部分板载Flash空间作为U盘,在连接PC时将会弹出一个约8MB的微型U盘(首次使用需要格式化,详见快速使用指南一节的安装开发板驱动,用户可以与普通U盘一样对该U盘进行文件操作,便于与开发板的数据交换。这种方式可将开发板记录的数据方便地通过CSV文件导出到PC,并制作数据图表,也可以方便地将PC上的数据导入U盘,供开发板利用。


注意

  • 当使用USB与PC连接时,请等待U盘正常弹出后,再对开发板烧录程序,也只有U盘弹出后,程序才会开始正常运行。

  • 关于Flash的容量:16MB Flash这里指16MB×8bit,即16MB=16384KB=16777216B,与硬盘的计算方式1MB=1000KB,1KB=1000B不同。其中8MB用于U盘功能,剩下约8MB用于程序代码。由于烧录机制,8MB程序代码空间会被分成两部分,均约为3.9MB,烧录时,会先在其中一部分烧录,完成后再复制到另外一部分运行,因此实际程序可用空间约为3.9MB

  • 传输速度:由于读写微型U盘的文件经过USB转UART芯片的转换,同时受NOR FLASH的读写速率限制,传输速度较慢。目前实测写入速度约为3KB/s,读取速度约为30KB/s

  • U盘功能(U盘+USB转串口)通过CH552固件实现,但仅支持Win7和Win10,且需要安装专用驱动。无U盘功能的CH552固件(仅USB转串口)具有更好的兼容性,无需安装专用驱动,Windows、Linux、MacOS三大平台无驱使用。用户可根据应用场景和开发的便利性自行更新该固件,更新方法见固件烧录部分的内容。

10. 固件烧录

开发板使用CH552用于USB转UART和U盘功能,为了不断优化使用体验和新增功能,将会不定期推出新版固件,用户可按照下述方法更新开发板固件:

  1. 点击8位CH55X系列标签
  2. 芯片型号选择CH552
  3. 点击下载CH552固件,解压缩压缩包。用户程序文件选择解压缩出来的以.hex为后缀的固件。下载配置如下图保持默认。
  4. 在确保开发板完全断电的状态下,如图示短接开发板中的两个测试点,然后使用USB线连接开发板和PC上电,程序会自动检测到CH552(检测到了以后,可断开测试点的短接),USB设备列表会弹出类似如下图字样,左下角显示“Linked Device is:CH552”。
  5. 点击“下载”开始烧录固件。
  6. 下载记录会显示下载进度,一般会在2s内完成固件烧录。


11. 应用样例

11.1 使用DFRobot Easy-IoT测试云端通信

通过上面的样例可完成NB-IoT或WiFi的信号测试,确认附近有NB-IoT或WiFi信号后,接下来可测试设备与云端的通信情况。这里以DFRobot出品的Easy-IoT轻量级物联网云平台为样例进行介绍。该平台极大地简化了用户设备上云所需要的大量配置,让创客与入门开发者10分钟内实现设备与云端的连接,尤其适用于物联网通信的快速测试和简单物联网项目的搭建。下面简述测试过程


设备发送消息到云端(NB-IoT版)

/*配置设备的认证信息*/
String Iot_id = "HJZv1ZFRSQ";                        //填入Iot_id
String Client_ID  = "12345";                        //任意数值,用于区分不同设备
String Iot_pwd    = "ByfP1-YABX";                    //填入Iot_pwd

/*配置IoT云平台的IP地址和端口号*/
String EasyIot_SERVER = "182.254.130.180";
uint16_t PORT = 1883;

/*配置要推送(Publish)或订阅(Subscribe)的topic*/
const char * pubTopic = "JoUOAg_WR";                //填入Topic
#include "DFRobot_BC20.h"
#include "DFRobot_Iot.h"

/*配置设备的认证信息*/
String Iot_id = "HJZv1ZFRSQ";                        //填入Iot_id
String Client_ID  = "12345";                        //任意数值,用于区分不同设备
String Iot_pwd    = "ByfP1-YABX";                    //填入Iot_pwd

/*配置IoT云平台的IP地址和端口号*/
String EasyIot_SERVER = "182.254.130.180";
uint16_t PORT = 1883;

/*配置要推送(Publish)或订阅(Subscribe)的topic*/
const char * pubTopic = "JoUOAg_WR";                //填入Topic

DFRobot_BC20 myBC20;
DFRobot_Iot myDevice;


/*连接到IoT云服务器*/
void ConnectCloud(){
    while(!myBC20.connected()){
        Serial.print("Attempting MQTT connection...");
        if(myBC20.connect(myDevice._clientId, myDevice._username, myDevice._password)){
            Serial.println("Connect Server OK");
        }else{
            myBC20.getQMTCONN();
        }
    }
}

void setup(){
    /*初始化串口,波特率115200*/
    Serial.begin(115200);

    /*初始化NB-IoT模组BC20*/
    Serial.print("Starting the BC20.Please wait. . . ");
    while(!myBC20.powerOn()){
        delay(1000);
        Serial.print(".");
    }
    Serial.println("BC20 started successfully !");

    /*检查SIM卡是否插入*/
    while(!myBC20.checkNBCard()){
        Serial.println("Please insert the NB card !");
        delay(1000);
    }

     /*检查是否已连入网络(NB-IoT基站)*/
    Serial.println("Waitting for access ...");
    while(myBC20.getGATT() == 0){
        Serial.print(".");
        delay(1000);
    }

    /*配置需要连接的IoT云服务器(Easy-IoT)*/
    myDevice.init(EasyIot_SERVER, Iot_id, Client_ID, Iot_pwd);
    myBC20.setServer(myDevice._mqttServer,PORT);

    /*连接到Easy-IoT*/
    ConnectCloud();

}

void loop(){
  /*IoT云服务器断线重连*/
  if (!myBC20.connected()) {
    ConnectCloud();
  }
  myBC20.loop();
  myBC20.publish(pubTopic, "Hello");
  delay(5000);
}

结果




云端发送消息到设备(NB-IoT版)

/*配置设备的认证信息*/
String Iot_id = "HJZv1ZFRSQ";                        //填入Iot_id
String Client_ID  = "12345";                        //任意数值,用于区分不同设备
String Iot_pwd    = "ByfP1-YABX";                    //填入Iot_pwd

/*配置IoT云平台的IP地址和端口号*/
String EasyIot_SERVER = "182.254.130.180";
uint16_t PORT = 1883;

/*配置要推送(Publish)或订阅(Subscribe)的topic*/
const char * pubTopic = "JoUOAg_WR";                //填入Topic
#include "DFRobot_BC20.h"
#include "DFRobot_Iot.h"

/*配置设备的认证信息*/
String Iot_id = "HJZv1ZFRSQ";            //填入Iot_id
String Client_ID  = "12345";            //任意数值,用于区分不同设备
String Iot_pwd    = "ByfP1-YABX";         //填入Iot_pwd

/*配置IoT云平台的IP地址和端口号*/
String EasyIot_SERVER = "182.254.130.180";
uint16_t PORT = 1883;

/*配置要推送(Publish)或订阅(Subscribe)的topic*/
const char * subTopic = "JoUOAg_WR";        //填入Topic

DFRobot_BC20 myBC20;
DFRobot_Iot myDevice;

/*回调函数。当从订阅的topic收到消息时,该函数被调用。*/
void callback(char * topic, byte * payload, unsigned int len){
  Serial.print("Recevice [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < len; i++){
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

/*连接到IoT云服务器*/
void ConnectCloud(){
    while(!myBC20.connected()){
        Serial.print("Attempting MQTT connection...");
        if(myBC20.connect(myDevice._clientId, myDevice._username, myDevice._password)){
            Serial.println("Connect Server OK");
            myBC20.SubTopic(0,1,subTopic,0);
        }else{
            myBC20.getQMTCONN();
        }
    }
}

void setup(){
    /*初始化串口,波特率115200*/
    Serial.begin(115200);

    /*初始化NB-IoT模组BC20*/
    Serial.print("Starting the BC20.Please wait. . . ");
    while(!myBC20.powerOn()){
        delay(1000);
        Serial.print(".");
    }
    Serial.println("BC20 started successfully !");

    /*检查SIM卡是否插入*/
    while(!myBC20.checkNBCard()){
        Serial.println("Please insert the NB card !");
        delay(1000);
    }

    /*检查是否已连入网络(NB-IoT基站)*/
    Serial.println("Waitting for access ...");
    while(myBC20.getGATT() == 0){
        Serial.print(".");
        delay(1000);
    }

    /*配置需要连接的IoT云服务器(Easy-IoT)*/
    myDevice.init(EasyIot_SERVER, Iot_id, Client_ID, Iot_pwd);
    myBC20.setServer(myDevice._mqttServer,PORT);

    /*配置回调函数*/
    myBC20.setCallback(callback);

    /*连接到Easy-IoT*/
     ConnectCloud();
}

void loop(){
  /*IoT云服务器断线重连*/
  if (!myBC20.connected()) {
    ConnectCloud();
  }
  myBC20.loop();
}

结果





至此,通过上述两个样例,完成了开发板(设备端)与Easy-IoT云平台(云端)的NB-IoT双向通信测试。

设备发送消息到云端(WiFi版)

/*配置WIFI名和密码*/
const char * WIFI_SSID     = "DFRobot-guest";        //填入WiFi SSID
const char * WIFI_PASSWORD = "dfrobot@2017";        //填入WiFi 密码

/*配置设备的认证信息*/
String Iot_id = "HJZv1ZFRSQ";                        //填入Iot_id
String Client_ID  = "12345";                        //任意数值,用于区分不同设备
String Iot_pwd    = "ByfP1-YABX";                    //填入Iot_pwd

/*配置IoT云平台的IP地址和端口号*/
String EasyIot_SERVER = "182.254.130.180";
uint16_t PORT = 1883;

/*配置要推送(Publish)或订阅(Subscribe)的topic*/
const char * pubTopic = "JoUOAg_WR";                //填入Topic
#include <WiFi.h>
#include <PubSubClient.h>
#include "DFRobot_Iot.h"

/*配置WIFI名和密码*/
const char * WIFI_SSID     = "DFRobot-guest";
const char * WIFI_PASSWORD = "dfrobot@2017";

/*配置设备的认证信息*/
String Iot_id = "HJZv1ZFRSQ";
String Client_ID  = "12345";
String Iot_pwd    = "ByfP1-YABX";

/*配置IoT云平台的IP地址和端口号*/
String EasyIot_SERVER = "182.254.130.180";
uint16_t PORT = 1883;

/*配置要推送(Publish)或订阅(Subscribe)的topic*/
const char * pubTopic = "JoUOAg_WR";

DFRobot_Iot myEasyIoT;
WiFiClient espClient;
PubSubClient client(espClient);

/*连接WiFi*/
void connectWiFi() {
  WiFi.disconnect();
  delay(100);
  Serial.print("Connecting to ");
  Serial.println(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.print("IP Adderss: ");
  Serial.println(WiFi.localIP());
}

/*连接到IoT云服务器*/
void ConnectCloud() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect(myEasyIoT._clientId, myEasyIoT._username, myEasyIoT._password)) {
      Serial.println("Connect Server OK");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" Try again in 5 seconds");
      delay(5000);
    }
  }
}


void setup() {
  /*初始化串口,波特率115200*/
  Serial.begin(115200);

  /*连接WIFI*/
  connectWiFi();

  /*配置需要连接的IoT云服务器(Easy-IoT)*/
  myEasyIoT.init(EasyIot_SERVER, Iot_id, Client_ID, Iot_pwd);
  client.setServer(myEasyIoT._mqttServer, PORT);

  /*连接到Easy-IoT*/
  ConnectCloud();
}

void loop() {
  /*IoT云服务器断线重连*/
  if (!client.connected()) {
    ConnectCloud();
  }
  client.loop();

  /*每隔一段时间向Easy-IoT*/
  Serial.println("Sending message to cloud...");
  client.publish(pubTopic, "Hello");
  Serial.println("Message is sent.");
  delay(10000);
}

结果




云端发送消息到设备(WiFi版)

/*配置WIFI名和密码*/
const char * WIFI_SSID     = "DFRobot-guest";        //填入WiFi SSID
const char * WIFI_PASSWORD = "dfrobot@2017";        //填入WiFi 密码

/*配置设备的认证信息*/
String Iot_id = "HJZv1ZFRSQ";                        //填入Iot_id
String Client_ID  = "12345";                        //任意数值,用于区分不同设备
String Iot_pwd    = "ByfP1-YABX";                    //填入Iot_pwd

/*配置IoT云平台的IP地址和端口号*/
String EasyIot_SERVER = "182.254.130.180";
uint16_t PORT = 1883;

/*配置要推送(Publish)或订阅(Subscribe)的topic*/
const char * pubTopic = "JoUOAg_WR";                //填入Topic
#include <WiFi.h>
#include <PubSubClient.h>
#include "DFRobot_Iot.h"

/*配置WIFI名和密码*/
const char * WIFI_SSID     = "DFRobot-guest";
const char * WIFI_PASSWORD = "dfrobot@2017";

/*配置设备的认证信息*/
String Iot_id = "HJZv1ZFRSQ";
String Client_ID  = "12345";
String Iot_pwd    = "ByfP1-YABX";

/*配置IoT云平台的IP地址和端口号*/
String EasyIot_SERVER = "182.254.130.180";
uint16_t PORT = 1883;

/*配置要推送(Publish)或订阅(Subscribe)的topic*/
const char * subTopic = "JoUOAg_WR";

DFRobot_Iot myEasyIoT;
WiFiClient espClient;
PubSubClient client(espClient);

/*连接WiFi*/
void connectWiFi() {
  WiFi.disconnect();
  delay(100);
  Serial.print("Connecting to ");
  Serial.println(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.print("IP Adderss: ");
  Serial.println(WiFi.localIP());
}

/*连接到IoT云服务器*/
void ConnectCloud() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect(myEasyIoT._clientId, myEasyIoT._username, myEasyIoT._password)) {
      Serial.println("Connect Server OK");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" Try again in 5 seconds");
      delay(5000);
    }
  }
}

/*回调函数。当从订阅的topic收到消息时,该函数被调用。*/
void callback(char * topic, uint8_t * payload, unsigned int len) {

  /*显示收到的topic名称和消息内容*/
  Serial.print("Recevice [Topic:");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < len; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void setup() {
  /*初始化串口,波特率115200*/
  Serial.begin(115200);

  /*连接WIFI*/
  connectWiFi();

  /*配置需要连接的IoT云服务器(Easy-IoT)*/
  myEasyIoT.init(EasyIot_SERVER, Iot_id, Client_ID, Iot_pwd);
  client.setServer(myEasyIoT._mqttServer, PORT);

  /*订阅(Subscribe)指定topic*/
  client.subscribe(subTopic);
  Serial.print("Topic:");
  Serial.print(subTopic);
  Serial.println(" subscribed!");

  /*配置回调函数*/
  client.setCallback(callback);

  /*连接到Easy-IoT*/
  ConnectCloud();
}

void loop() {
  /*IoT云服务器断线重连*/
  if (!client.connected()) {
    ConnectCloud();
  }
  client.loop();
}

结果





至此,通过上述两个样例,完成了开发板(设备端)与Easy-IoT云平台(云端)的WiFi双向通信测试。

12. 固件更新记录

12.1 Arduino SDK板卡支持包

  1. 解决了WiFi连接MQTT超时问题。(Attempt MQTT connection,rc=-1)。
  1. 解决因CH552波特率误差导致的U盘通信过程中的丢包、重传问题,最终导致无法弹出U盘的问题。
  2. DataLogger.ino增加按SET按钮控制是否保存进flash的功能,以提醒用户在掉电前可以先暂停将数据保存进flash中。
  1. 增加了PubSubClient、ArduinoJson、OneWire作为内置库。
  2. 修改了ProductKey、DeviceName、DeviceSecret等参数,使用户可以双击选中。
  3. 在easy-IoT相关样例的头部注释中添加Easy-IoT相关链接
  4. 移除了开发板选项里的TinkerNode NB-IoT(GL)选项。

12.2 CH552固件

12.2.1 CH552固件(有U盘版本)

1.仅支持Win7和Win10系统,需要安装专用驱动程序。

12.2.1 CH552固件(无U盘版本,CH340固件)

  1. 修复MacOS兼容性问题。
  1. 调整波特率,修复串口打印乱码问题。
  1. 无需安装专用驱动,Windows、Linux、MacOS三大平台无驱使用。
  2. 无U盘功能。
  3. 固件更新后,在设备管理器中可看到类似如下的串口设备

13. 常见问题

Q1. 是否可以直接通过过孔焊盘的5V或3V3对开版板进行供电?


A1.

Q2. 可以边冲边放吗?(太阳能、外部供电、USB)
A2. 可以。

Q3. CH341驱动安装后,设备管理器中提示Windows 无法验证此设备所需的驱动程序的数字签名
A3.目前仅带U盘固件可能出现该问题。驱动经过数字签章,对于大部分Windows系统没有安装问题,但仍有小部分会遇到数字签名的问题,可通过禁用Windows系统的数字签名认证解决,点击查看解决方案

Q4. 使用适配器通过USB口进行外部供电时,TinkerNode不工作。
A4. 目前仅带U盘固件会出现该问题。由于部分适配器内部会借助D+、D-区分设备类型,从而导致TinkerNode会卡在等待U盘加载的步骤,无法正常工作。推荐需要外部供电时,使用VIN接线柱,或使用只能供电(不包含“D+D-”数据线)的USB线。

更多问题及有趣的应用,可以 访问论坛 进行查阅或发帖。

14. 更多

DFshopping_car1.png DFRobot商城购买链接