至于有线我们使用W5500来实现,在以前的文章中已经多次说明过,这一次就不再重复了。
3、软件设计
接下来我们说一说软件的设计,软件的设计较硬件要繁杂的多,我们选取其中一部分前面没有说明过的做一些说明。首先我们说一下PWM控制,每台采集站有2路进气,所以我们需要控制两个气泵,以及2路的PWM,每路可以单独控制,在试验时我们使用50%的占空比。
void PWM_Configuration(void) {
//计算初始化的频率和占空比
TimerPeriod = PWMTimePeriod;//计算用于设置ARR寄存器的值使产生信号的频率为17.57 Khz
PWM1Pulse= (uint16_t) (((uint32_t) 5 * (TimerPeriod - 1)) / 10);//计算CCR1寄存器的值在通道1和1N产生50%占空比,用于TIM1
PWM2Pulse= (uint16_t) (((uint32_t) 5 * (TimerPeriod - 1)) / 10);//计算CCR1寄存器的值在通道1和1N产生50%占空比,用于TIM8
PWM_InitProcess(TIM1,TimerPeriod,PWM1Pulse);
}
其次我们说以说I2C控制,有好几路传感器都使用的是I2C数据通讯来实现,我们在这里我们只说两个基本的I2C操作函数,一个是下发命令,一个是读取数据。所有的操作都刻以通过调用这两个函数来实现。
/*向I2C从站下发指令,指令格式均为1个字节*/
void SendCommandToI2CSlave(I2C_TypeDef*I2Cx,uint8_t deviceAddress,uint8_t command)
{
uint16_ti2cTimeout=TimeoutPeriod;
/*产生I2C起始信号*/
I2C_GenerateSTART(I2C2, ENABLE);
/*检测 EV5 事件并清除标志*/
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
{
if((i2cTimeout--) == 0) return ;
}
/*发送I2C从站的地址*/
I2C_Send7bitAddress(I2Cx,deviceAddress,I2C_Direction_Transmitter);
i2cTimeout=TimeoutPeriod;
/*检测 EV6 事件并清除标志*/
while (!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if((i2cTimeout--) == 0) return ;
}
/*下发操作命令*/
I2C_SendData(I2Cx, command);
i2cTimeout=TimeoutPeriod;
/*检测 EV8 事件并清除标志*/
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if((i2cTimeout--) == 0) return ;
}
/* 产生I2C停止信号 */
I2C_GenerateSTOP(I2Cx, ENABLE);
}
/*从I2C从站读取多个字节数据的值*/
void GetBytesFromI2CSlave(I2C_TypeDef*I2Cx,uint8_t deviceAddress,uint8_t *pData,uint16_t bytesNum)
{
uint16_ti2cTimeout=TimeoutPeriod;
/*如果I2C总线忙,则等待一段时间*/
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))
{
if((i2cTimeout--) == 0) return ;
}
/* 产生 I2C 起始信号 */
I2C_GenerateSTART(I2Cx, ENABLE);
/*检测 EV5 事件并清除标志*/
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
{
if((i2cTimeout--) == 0) return ;
}
/*发送I2C从站的地址*/
I2C_Send7bitAddress(I2Cx,deviceAddress+1,I2C_Direction_Receiver);
i2cTimeout=TimeoutPeriod;
/*检测 EV6 事件并清除标志*/
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
if((i2cTimeout--) == 0) return ;
}
while(bytesNum)
{
if(bytesNum==1)
{
I2C_AcknowledgeConfig(I2Cx, DISABLE);//关闭应答
I2C_GenerateSTOP(I2Cx, ENABLE);//停止信号
}
i2cTimeout=TimeoutPeriod;
/*检测 EV7 事件并清除标志*/
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))
{
if((i2cTimeout--) == 0) return ;
}
/*通过 I2C,从设备中读取一个字节的数据 */
*pData=I2C_ReceiveData(I2Cx);
pData++;
bytesNum--;
}
/*使能应答,方便下一次 I2C 传输*/
I2C_AcknowledgeConfig(I2Cx, ENABLE);
}
接下来我们看看将数据存储到本地SD卡的操作过程,数据保留2位小数,并且采用4舍5入处理。
//将数据写入到SD卡
void WriteDataToSDCard(void)
{
//将数据写入SD卡
saveData[0]=((int16_t)(tempProcessValue*100+0.5))/100.0;//温度测量值
saveData[1]=((int16_t)(presProcessValue*100+0.5))/100.0;//压力测量值
saveData[2]=((int16_t)(flowProcessValue1*100+0.5))/100.0;//流量计1的标况流量
saveData[3]=flowTatolVolume1;//流量计1的工况累计流量
saveData[4]=flowStdTatolVolume1;//流量计1的标况累计流量
saveData[5]=((int16_t)(flowProcessValue2*100+0.5))/100.0;//流量计2的标况流量
saveData[6]=flowTatolVolume2;//流量计2的工况累计流量
saveData[7]=flowStdTatolVolume2;//流量计2的标况累计流量
saveDate[0]=systemYear;
saveDate[1]=systemMonth;
saveDate[2]=systemDate;
saveDate[3]=systemHour;
saveDate[4]=systemMinute;
saveDate[5]=systemSecond;
SDCardFileOperation();
}
4、结果展示
我们在OneNET上创建了一个产品,6台设备,以及4个应用,来验证方案的效果,在测试过程中我们使用了Wifi方式来进行此次测试,因为这也是我们正是产品主要使用的连网方式。我们看一看数据上传的趋势图:
接下来我们看看显示位置及温湿度的应用截图:
我们再来看看显示大气压、温度和湿度的截图:
我们再来看看气体流量及柱状图显示:
至此,我们的测试项目完成,再次感谢
电子发烧友和中国移动OneNET给我们带来的完美体验。