拓展空间:
(1)仿真的获取和发送可以应用到真实传感器
(2)mqtt,Django和数据信息驾设到云端既可以真正实现远程获取数据以及控制传感器
涉及:
linux下的Python串口编程、mqtt编程、网络udp编程、数据库编程
Django下的网页实时获取数据库信息
1、工具
(1)操作系统:linux乌班图16.04、Windows10
(2)软件工具:
仿真工具:Proteus 8 Professional
虚拟串口工具:vspdpro.exe()
TCP接收工具:通讯猫(TCP接收,也可以写代码代替)
mqtt工具:MQTTBox(可以写代码代替)
2、准备工作
(1)搭建一个本地的 mqtt代理服务器:mosquitto-1.4.5保持开启状态
(2)搭建一个云mysql数据库
(3)将虚拟串口保持开启
3、功能实现流程
4、实现效果
(1)先将仿真启动主要体现功能为:从模拟传感器DHT11获取数据和发送数据
控制模拟传感器Motor
(2)运行程序:串口接收到的数据并传送给udp客服端(可以从通讯猫接收)且保存在数据库
(3)由Django做后端的最简单的网页页面读取数据:(这里的数据由于数据表改动导致的表格和原本不一样,基本形式一样)
5、Djanggo代码
(1)数据模型(根据获取到的数据去变化建表)
from django.db import models
# 1.创建模型类
class wenshiduInfo(models.Model):
# 2.定义字段 属性
id = models.CharField(primary_key=True, max_length=20, default="NULL")
createtime = models.CharField(max_length=50, default="NULL")
TempH = models.CharField(max_length=10, default="NULL")
class Meta:
verbose_name = '数据'
verbose_name_plural = verbose_name
# 魔法函数
def __str__(self):
return self.id
(2)路由
from django.urls import path
from . import views
urlpatterns = [
path('', views.homepage)
]
(3)视图接口
from django.shortcuts import render
from .models import wenshiduInfo
# Create your views here.
def homepage(request):
wenshidu = wenshiduInfo.objects.all()
context = {
'wenshidu':wenshidu
}
return render(request,'cjb/index.html',context)
# 3.终端操作 数据迁移
(4)网页模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>温湿度显示页面</title>
</head>
<body>
<table border="1" cellpadding="0" width="600px" align="center" >
<thead>
<tr align="center">
<th>编号</th>
<th>创建时间</th>
<th>温湿度数据</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for i in wenshidu %}
<tr align="center">
<td>{{i.id}}</td>
<td>{{i.createtime}}</td>
<td>{{i.TempH}}</td>
<td>
<a href ="#">编辑</a>
<a href ="#">删除</a>
</td>
</tr >
{% endfor %}
</tbody>
</table>
</body>
</html>
6、Python实现代码(还未面向对象封装):
(1)串口接收到的数据传送给且保存在数据库
import serial
import datetime
import socket
from pymysql import *
def main():
ser_port = "/dev/ttyS1" # 端口
ser_baudrate = 9600 # 设置波特率(这里使用的是stc89c52)
ser = serial.Serial(ser_port, ser_baudrate, timeout=65)
while True:
#data = ser.readline() #读串口数据
tem = ser.readline().decode('utf-8') #读温度数据
hum = ser.readline().decode('utf-8') #读湿度数据
# 获取当前时间
curr_time = datetime.datetime.now()
time_str = datetime.datetime.strftime(curr_time,'%Y-%m-%d %H:%M:%S')
data = "读取温度:"+ tem +"读取湿度:"+ hum +"创建时间:"+time_str
print(data)
conn = connect(host='localhost',port=3306,database='cjb',user='root',password='mysql',charset='utf8')
cs1 = conn.cursor()
#将数据存储进入数据库
cs1.execute('insert into cjb_wenshidu(createtime,name,data) values("%s","温度","%s")'%(time_str,tem))
cs1.execute('insert into cjb_wenshidu(createtime,name,data) values("%s","湿度","%s")'%(time_str,hum))
# 提交之前的操作,如果之前已经之执行过多次的execute,那么就都进行提交
conn.commit()
# 创建一个udp套接字
udp_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udp_socket.sendto(data.encode("utf-8"),("127.0.0.1",7690))
cs1.close()
conn.close()
ser.close() #关闭串口
udp_socket.close()
if __name__ == '__main__':
main()
(2)串口通信发送数据控制舵机
import serial
def main():
ser_port = "/dev/ttyS1" # 端口
ser_baudrate = 9600 # 设置波特率
ser = serial.Serial(ser_port, ser_baudrate, timeout=65)
ser.flushInput() # 清空缓冲区域
print("------发送指令1舵机转;0舵机停止------")
while True:
data = input("请发送指令:")
ser.write(data.encode("utf-8"))
ser.close() #关闭串口
if __name__ == '__main__':
main()
(3)mqtt发布消息.py
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
"""
flags是一个包含代理回复的标志的字典;
rc的值决定了连接成功或者不成功:0:连接成功;
"""
if rc == 0:
print("连接成功" )
else:
print("连接失败" )
def on_message(client, userdata, msg):
"""
当收到关于客户订阅的主题的消息时调用。
msgessage是一个描述所有消息参数的MQTTMessage。
"""
print("主题"+msg.topic + "获得的数据:" + str(msg.payload))
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect('broker.hivemq.com', 1883, 600) # 600为keepalive的时间间隔
pub = input("请输入要发布的主题:")
while True:
#发布主题用来控制舵机的轮转
payload = input("请输入要发布的消息:")
client.publish(pub, payload.encode("utf-8"), qos=0)
(4)mqtt订阅消息利用线程的方式将接受到的消息传给串口(还需要改进,接收到的订阅消息同步串口未成功)
import paho.mqtt.client as mqtt
from multiprocessing import Process
import datetime
import serial
#写数据到串口
def write_message(msg):
ser_port = "/dev/ttyS1" # 端口
ser_baudrate = 9600 # 设置波特率
ser = serial.Serial(ser_port, ser_baudrate, timeout=65)
ser.flushInput() # 清空缓冲区域
#data = msg.payload.decode("utf-8")
#ser.write(msg.payload.decode("utf-8"))
data = "1"
ser.write(data.encode("utf-8"))
ser.close() #关闭串口
def on_connect(client, userdata, flags, rc):
"""
flags是一个包含代理回复的标志的字典;
rc的值决定了连接成功或者不成功:0:连接成功;
"""
if rc == 0:
print("连接成功" )
else:
print("连接失败" )
def on_message(client, userdata, msg):
"""
当收到关于客户订阅的主题的消息时调用。
msgessage是一个描述所有消息参数的MQTTMessage。
"""
# 获取当前时间
curr_time = datetime.datetime.now()
time_str = datetime.datetime.strftime(curr_time,'%Y-%m-%d %H:%M:%S')
print("主题"+msg.topic + "获得的数据:" + str(msg.payload.decode('utf-8')) + "创建时间:"+time_str)
# 消息处理开启多进程
p = Process(target=write_message, args=(msg.payload.decode("utf-8")))
p.start()
def on_disconnect(client, userdata, rc):
pass
client = mqtt.Client()
client.on_disconnect = on_disconnect
client.connect('broker.hivemq.com', 1883, 600) # 600为与代理通信之间允许的最长时间段
client.loop_start() # 保持连接
#订阅温度湿度主题来收集温湿度数据
#sub = input("请输入要订阅的主题:")
client.subscribe("cjb", qos=0)
client.on_connect = on_connect
client.on_message = on_message
while True:
pass
(5)udp客服端
import socket
def main():
#1.创建套接字
udp_socket=socket.socket (socket.AF_INET,socket.SOCK_DGRAM)
#2.绑定一个本地信息
local_addr=("",7690)
udp_socket.bind(local_addr) #必须绑定自己电脑的ip和端口,‘‘表示默认自己电脑ip
while True:
#3.接收数据
recv_data=udp_socket.recvfrom(1024)
#4.打印数据
#因为接收的数据是以(接收的数据,(ip,port))形式
recv_msg=recv_data[0]
send_addr=recv_data[1]
send_ip=send_addr[0]
send_port=send_addr[1]
print("来自(ip地址%s,端口号%s)的数据:"%(send_ip,send_port))
print(recv_msg.decode("utf-8"))
#5.关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
7、仿真代码:
#include <DHTxx.h>
#define PUBLISH_DELAY 5000
DHTXX io_HTS1 = DHTXX (8, 11);
long previousMillis;
//dc
int Motor1 = 7;
int Motor2 = 6;
int Motor3 = 5;
int Motor4 = 4;
void setup() {
// setup serial communication
Serial.begin(9600);
while(!Serial) {};
//Serial.println(F("lab12"));
//Serial.println();
// setup DHT sensor
io_HTS1.begin();
//Serial.println();
//Serial.println(F("Ready!"));
previousMillis = millis();
//dc
pinMode(Motor1, OUTPUT);
pinMode(Motor2, OUTPUT);
pinMode(Motor3, OUTPUT);
pinMode(Motor4, OUTPUT);
digitalWrite(Motor1, HIGH);
digitalWrite(Motor2, HIGH);
digitalWrite(Motor3, HIGH);
digitalWrite(Motor4, HIGH);
}
void loop() {
// it's time to send new data?
if(millis() - previousMillis > PUBLISH_DELAY) {
sendData();
previousMillis = millis();
}
//readSerial
readData();
}
void readData()
{
char val = Serial.read();
if(val == '1')
{
//Serial.println(F("ON message received, turning relay ON"));
digitalWrite(Motor2, LOW);
digitalWrite(Motor1, HIGH);
//Serial.println(F("First Motor is moving in Clockwise Direction."));
}
if(val == '0')
{
//Serial.println(F("OFF message received, turning relay OFF"));
digitalWrite(Motor1, LOW);
digitalWrite(Motor2, LOW);
// Serial.println(F("First Motor is Stopped"));
}
}
void sendData() {
char msgBuffer[50];
float var_Humidity=io_HTS1.readHumidity();
float var_tCelsius=io_HTS1.readTemperature(0);
float var_tFarhenheit=io_HTS1.readTemperature(1);
Serial.println(dtostrf(var_tCelsius, 6, 0, msgBuffer));
Serial.println(dtostrf(var_Humidity, 6, 0, msgBuffer));
}