打印

【21ic第二届设计大赛】+局域物联网

[复制链接]
1831|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 yongruru 于 2018-8-21 13:35 编辑

  根据网络容量大小本文提出两种网络方案。第一种针对小型网络10个节点以内,使用MESH网络,主机轮询从机通信。第二种针对10个节点以上网络,采用LoRaWAN网络。下面逐个对两种方案的结构拓扑、优点和限制、设计细节、功能演示等几个方面深入研究。

一、基于lora无线通信构建的MESH网络,实现局域物联网。

结构拓扑

设计概述
  系统分为主机和从机,主机由主控、显示和lora通信模块组成,从机由主控、通信模块和多种传感器组成。工作流程为,从机采集传感器数据存储,主机轮训从机,当被询问到时,根据命令上传传感器数据或者控制IO口输出。主机收到从机数据后处理显示。

优点和限制
优点:1通信逻辑简单,使用现成模块更加简单。2成本低,sx1276相较网关价格有数量级差距。
限制:1网络容量低,随着网络容量增加,轮训的时间变长,实时性变差2增加新节点需要修改主机程序。

电路设计
MCU最小系统,我用的芯片是Microchip的ATSAMC21
电池充电电路,充电电压4.2v,给锂离子电池充电。芯片 EAT6003
电源管理,一个给MCU供电,另一个给传感器供电,由MCU控制是否供电,控制功耗。
传感器电路,两路I2C、两路UART、两路ADC。分别是空气质量CCS811、气压BMP180、GPS模块(备用,可应用于农场都能场景)、lora通信模块、TEMT光敏电阻、NTC热敏电阻。

硬件搭建
8.18补充
一个主机,依次询问两个从机,间隔为2s。
软件设计
8.18补充
主程序流程图,关键函数
/**
项目:21IC
角色:中心设备
功能:询问从机,控制IO
*/
#include <asf.h>
#include "my_driver/my_driver.h"
int main (void)
{
        system_init();                        //时钟
        delay_init();                        //延时
        my_io_init();                        //io初始化
        sercom_lora_init();                //lora串口
        sercom_test_init();                //测试串口
        system_interrupt_enable_global();                //开中断
        while(1)
        {
                ask_slave();                //询问从机2s中一次
        }
}
void ask_slave(void)
{
        //发送给终端03
        static uint8_t i;
        for (i=0;i<16;i++)
        {
                usart_write_wait(&usart_lora,test_cmd_ASK_03[i]);
        }
        write_2s=2000;
        while(write_2s)
        {
                delay_ms(1);
                write_2s--;
                recieve_lora();        
        }
        //需要添加从机再添加上述代码
        //发送给终端05
        for (i=0;i<16;i++)
        {
                usart_write_wait(&usart_lora,test_cmd_ASK_05[i]);
        }
        write_2s=2000;
        while(write_2s)
        {
                delay_ms(1);
                write_2s--;
                recieve_lora();
        }
}
static void recieve_lora(void)
{
        if (cmd_flag)
        {
                cmd_flag=0;
                static uint8_t i;
                for (i=1;i<cmd_count-2;i++)
                {
                        usart_write_wait(&usart_test,cmd_message[i]);
                }
        }        
}


从程序流程图,关键函数
#include <asf.h>
#include "my_driver/my_driver.h"
int main (void)
{
        system_init();                        //时钟
        delay_init();                        //延时函数
        my_io_init();                        //LED
        tc_100ms_init();                //100ms
        sercom_test_init();                //调试串口
        sercom_lora_init();                //lora通信的串口
        sercom_i2c_init();                //I2C初始化
        system_interrupt_enable_global();                //开中断
        adc_ntc_init();
        adc_light_init();
        bmp180_init();
        ccs811_init();                        //空气质量传感器初始化
        while(1)
        {
                task_senser();   //读各种传感器的值
                answer_host();                //收到主机询问,回复传感器值
        }        
}
void task_senser(void)
{
        if (task_count>10)
        {
                task_count=0;
                read_ALG();
                read_light();
                read_ntc();
                read_UT_UP();
                port_pin_toggle_output_level(LED_1);
        }
}
void answer_host(void)
{
        //判断串口是否有数据
        if (cmd_flag)
        {
                cmd_flag=0;
                //解释命令
                if(hand_center("#ASK[        DISCUZ_CODE_5        ]quot;))
                {
                        pack_message();                                        //按模块格式封装数据
                        send_message();                                        //发送封装数据
                        port_pin_toggle_output_level(LED_3);
                }
        }
}

功能演示
8月18日补充

主机测试串口输出03和05两个设备上传的不同数据。

8月19日更新,为主机加入了屏幕显示,将串口打印的代码,改成在屏幕显示即可。

可以显示co2的值和累计曲线。


二、基于loraWAN无线网络,实现局域物联网

结构拓扑

设计概述
  节点采集传感器信息,上报给网关。网关发送给应用服务器,应用服务器做出显示。本方案中,网关和应用服务器都部署在linux电脑上,实物上是一个,对外输出HDMI接口做显示。

优点和限制
优点:1网络容量大。2添加节点简单。3节点功耗更低
限制:1网关成本高。2LoraWAM网络复杂,需要多方面知识

传感器部分和方案一相同,只是在无线通信的时候换成带LoRaWAN的协议栈的模块。服务器通过网关收到节点数据后,再写个web程序展示出来。
具体设计见3楼。

  说明:今天刚看见这个活动,还有一周的时间。所以不打算购买器件和制作电路板,有什么器件用什么,没有器件而不能实现的功能也不在纠结,争取能将两个方案制作出来,这才是最重要的。其中MCU采集传感器部分是相同的,通信部分和显示部分会有区别。两个方案的通信部分我计划做完。显示会做方案一的,方案二只在终端显示节点原始数据,不做进一步处理了。希望能够按计划完成^_^

  说明2:两种方案使用的模块通信距离都可以达到1公里以上(直线距离)。可以说是远距离低功耗的无线通信方案,有一定的应用价值。

相关帖子

沙发
yongruru|  楼主 | 2018-8-14 22:02 | 只看该作者
本帖最后由 yongruru 于 2018-8-19 20:52 编辑

8月15日,今天翻箱倒柜找板子和器件。有几块以前工程剩下的MCU板子,还翻出来一个空气质量传感器CSS811、一个气压传感器BMP180、一个GPS模块、光敏电阻。最重要的还有几个lora模块。下面展示出来

MCU板子

依次是:LoRa模块、GPS、CSS811、BMP180、TEMT

找好了这些材料,今天就先把原理图画出来,更新到上面,然后硬件连通,明天开始写程序

--------------------------------------------------------------------------------------------------------------------------------

8月16日,今天看了看板子的引脚定义,把部分器件先连起来了,有空气质量传感器,和lora通信模块,还有测试的串口,如下图


然后把程序的框架建立起来:添加所需要的驱动,建立自己的模块列表。下面简单展示下步骤

在ASF库中选择自己需要的驱动包

创建自己的模块列表,如上图标志1,今天只完成了ccs811的程序模块。上图中2是设备的初始化,3是ccs811的初始化,4是读取C02和有机物

最后是程序运行结果

传感器暂时先到这里,明天先把lora通信部分搞出来,等全部程序写完,我整理整理,再一起上传。23:08,晚安

---------------------------------------------------------------------------------------------------------------------------------------------------

8月17日,今天来弄lora通信

首先配置lora模块,写入频率,网络地址,节点地址,串口波特率。相同频率和网络、不同地址的模块才可以通信。

配置出主机和从机。

将Lora模块连接到MCU板,左边从机,右边主机

下面开始主机软件编写
main.c
/**
项目:21IC
角色:中心设备
功能:询问从机,控制IO
*/
#include <asf.h>
#include "my_driver/my_driver.h"
int main (void)
{
        system_init();                        //时钟
        delay_init();                        //延时
        my_io_init();                        //io初始化
        sercom_lora_init();                //lora串口
        sercom_test_init();                //测试串口
        system_interrupt_enable_global();                //开中断
        while(1)
        {
                ask_slave();                //询问从机2s中一次
        }
}

ask_slave()轮训从机函数
void ask_slave(void)
{
        //发送给终端A
        static uint8_t i;
        for (i=0;i<16;i++)
        {
                usart_write_wait(&usart_lora,test_cmd_ASK_03[i]);
        }
        write_2s=2000;
        while(write_2s)
        {
                delay_ms(1);
                write_2s--;
                recieve_lora();        
        }
        
        //需要添加从机再添加上述代码
}

recieve_lora()接收从机回复
static void recieve_lora(void)
{
        if (cmd_flag)
        {
                cmd_flag=0;
                static uint8_t i;
                for (i=1;i<cmd_count-2;i++)
                {
                        usart_write_wait(&usart_test,cmd_message[i]);
                }
        }        
}

lora串口中断服务,接收字节,解析出从机数据
/LoRa中断函数
ISR(SERCOM4_Handler){
        uint16_t temp;
        if (usart_read_wait(&usart_lora, &temp) == STATUS_OK) {
                lora_buffer=temp;        
                if (lora_buffer==0x23)                //遇到两个#判定为头
                {
                        cmd_head_count++;
                }else
                {
                        cmd_head_count=0;
                }
                if(cmd_head_count==2)        //开始存储
                {
                        cmd_start=1;
                        cmd_count=0;
                        cmd_flag=0;
                }
                if (cmd_start)
                {
                        cmd_message[cmd_count]=lora_buffer;
                        cmd_count++;
                }
                if (lora_buffer==0X24)
                {
                        cmd_end_count++;
                }else
                {
                        cmd_end_count=0;
                }
                if (cmd_end_count==2)
                {
                        cmd_start=0;
                        cmd_flag=1;
                }
        }
}

从机软件修改
main函数中,注销之前的应用函数,添加answer_host()函数
 while(1)
        {
//                 delay_ms(1000);
//                 read_ALG();                        //读ccs811
                answer_host();                //收到主机询问,回复传感器值
        }        
answer_host()函数,解主机询问,后续可以添加控制IO等
void answer_host(void)
{
        //判断串口是否有数据
        if (cmd_flag)
        {
                cmd_flag=0;
                //解释命令
                if(hand_center("#ASK[        DISCUZ_CODE_5        ]quot;))
                {
                        pack_message();                                        //按模块格式封装数据
                        send_message();                                        //发送封装数据
                        port_pin_toggle_output_level(LED_3);
                }
        }
}
实现通信后,下一步工作是添加主机HMI人机交互界面,丰富传感器。
今天就先到这里,明天周六争取完成方案一。
今天是七夕祝愿有情人终成眷属,不多说了,老婆喊我了

--------------------------------------------------------------------------------------------------------------------------------
8月18日上午,先把所填程序运行的结果补上

S03表示从机的编号,主机询问03号,03号回复上来的值
下面在添加一台从机,演示一主多从,轮训查询,避免碰撞
void ask_slave(void)
{
        //发送给终端03
        static uint8_t i;
        for (i=0;i<16;i++)
        {
                usart_write_wait(&usart_lora,test_cmd_ASK_03[i]);
        }
        write_2s=2000;
        while(write_2s)
        {
                delay_ms(1);
                write_2s--;
                recieve_lora();        
        }
        //需要添加从机再添加上述代码
        //发送给终端05
        for (i=0;i<16;i++)
        {
                usart_write_wait(&usart_lora,test_cmd_ASK_05[i]);
        }
        write_2s=2000;
        while(write_2s)
        {
                delay_ms(1);
                write_2s--;
                recieve_lora();
        }
}
主机程序,添加代码,
从机程序程序由于没有更多的传感器,用固定值模拟。
最后演示如下

主机收到了上S03和S05两个从机的数据。
下午来丰富下,传感器的内容。

8月18日下午,首先看了下bmp180,也是i2c接口,读取寄存器的值也比较简单,复杂一点的是,读出来的值需要计算。而且计算量还不小,不过按他的公式来基本就能算出来了

数据手册关于计算的部分
void read_UT_UP(void)
{
        port_pin_toggle_output_level(LED_3);
        //读取I2C
        write_data[0]=0xF4;
        write_data[1]=0x2E;
        i2c_master_write_packet_wait(&i2c_master_instance, &bmp180_write2);
        delay_ms(5);
        write_data[0]=0xF6;
        i2c_master_write_packet_wait_no_stop(&i2c_master_instance, &bmp180_write1);
        i2c_master_read_packet_wait(&i2c_master_instance, &bmp180_read2);
        //存储
        unsigned int u_temp;
        unsigned long u_pressure;
        long x1,x2,b5,b6,x3,b3,p;
        unsigned long b4,b7;
        
        u_temp=read_data[0];
        u_temp=u_temp<<8;
        u_temp=u_temp+read_data[0];

        //计算温度
        x1 = (((long)u_temp - (long)ac6)*(long)ac5) >> 15;
        x2 = ((long) mc << 11) / (x1 + md);
        b5 = x1 + x2;
        temperature = ((b5 + 8) >> 4);
        //////////////////////////////////////////////
        write_data[0]=0xF4;
        write_data[1]=0x34;
        i2c_master_write_packet_wait(&i2c_master_instance, &bmp180_write2);
        delay_ms(5);
        write_data[0]=0xF6;
        i2c_master_write_packet_wait_no_stop(&i2c_master_instance, &bmp180_write1);
        i2c_master_read_packet_wait(&i2c_master_instance, &bmp180_read3);
        
        u_pressure=read_data[0];
        u_pressure=u_pressure<<8;
        u_pressure=u_pressure+read_data[1];
        
        //计算气压
        b6 = b5 - 4000;
        x1 = (b2 * (b6 * b6)>>12)>>11;
        x2 = (ac2 * b6)>>11;
        x3 = x1 + x2;
        b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
        x1 = (ac3 * b6)>>13;
        x2 = (b1 * ((b6 * b6)>>12))>>16;
        x3 = ((x1 + x2) + 2)>>2;
        b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
        b7 = ((unsigned long)(u_pressure - b3) * (50000>>OSS));
        if (b7 < 0x80000000)
        {
                p = (b7<<1)/b4;
        }
        else
        {
                p = (b7/b4)<<1;
        }
        x1 = (p>>8) * (p>>8);
        x1 = (x1 * 3038)>>16;
        x2 = (-7357 * p)>>16;
        pressure = p+((x1 + x2 + 3791)>>4);
        //usart_write_buffer_wait(&usart_test," pres=",6);
//         usart_write_wait(&usart_test,pressure/100000+0x30);
//         usart_write_wait(&usart_test,pressure%100000/10000+0x30);
//         usart_write_wait(&usart_test,pressure%10000/1000+0x30);
//         usart_write_wait(&usart_test,pressure%1000/100+0x30);
//         usart_write_wait(&usart_test,pressure%100/10+0x30);
//         usart_write_wait(&usart_test,pressure%10+0x30);
//         usart_write_wait(&usart_test,0x0a);
        
        //绝对高度计算
        //         height = 44330 * (1-powf(((pressure) / 101325),(1.0/5.255)));
}
我的程序,气压值出来了,绝对高度还算的不对,后续再看吧

然后弄了下光敏电阻和热敏电阻,光敏电阻随光强度变强阻值变小,热敏电阻也是温度低时阻值比较大。原理是一样的,只是配的分压电阻需要实际选择下。单片机ADC采集传感器的电压再经过公式或者查表转换成相应的单位。下面我的程序值写到读ADC的值,后面转换的单位的工作暂时没有做,有兴趣的朋友可以自己查查,网上也不较多。
//热敏电阻adc初始化
void adc_ntc_init(void)
{
        struct adc_config config_adc_ntc;
        adc_get_config_defaults(&config_adc_ntc);                                                //获取默认配置
        config_adc_ntc.positive_input        =        ADC_POSITIVE_INPUT_PIN0;
        config_adc_ntc.negative_input   =        ADC_NEGATIVE_INPUT_GND;
        config_adc_ntc.reference        =        ADC_REFERENCE_INTVCC2;                //选择基准电压
        adc_init(&adc_instance, ADC0, &config_adc_ntc);                                        //初始化
        adc_enable(&adc_instance);                                                                                //使能        
}
static void read_ntc(void)
{
        adc_set_positive_input(&adc_instance,ADC_POSITIVE_INPUT_PIN0);
        uint16_t ntc_result;
        adc_start_conversion(&adc_instance);                //开始转换
        while (adc_read(&adc_instance,&ntc_result)==STATUS_OK);
}


到现在实现了主从的轮训通讯,从机可以采集到4个传感器的值。到此方案一先告一段落。稍后将这几天的内容更新到1楼,完整的程序还是要整理后再放出来(完善功能,编写注释)。朋友们的回复是我最大的动力,欢迎交流、批评、灌水、斧正、提问。
楼下开始方案二LoRaWAN网络研究。
-------------------------------------------------------------------------------------------------------------------------------------------------

8月19日更新,主机还有块屏幕,给忘记了。屏幕用最简单的串口屏,DIY嘛。串口屏会提供开发软件,将界面便捷好后,下载到屏幕中,然后主机给屏传递需要限制的值就可以了,下面大致坐下演示

添加了三个控件,一个文本显示“CO2”,一个数字是CO2的值,还有一个曲线是根据每次CO2的值绘制出来的。
单片机向屏幕串口发送“n0.val=**”可以给数字控件赋值,发送“add 1 0 **”给曲线赋值,**为CO2的实际值。下面是实物演示


使用特权

评论回复
评分
参与人数 1威望 +4 收起 理由
arima + 4 很给力!
板凳
yongruru|  楼主 | 2018-8-14 22:03 | 只看该作者
本帖最后由 yongruru 于 2018-8-21 13:29 编辑

方案一的网络基本上算是小打小闹,不是说看不起第一种方案,这就像单片机系统和PC电脑一样,各有特点,各有适合的应用场景,只不过电脑更通用一些。同样的LoRaWAN网络应用的场景也更为广阔。
简单介绍介绍,lora是无线电射频技术,方案一和方案二物理上都是lora技术。LoRaWAN是网络技术,更多的是软件技术。

本方案使用class a模式,可以更节能。5秒钟上报一次数据,上报数据后会收下发命令。因为对距离要求不是很高,对实时性还有一定要求,所以设置SF=7,BW=250。这种配置下网络容量差不多能到100左右,如果要增加网络容量,可以增加网关或者把节点上报时间间隔再加大些。


下面展示下硬件

网关
网关大致由一个linux电脑和SX1301射频模块组成,linux电脑里有SX1301驱动服务和LoRaWAN网络服务。这是一个单网关的一体方案,集成了NS服务。也可以将NS服务放在云端,基本上这两种方式的比较多。然后呢,将我的应用服务也放在这个linux电脑里,用HDMI连接显示器,访问浏览器显示数据。物理上中心只是一个设备,但却包含了一个网关和服务器,服务器里有包含了3个服务。



节点
节点是一个stm32+sx1278,其中stm32包含了LoRaWAN协议栈。
这里插入一条,为什么两个方案中节点我都选择了现成模块?其实硬件原理上不是很难,一共就一二十个器件,完全可自己画板子做,成本低,使用也更灵活,但是为什么不这样做呢?因为射频对布局、布线、阻抗有一定要求,需要设计时考虑,需要射频工程师来完成。即便设计PCB没有问题,购买器件的参数差别、精度、甚至不同批次都可能产生影响。一般大厂都是和升特公司合作共同开发,升特公司提供指导。市面上的模块性能差别还是挺大的,多数达不到宣传的通信距离。
继续说节点的功能,在升特提供的协议栈上修改,协议栈是一个状态机,负责初始化、入网,发送数据等。



我添加一个任务,串口收到数据,修改状态标志,通过协议栈发送数据,如下

串口中断中解处我的数据。

修改状态标志,发送数据。

8月20日,补充演示内容:串口助手输入数据,通过上面程序的节点发送出去,网关接收到数据给服务器,应用访问服务器显示出来。
演示:

1、节点上电,自动入网(网关打开的情况下)。之后就可以发数据了。

2、中心设备上电,自动打开lorawan的服务。浏览器登录应用服务,输入ID,连接后就可以和节点收发数据了。
如上图,中心已经收到节点发过来的数据“CO2=100 VOL=50”,显示的是16进制,感兴趣的朋友可以对照下ACSII码表,确认下。




使用特权

评论回复
地板
21ic小喇叭| | 2018-8-15 07:59 | 只看该作者
期待后续继续分享哦~

使用特权

评论回复
5
小小电子爱好者| | 2018-8-15 08:42 | 只看该作者
加油

使用特权

评论回复
6
603820434| | 2018-8-15 10:05 | 只看该作者
点赞  

使用特权

评论回复
7
yongruru|  楼主 | 2018-8-17 09:15 | 只看该作者
21ic小喇叭 发表于 2018-8-15 07:59
期待后续继续分享哦~

好的,争取截止前每天有更新

使用特权

评论回复
8
yongruru|  楼主 | 2018-8-17 09:16 | 只看该作者

使用特权

评论回复
9
yongruru|  楼主 | 2018-8-17 09:16 | 只看该作者

使用特权

评论回复
10
21ic小喇叭| | 2018-8-17 15:42 | 只看该作者
比赛还有三天就结束啦,还请及时更新哦,这样才不会影响到时候的评委打分~

使用特权

评论回复
11
yongruru|  楼主 | 2018-8-20 11:10 | 只看该作者
21ic小喇叭 发表于 2018-8-17 15:42
比赛还有三天就结束啦,还请及时更新哦,这样才不会影响到时候的评委打分~ ...

麻烦将我的帖子链接也放到活动参赛帖里吧。

使用特权

评论回复
评论
21ic小喇叭 2018-8-20 13:42 回复TA
好的 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

72

帖子

4

粉丝