Zigbee无线传感网 CC2530+DHT11&DS18B20 温湿度采集 串口上位机显示
Posted Link2Points
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Zigbee无线传感网 CC2530+DHT11&DS18B20 温湿度采集 串口上位机显示相关的知识,希望对你有一定的参考价值。
一、介绍
- 硬件:4块CC2530模块,2个DS18B20温度传感器、1个DHT11传感器、一个抽水器(可无)。
- 软件:基于C#开发上位机(.NET Framework 4.8)、ZStack-2.5.1a协议栈。
- 由协调器及各节点组建星型网,采用点播通讯(P2P),结合上位机的限制最多可以接入6个终端节点。
- 硬件效果图
二、上位机数据采集
(一)采集数据
打开串口,显示情况和波动。
(二)拓扑结构
显示节点的数据和其短地址。
(三)新节点加入网络
(四)节点事件
节点4湿度高于 70%,进行提示,拓扑图隐藏该节点,与此同时抽水器停止工作。
三、实现分析
(一)配置文件
- 在f8wConfig.cfg中
设置信道 : -DDEFAULT_CHANLIST=
(似乎11信道容易受WIFI信号影响)
设置PAN_ID: -DZDAPP_CONFIG_PAN_ID= - 在SampleApp.h
数据发送间隔 3 s
#define SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT 3000
(二)发送
- 在 SampleApp.c 中
//无线发送到协调器
if ( AF_DataRequest( &SampleApp_P2P_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_P2P_CLUSTERID,
len, // 数据长度
str, // 数据内容
&SampleApp_MsgID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
}
(三)短地址和数据获取
短地址 pkt->srcAddr.addr.shortAddr 是网络随机分配的,
MAC地址 pkt->macDestAddr 更适合作为数据存储的主键,
数据 uint8 temperature=pkt->cmd.Data[0]; uint8 humidity=pkt->cmd.Data[1];
- 在AF.h中
typedef struct
{
union
{
uint16 shortAddr; // (短地址)
ZLongAddr_t extAddr;
} addr;
afAddrMode_t addrMode;
uint8 endPoint;
uint16 panId; // used for the INTER_PAN feature
} afAddrType_t;
typedef struct
{
osal_event_hdr_t hdr; /* OSAL Message header */
uint16 groupId; /* Message's group ID - 0 if not set */
uint16 clusterId; /* Message's cluster ID (簇ID) */
afAddrType_t srcAddr; /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,
it's an InterPAN message */
uint16 macDestAddr; /* MAC header destination short address (MAC地址) */
uint8 endPoint; /* destination endpoint */
uint8 wasBroadcast; /* TRUE if network destination was a broadcast address */
uint8 LinkQuality; /* The link quality of the received data frame (网络连接质量) */
uint8 correlation; /* The raw correlation value of the received data frame */
int8 rssi; /* The received RF power in units dBm (信号能量) */
uint8 SecurityUse; /* deprecated */
uint32 timestamp; /* receipt timestamp from MAC */
uint8 nwkSeqNum; /* network header frame sequence number */
afMSGCommandFormat_t cmd; /* Application Data */
} afIncomingMSGPacket_t;
- 在 SampleApp.h 中
void SampleApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt )
{
uint8 buff[50]={0};
switch ( pkt->clusterId )
{
// 接收终端上传的温湿度数据
case SAMPLEAPP_P2P_CLUSTERID:
{
// 取出温湿度数据
uint8 temperature = pkt->cmd.Data[0];
uint8 humidity= pkt->cmd.Data[0];
// 取出短地址
uint16 shortAddress = pkt->srcAddr.addr.shortAddr;
// 处理和数据打包上传串口略····
}
break;
// 接收温度
case SAMPLEAPP_DS18B20_CLUSTER:
{
// 略····
}
break;
default:
break;
(四)数据包分析
串口数据打包格式:
长度:14;
校验位:C4;
功能码:02;
数据:3B 31 3B 54 3A 32 37 2E 30 20 43 3B 34 34 34 31 3B
结尾:0D 0A 。
补充
- 数据部分的3B作为数据内容分隔符(;):(功能码)+(;)+(采集数据)+(;)+(短地址)+(;)。
- 并以换行符为结尾 \\r\\n 比较省事
(五)上位机
// 是否打开串口
bool isOpenSP;
// 记录数
private int recordNum = 0;
// 记录各个节点的检测结果 用于 拓扑图
private string[] pointsTopology = {"", "", "", "", "", ""};
// 绘图
private Graphics graphics;
private void mainForm_Load(object sender, EventArgs e)
{
Resize += mainForm_Resize;
refreshBtn_Click(null, null);
// 波特率
int[] BR =
{
4_800, 9_600, 14_400, 19_200, 38_400, 56_000, 57_600, 115_200, 128_000,
256_000, 460_800, 512_000, 750_000, 921_600, 1_500_000
};
foreach (int val in BR)
{
BRComboBox.Items.Add(val);
}
// 手动添加事件处理程序
serialPort1.DataReceived += serialPort1_DataReceived;
// 绘图初始化
graphics = topologyPanel.CreateGraphics();
}
- 串口部分
通过Rider开发的上位机,似乎在VS中串口部分会出问题(这时就需要利用委托delege)
/*
* 3. 功能实现
* 打开串口按键按键 openBtn_Click
* 串口数据接收 serialPort1_DataReceived
* 接收数据清空 clearBtn_Click
* 刷新串口号按键 refreshBtn_Click
*/
private void openBtn_Click(object sender, EventArgs e)
{
if (SPComboBox.Text.Equals("") || BRComboBox.Text.Equals(""))
{
return;
}
if (!isOpenSP)
{
try
{
serialPort1.PortName = SPComboBox.SelectedItem.ToString();
serialPort1.BaudRate = Convert.ToInt32(BRComboBox.SelectedItem.ToString());
serialPort1.Open();
}
catch
{
MessageBox.Show("端口错误,请检查串口" , "错误");
return;
}
}
else
{
serialPort1.Close();
}
openBtn.Text = isOpenSP ? "打开" : "关闭";
SPComboBox.Enabled = !SPComboBox.Enabled;
BRComboBox.Enabled = !BRComboBox.Enabled;
isOpenSP = !isOpenSP;
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (isOpenSP)
{
try
{
// 读取串口数据
string revStr = serialPort1.ReadLine();
revRichTextBox.AppendText(revStr);
revRichTextBox.SelectionStart = revRichTextBox.Text.Length;
// 显示
string[] pointsData = revStr.Split('\\n');
Label[] pointsLabel = {point1Label, point2Label, point3Label, point4Label, point5Label, point6Label};
// 节点名称
Label[] pointsName = {pointName1Label, pointName2Label, pointName3Label, pointName4Label, pointName5Label, pointName6Label};
foreach (string pointData in pointsData)
{
int preSplit = pointData.IndexOf(";") + 1;
int nextSplit = pointData.IndexOf(";", preSplit);
// 获取采集节点 显示 id - 1
int index = Convert.ToInt32(pointData.Substring(preSplit,nextSplit - preSplit)) - 1;
preSplit = nextSplit + 1;
nextSplit = pointData.IndexOf(";", preSplit);
// 串口格式解析显示
pointsLabel[index].Text = pointData.Substring(preSplit, nextSplit - preSplit);
// 温度
string temp = pointData.Substring(preSplit + 2, pointData.IndexOf(" C") - preSplit - 2);
chart1.Series[index].Points.AddXY(recordNum, temp);
// 该曲线的节点名称
chart1.Series[index].Name = pointsName[index].Text + "温度";
// 湿度
string humidity = "50";
if (index % 2 != 0)
{
humidity = pointData.Substring(pointData.IndexOf("H:") + 2,
nextSplit - pointData.IndexOf("H:") - 2);
chart1.Series[pointsLabel.Length + index].Points.AddXY(recordNum, humidity);
// 该曲线的节点名称
chart1.Series[pointsLabel.Length + index].Name = pointsName[index].Text + "湿度";
}
// 给予处理 温度低于5度 湿度大于70% 则颜色提示
if (Convert.ToDouble(temp) < 5 || Convert.ToDouble(humidity) > 70)
{
pointsLabel[index].BackColor = Color.FromArgb(74, 140, 218);
pointsTopology[index] = "";
}
else
{
pointsLabel[index].BackColor = Color.White;
// 记录可处理的值 用于拓扑图
pointsTopology[index] = pointData.Substring(pointData.IndexOf(";") + 1);
}
pointsName[index].BackColor = pointsLabel[index].BackColor;
}
recordNum++;
chart1.ChartAreas[0].AxisX.Title = "时间";
chart1.ChartAreas[0].AxisY.Title = "数据";
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString());
}
}
}
private void clearBtn_Click(object sender, EventArgs e)
{
revRichTextBox.Text = "";
point1Label.Text = "0";
point2Label.Text = "0";
point3Label.Text = "0";
point4Label.Text = "0";
point5Label.Text = "0";
point6Label.Text = "0";
}
private void refreshBtn_Click(object sender, EventArgs e)
{
SPComboBox.Items.Clear();
// 获取端口号
string[] PortNames = SerialPort.GetPortNames();
for (int i = 0; i < PortNames.Length; i++)
{
//将数组内容加载到comboBox控件中
SPComboBox.Items.Add(PortNames[i]);
}
}
- 数据拓扑部分
/*
* 2 功能选项
* 功能列表缩放 funBtn_Click
* 按键初始化 funBtnsInit
* 数据采集界面按键 dataBtn_Click
* 拓扑图界面按键 topologyBtn_Click
*/
private void funBtn_Click(object sender, EventArgs e)
{
funPanel.Width = funPanel.Width == 40 ? 250 : 40;
titLabel.Width = funPanel.Width;
}
private void funBtnsInit()
{
dataBtn.BackColor = funPanel.BackColor;
topologyBtn.BackColor = funPanel.BackColor;
dataPanel.Visible = false;
topologyPanel.Visible = false;
}
private void dataBtn_Click(object sender, EventArgs e)
{
funBtnsInit();
dataBtn.BackColor = clickedBgColor;
dataPanel.Visible = true;
}
private void topologyBtn_Click(object sender, EventArgs e)
{
funBtnsInit();
topologyBtn.BackColor = clickedBgColor;
topologyPanel.Visible = true;
// 绘制静态拓扑图
graphics.Clear(topologyPanel.BackColor);
graphics.FillRectangle(new SolidBrush(Color.Crimson),300, 300, 50, 50);
Pen pen = new Pen(Color.Coral);
Brush brush = new SolidBrush(Color.Coral);
Point[] startPoint =
{
new Point(300, 300), new Point(325, 300), new Point(350, 300),
new Point(350, 350), new Point(325, 350), new Point(300, 350)
};
Point[] endPoint =
{
new Point(100, 100), new Point(325, 200), new Point(450, 400),
new Point(450, 450), new Point(325, 450), new Point(250, 200)
};
int index = 0;
foreach (string pointTopology in pointsTopology)
{
if (pointTopology.Equals(""))
{
continue;
}
graphics.DrawLine(pen,startPoint[index], endPoint[index]);
graphics.FillEllipse(brush, endPoint[index].X, endPoint[index].Y, 20, 20);
graphics.DrawString(pointTopology,
new Font("微软雅黑", 10),
new SolidBrush(Color.Black),
endPoint[index].X + 5, endPoint[index].Y + 5);
index++;
}
pointsTopology = new []{"", "", "", "", "", ""};
}
四、IAR
- iar软件和协议栈之间似乎有对应的联系,Z-stack 2.5.1的协议栈在 高版本 IAR 下编译出问题参考
- IAR 设置 外部编辑器
Tools > Options
Editor > External Editor > 勾选 Use External Editor > 选择外部编辑器程序地址 > 填写 Arguments栏内容为 “$FILE_PATH$” > 点击确认
点击文件,即可通过其它编辑器编辑,然而也会有中文乱码的问题。
以上是关于Zigbee无线传感网 CC2530+DHT11&DS18B20 温湿度采集 串口上位机显示的主要内容,如果未能解决你的问题,请参考以下文章