Proteus是一款经典的单片机仿真软件,该软件功能强大,但是也有其限制,Proteus不提供WIFI模块等网络模块扩展网络功能,但是在实际使用中,我们真的无法在Proteus中实现网络功能吗?答案是否定的,Proteus有一个非常灵活的器件,那就是串口(COMPIM),结合虚拟串口,COMPIM可以和电脑通信,这时我们可以使用python写一个脚本,接受虚拟串口数据,然后使用我们计算机连接的网络发送到阿里云平台,此时我们的电脑充当了一个网关的作用,通过这种方式我们就实现了Proteus连接到阿里云平台。本次设计需要写三个代码,分别是Protues端、Python网关、Python UI。
一、实现步骤
1、Proteus端
首先我们需要在Proteus上创建一个简单的的仿真项目,只有两个部分分别是一个滑动变阻器,用于模拟传感器,一个COMPIM,并配置好虚拟串口。
然后我们测试一下,STM32读取ADC是否正确,使用串口调试助手,查看一下数据。如下图,当串口循环打印234(不换行),表示本次数据获取正确。
参考代码如下:
#include "stm32f10x.h"
#include "stdio.h"
#include "bsp_SysTick.h"
#include "system.h"
#include "usart.h"
#include "bsp_clkconfig.h"
#include "bsp_mcooutput.h"
#include "LCD1602.h"
#include "Light.h"
#include "stm32f10x_tim.h"
#include "Light.h"
#include "Key.h"
#include "Led.h"
#include "Timer.h"
#include "stm32f10x_it.h"
uint16_t val=0;
void delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //璁剧疆瀹氭椂鍣ㄩ噸瑁呭€?
SysTick->VAL = 0x00; //娓呯┖褰撳墠璁℃暟鍊?
SysTick->CTRL = 0x00000005; //璁剧疆鏃堕挓婧愪负HCLK锛屽惎鍔ㄥ畾鏃跺櫒
while(!(SysTick->CTRL & 0x00010000)); //绛夊緟璁℃暟鍒?
SysTick->CTRL = 0x00000004; //鍏抽棴瀹氭椂鍣?
}
void delay_ms(uint32_t xms)
{
while(xms--)
{
delay_us(1000);
}
}
uint16_t cnt=0;
int main(void)
{
int i=0;
RCC_ClocksTypeDef RCC_Clocks; //时钟结构体
HSE_SetSysClock(RCC_PLLMul_7); //8*7=56Mhz,库函数默认多数为72MHZ。此处设置为56M,主要是因为发现72M时proteus仿真串口容易出现乱码。
RCC_GetClocksFreq(&RCC_Clocks); //获取片上时钟
MCO_GPIO_Config(); //MCO配置,PA8输出波形,可用示波器观察
RCC_MCOConfig(RCC_MCO_SYSCLK); //MCO选择输出的时钟
SysTick_Init(); //嘀嗒时钟初始化
Led_Init();
usart_init();
Light_Init();
while(1)
{
val = ((float)Light_GetValue()/4095*330);
if(++cnt >= 700){
cnt=0;
printf("%d", val);
}
delay_ms(200);
}
}
2、Python网关端
Python网关端需要用到的包大致为pyserial和MQTT,通过串口获取到虚拟串口发送过来的数据,然后连接MQTT,将虚拟串口转发而来的数据进行上传。
(1)首先,我们需要在注册一个阿里云,点开物联网平台。
(2)创建一个物联网产品,并且在里面创建两个设备。light是连接Proteus的设备,MQTT_fx是连接Python UI的设备。
(3)连接阿里云平台,我们需要获取阿里云注册产品和设备时的三元组,在阿里云平台上获取并在python中以字典的方式存储,如下图:
options = {
'productKey': '',
'deviceName': '',
'deviceSecret': '',
'regionId': 'cn-shanghai'
}
(4)然后,我们需要通过虚拟串口连接Proteus,并接受数据,然后上传到阿里云平台。参考代码如下:
import paho.mqtt.client as mqtt
import hashlib
import hmac
import serial
import time
serial = serial.Serial("COM2", 115200, timeout=0.5)
# 这个就是我们在阿里云注册产品和设备时的三元组啦
# 把我们自己对应的三元组填进去即可
options = {
'productKey': '',
'deviceName': '',
'deviceSecret': '',
'regionId': 'cn-shanghai'
}
HOST = options['productKey'] + '.iot-as-mqtt.' + options['regionId'] + '.aliyuncs.com'
PORT = 1883
PUB_TOPIC = "/sys/" + options['productKey'] + "/" + options['deviceName'] + "/thing/event/property/post";
def hmacsha1(key, msg):
return hmac.new(key.encode(), msg.encode(), hashlib.sha1).hexdigest()
def getAliyunIoTClient():
timestamp = str(int(time.time()))
CLIENT_ID = "paho.py|securemode=3,signmethod=hmacsha1,timestamp=" + timestamp + "|"
CONTENT_STR_FORMAT = "clientIdpaho.pydeviceName" + options['deviceName'] + "productKey" + options[
'productKey'] + "timestamp" + timestamp
# set username/password.
USER_NAME = options['deviceName'] + "&" + options['productKey']
PWD = hmacsha1(options['deviceSecret'], CONTENT_STR_FORMAT)
client = mqtt.Client(client_id=CLIENT_ID, clean_session=False, callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
client.username_pw_set(USER_NAME, PWD)
return client
def recv(serial):
while True:
dat = serial.readline()
if dat == '':
continue
else:
break
return dat
if __name__ == '__main__':
if serial.isOpen():
print("Serial COM2 Success!")
else:
print("Serial COM2 Failed!")
client = getAliyunIoTClient()
client.connect(HOST, 1883, 300)
while True:
dat = serial.readline()
if dat != b'':
dat = int(dat)
dat = dat*1.0/100
final_string = f'{{"voltage":{dat}}}'
client.publish("/k0ehplCy1Mt/light/user/update", final_string, 0)
print("Send", dat)
time.sleep(0.2)
3、阿里云产品流转
(1)在阿里云平台上再注册一个设备,该设备用于连接到我们的PythonUI,我们设备的名字叫做 MQTT_fx.
(2)创建云产品流转规则,本次云产品流转规则名字叫做IOT1,如下图:
(3)编写SQL语句,进行topic之间的流转。
4、Python UI端口
PythonUI端有两个功能,一个是从阿里云获取数据,不同于Proteus端,PythonUI端需要连接另一个设备,另一个是PyQT显示。
(1)首先,我们需要连接到阿里云Mqtt_fx端,同样利用三元组,然后获取topic的数据,数据格式一般是json,本地对其进行解析,得到数据,然后让其显示在QT设计的前端窗口。代码如下所示:
def on_message(self, mqttc, obj, msg):
print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))
self.label3set("设备状态:在线")
dat = str(msg.payload)
self.qle.append("接收数据\n" + dat)
dat = dat.lstrip("b")
# 查找冒号的位置
colon_index = dat.index(':')
# 提取冒号后的部分,并去除可能的空格
number_part = dat[colon_index + 1:].strip()
number_part = number_part.rstrip("}'")
# 输出结果
print(number_part)
text = "电压:" + number_part
(2)然后就是数据显示,本次设计了一个线程进行数据获取,同时设置mqtt的 on_mssage 函数,当阿里云有数据发送过来的时候 on_mssage 函数就会自动执行。
def on_message(self, mqttc, obj, msg):
print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))
self.label3set("设备状态:在线")
dat = str(msg.payload)
self.qle.append("接收数据\n" + dat)
dat = dat.lstrip("b")
# 查找冒号的位置
colon_index = dat.index(':')
# 提取冒号后的部分,并去除可能的空格
number_part = dat[colon_index + 1:].strip()
number_part = number_part.rstrip("}'")
# 输出结果
print(number_part)
text = "电压:" + number_part + "V"
self.label6.setText(text)
二、实现效果
1、运行Proteus
运行Protues,可以看到 COMPIM 的 TXD 在不断闪烁,说明此时STM32在给虚拟串口发送数据。
2、运行Python网关
运行Python网关,控制台会打印数据,这是Python网关发送给阿里云平台的数据,上传到阿里云的topic。
3、运行Python UI
运行Python UI可以看到设备状态、日志、电压、服务器状态,当我们运行了Proteus仿真,此时这几个值会进行显示,改变Proteus的值,Python UI的电压值会改变。
如果关闭Python网关,此时Python UI会显示设备离线,因为此时Python网关已经不工作了,Proteus无法连接到阿里云平台,但是服务器还是运行的,所以服务器状态是已连接。
三、项目总结
本次项目实现了Proteus联网,由于Proteus自生并没有WIFI模块,所以我们使用COMPIM进行,借助虚拟串口连接到我们写的Python脚本,借助计算机的网络连接到阿里云平台,阿里云平台进行数据流转将数据转发到另一个设备的topic,同时Python UI读取到数据显示在界面上。
以下是演示地址: