Arduino 使用 BC26/BC35 连接至阿里云平台

一、前言

本人最近参加的项目需要使用到NB-IoT模块,在网上寻找了一圈之后,发现Arduino常用的NB-IoT模块如下:
请添加图片描述

请添加图片描述

这两个模块均来自DFRobot,还有一些独立的模块。网上有关于这些通信模块的资料,大多数都是跟Arduino UNO或者STM32做的调试,没有见过有人使用Arduino Mega 2560与这些模块连接。

因为本次的项目需要使用到非常多的针脚,UNO的针脚数无法满足需求,而Mac电脑没办法对32芯片进行烧写,故只能选择Mega2560。

这就有了一个新的问题,模块的兼容性能否满足需求?

二、开始调试前的准备工作

1.通信模块的选择与软件版本

本次选择的模块是BC260YBC35
请添加图片描述

请添加图片描述

软件版本使用的是

请添加图片描述

2.固件的烧录

因为原厂的固件是不支持MQTT协议的,这块需要到手后专门烧录支持MQTT的AT固件,具体的烧录办法需要向商家询问,由于固件和参考资料属于官方的限制性文档,故在这里不再公布。

只是烧录时有几个要点需要注意
1)烧录软件尽量放在系统的根目录,且路径上不要出现中文或者空格,因为会增加烧录失败的可能性;
2)要烧录的固件的文件层次不要太深,尽量放在系统根目录下,且路径上不要出现中文或者空格,同样也会增加烧录失败的风险;、
3)使用的USB转TTL下载器一定要在电脑上装驱动,例如我的USB TTL下载器是CH340C的芯片,那么我就需要在电脑上安装对应芯片的驱动程序;

PS:本人烧录固件的前几次都是因为这样的原因而失败的,还有中间需要手动复位,就是说RESET针脚需要手动短暂接地。

3.调试前需要一个干净的桌面

这一点很重要很重要很重要!!!!!!!!!!!!!!!!!!!!

本人在调试的时候在这方面刚刚吃过亏,一定要有一个整洁的桌面。

因为一个非常离谱的错误导致一下午都耗在调试上了。

起因是这样的,在调试程序的时候,突然就跑通了一次,然后就再没跑通了,无论怎样改程序、改接线,都没用,单独测2560和通信模块都没问题,合在了一起就不行,并且在这过程中还排除了库文件不兼容的问题。那么问题就出在了模块与2560的接线上了,因为我测试的时候,因为杜邦线太长了,就团成了一团,并且线的周围有一个扬声器和一团高频信号线和一团交流电线。直到我清理了一下桌面,顺直了杜邦线之后,突然程序就再没报过错了。说明了这些环境对信号的传输造成了影响,估计是信号串扰吧。

请添加图片描述

图片中可以清晰的看到有一根HDMI线、一根雷电3的线、两根交流电供电线、若干USB数据线,左边和右边还有扬声器。长出来的杜邦线就被我团成了一团放在了这堆线上面(类似的场景,我没拍,就拿这张图还原个情景再现)然后调试就出Bug了。

所以调试前一定要有一个干净整洁的桌面!!!!!

三、开始调试硬件

直接上程序,这个程序是店家提供的,我们来做个逐步的分析

#include <Arduino.h>
#include <SoftwareSerial.h>
#include <ArduinoJson.h>

DynamicJsonDocument json(200);

SoftwareSerial mySerial(50,52) ;//RX  TX

void CommandtoNBIOT (String cmd, char *res)
{
    
    
  while (1)
  {
    
    
    mySerial.println(cmd);
    delay(300);
    while (mySerial.available() > 0)
    {
    
    
      if (mySerial.find(res))
      {
    
    
        digitalWrite(7, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(100);              // wait for a second
        digitalWrite(7, LOW);    // turn the LED off by making the voltage LOW
        delay(100);
        Serial.println(res);
        return;
      }
      else
      {
    
    
        Serial.print(cmd);
        Serial.println("  Return ERROR!");
      }
    }
    delay(200);
  }
}

void MQTT_PubData(void)//发布数据到平台
{
    
     //"/sys/a1qmGxDM8cd/mzhtest001/thing/event/property/post","{"id":"26","version":"1.0","params":{"CurrentTemperature":{"value":23},"RelativeHumidity":{"value":58}},"method":"thing.event.property.post"}"
  char sendjson[] = "{\"id\":\"26\",\"version\":\"1.0\",\"sys\":{\"ack\":0},\"params\":{\"CurrentTemperature\":{\"value\":50},\"CurrentHumidity\":{\"value\":10}},\"method\":\"thing.event.property.post\"}";
  char T_json[200];
  sprintf(T_json, sendjson); //,humidata
  mySerial.println("AT+QMTPUB=0,0,0,0,\"/sys/gbruRYswLWR/WEATHER/thing/event/property/post\""); //send message,主题更改
  delay(100);
  mySerial.println(T_json);
  mySerial.write(0x1A);
  delay(300);
  // wait for a second
  while (mySerial.available() > 0)
  {
    
    
  //  char inByte = mySerial.read();
  //  Serial.print(inByte);
  if (mySerial.find("+QMTPUB: 0,0,0"))
   {
    
    
   Serial.println("+QMTPUB: 0,0,0");
   break;
  }
  }
}



void BC260Y_init(void)//初始化MQTT连接
{
    
    
  Serial.println("1");
  // prints title with ending line break
  CommandtoNBIOT("AT", "OK");
  mySerial.println("ATE0&W");//关闭回显
  delay(300);
  CommandtoNBIOT("AT+CPIN?", "+CPIN: READY"); //返+CPIN:READY,表明识别到卡了
  Serial.println("2");
  CommandtoNBIOT("AT+CGATT?", "+CGATT: 1"); //返+CGACT: 1,就能正常工作了
  Serial.println("3");
  mySerial.println("AT+QMTCLOSE=0");//关闭上一次socekt连接
  delay(300);
  mySerial.println("at+qmtcfg=\"aliauth\",0, \"gbruRYswLWR\",\"WEATHER\",\"d9661e128b5590cf5b7f880d991c7f7e\"");//配置三元素
  delay(300);
  CommandtoNBIOT("AT+QMTOPEN=0,\"iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883", "+QMTOPEN: 0,0"); //建立服务器的IP和端口连接
  delay(300);
  CommandtoNBIOT("AT+QMTCONN=0,\"WEATHER\"", "+QMTCONN: 0,0,0"); //建立服务器的IP和端口连接
  delay(300);
}


void setup() {
    
    
  // put your setup code here, to run once:
  // initialize digital pin 13 as an output.
  pinMode(7, OUTPUT);
  Serial.begin(9600); //
  mySerial.begin(9600);
  delay(2000);
  
  BC260Y_init();
}

void loop() {
    
    
  
  // put your main code here, to run repeatedly:
  MQTT_PubData();//发布数据
  Serial.println("Data_Pub_Success");
  delay(4000);
}

首先来说第一部分,定一个软串口

SoftwareSerial mySerial(50,52) ;//RX  TX

我个人更建议使用如下的方式

SoftwareSerial mySerial = SoftwareSerial(50,52) ;//RX  TX

这里定义了50号数字口是RX,52号数字口是TX

接线的方法如下:

BC260/BC35                              Arduino

   TX0         ------------------>        D50 
   
   RX0         ------------------>        D52
   
   GND         ------------------>        GND 
   
   VIN         ------------------>        5 V 
   

接着让软串口在9600波特率上运行着

void setup() {
    
    
	pinMode(7, OUTPUT);		//我在7针脚上接了一个灯
	Serial.begin(9600); 	//让串口在9600波特率上运行
	mySerial.begin(9600);	//让软串口在9600波特率上运行
	delay(2000);
	BC260Y_init();			//初始化BC260/BC35
}

这段程序展示了如何将AT指令发送到通信模块上

void CommandtoNBIOT (String cmd, char *res)
{
    
    
	while (1)
	{
    
    
		mySerial.println(cmd);
		delay(300);
		while (mySerial.available() > 0)
		{
    
    
			if (mySerial.find(res))
			{
    
    
				digitalWrite(7, HIGH);   
			    delay(100);              
			    digitalWrite(7, LOW);    
			    delay(100);
			    Serial.println(res);
			    return;
			}
			else
			{
    
    
			    Serial.print(cmd);
			    Serial.println("  Return ERROR!");
			}
		}
		delay(200);
	}
}

使用mySerial.println(cmd)发送AT指令。切记,必须使用println来发送,若没有换行符,通信模块不执行该指令。
等待一段时间后用find在通信模块串口返回的值中寻找有没有我要的返回值。

例如,我输入AT后应该返回OK,那么里面的 cmd 对应 AT,res 对应 OK。

若没有得到想要的返回值,该模块会一直循环发送指令。

初始部分代码如下:

void BC260Y_init(void)//初始化MQTT连接
{
    
    
	Serial.println("1");
	// prints title with ending line break
	CommandtoNBIOT("AT", "OK");
	mySerial.println("ATE0&W");//关闭回显
	delay(300);
	CommandtoNBIOT("AT+CPIN?", "+CPIN: READY"); //返+CPIN:READY,表明识别到卡了
	Serial.println("2");
	CommandtoNBIOT("AT+CGATT?", "+CGATT: 1"); //返+CGACT: 1,就能正常工作了
	Serial.println("3");
	mySerial.println("AT+QMTCLOSE=0");//关闭上一次socekt连接
	delay(300);
	mySerial.println("at+qmtcfg=\"aliauth\",0, \"${ProductKey}\",\"${deviceName}\",\"${DeviceSecret}\"");//配置三元素
	delay(300);
	CommandtoNBIOT("AT+QMTOPEN=0,\"iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883", "+QMTOPEN: 0,0"); //建立服务器的IP和端口连接
	delay(300);
	CommandtoNBIOT("AT+QMTCONN=0,\"${deviceName}\"", "+QMTCONN: 0,0,0"); //建立服务器的IP和端口连接
	delay(300);
}

数据发送部分的代码参考

void MQTT_PubData(void)//发布数据到平台
{
    
     
	char sendjson[] = "{\"id\":\"26\",\"version\":\"1.0\",\"sys\":{\"ack\":0},\"params\":{\"CurrentTemperature\":{\"value\":50},\"CurrentHumidity\":{\"value\":10}},\"method\":\"thing.event.property.post\"}";
    char T_json[200];
    sprintf(T_json, sendjson); //,humidata
    mySerial.println("AT+QMTPUB=0,0,0,0,\"/sys/${ProductKey}/${deviceName}/thing/event/property/post\""); //send message,主题更改
    //具体的请参考阿里云的topic相关文档
    delay(100);
    mySerial.println(T_json);
    mySerial.write(0x1A);
    delay(300);
    // wait for a second
    while (mySerial.available() > 0)
    {
    
    
    //  char inByte = mySerial.read();
    //  Serial.print(inByte);
        if (mySerial.find("+QMTPUB: 0,0,0"))
         {
    
    
             Serial.println("+QMTPUB: 0,0,0");
             break;
         }
    }
}

那么如何快速判断模块是否能够使用呢?

#include <SoftwareSerial.h>

SoftwareSerial bcserial = SoftwareSerial(50,52); //rx tx

void setup() {
    
    
  // put your setup code here, to run once:
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  bcserial.begin(9600);
  delay(100);
  while (1)
  {
    
    
      Serial.print("AT\r\n");
      bcserial.println("AT");
      delay(300);
      Serial.println(bcserial.read());
      while (bcserial.available() > 0)
      {
    
    
          if (bcserial.find("OK"))
          {
    
    
              digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
              delay(100);              // wait for a second
              digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
              delay(100);
              Serial.println('OK');
              return;
           }
           else
           {
    
    
              Serial.print("AT");
              Serial.println("  Return ERROR!");
           }
        }
        delay(200);
    }
  
}

void loop() {
    
    
    // put your main code here, to run repeatedly:
    Serial.println("OKKKKKK");
}

如果返回的像是这样的信息,就说明该模块与Arduino之间连接良好
请添加图片描述

四、阿里云平台的设置

首先得要开通阿里云的物联网平台,测试的话就使用公共实例即可

1.添加产品并添加功能

在左边的设备管理里面的产品,创建产品:

请添加图片描述
产品名称自定

请添加图片描述
点击 查看 之后选择功能定义然后点击添加自定义功能(我这个是已经添加过并发布的了请添加图片描述

请添加图片描述
请添加图片描述
然后点击发布上线即可。

2.添加设备

请添加图片描述
点击设备管理,然后点击添加设备,出现如下的画面,设备名字自己定义即可
请添加图片描述
然后将设备的三要素填写的Arduino的程序中的对应位置上,然后烧录进Arduino,等待设备的激活连接。
请添加图片描述
请添加图片描述

激活成功之后在物理型数据里就能看到刚刚添加的功能的数据了。

五、小结

第一次折腾NB-IoT,踩了好些的坑,更多的坑则是让我的搭档踩了(我俩都第一次接触这个)。

把这个发出来仅仅是记录了一下能成功运行的整个流程。

Arduino的程序在使用起来还是过于的麻烦,后续有计划打算封装一个兼容BC260Y和BC35 NB-IoT模块的库,使用起来能相对的方便不少。不过我也得学不少的东西。

猜你喜欢

转载自blog.csdn.net/qq_17790209/article/details/119769792