下面是使用Python串口实时显示数据并绘图的完整攻略。
确定开发环境和需要的第三方库
- Python环境(推荐Python 3.x版本)。
- pyserial(Python的串口通讯库,用于与串口进行通讯)。
- matplotlib(Python的可视化库,用于数据的绘图)。
- numpy(Python的科学计算库,用于处理数据和计算)。
打开串口通讯
import serial
ser = serial.Serial('COM5', 9600) # 使用COM5的串口,波特率9600
在这段代码中,我们使用了Python的serial库,初始化了一个串口对象ser
。一定要注意串口号和波特率需要根据实际情况进行修改。
实时读取串口数据
while True:
data = ser.readline().decode('utf-8') # 读取串口数据并解码
print(data.strip()) # 输出数据
在这段代码中,我们使用了一个死循环不断读取串口数据,并使用Python内置print()
函数将数据输出。strip()
函数用于去除数据首尾的空格和换行符。
绘制实时数据图像
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
line, = ax.plot(np.random.randn(100)) # 随机初始化一条线
ax.set_ylim(-5, 5) # 设置Y轴范围
while True:
data = ser.readline().decode('utf-8')
print(data.strip())
y = float(data.strip()) # 将读取到的数据转换为浮点数
line.set_ydata(np.append(line.get_ydata(), y)) # 将新数据添加到线的数据中
ax.relim() # 重新计算坐标系的范围
ax.autoscale_view(True, True, True) # 自适应坐标系范围
plt.pause(0.001) # 暂停0.001秒,使图像更新
在这段代码中,我们使用了Python的matplotlib库进行数据可视化,并且使用了numpy
库处理数据。我们首先创建了一个窗口,初始化了一条虚拟的直线。在死循环中,我们读取串口数据,并将其转换为浮点数。然后将它添加到线的数据中,并且使用自适应的方式更新坐标系和图像。最后使用plt.pause()
函数暂停0.001秒以便图像可以更新。
示例说明
示例1:读取温湿度传感器实时数据并绘制温度曲线
我们使用DHT11温湿度传感器,将数据通过串口发送到电脑。下面给出Arduino程序示例:
#include <DHT.h>
#define DHTPIN 2 // DHT11数据引脚
#define DHTTYPE DHT11 // DHT11传感器类型
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(9600); // 设置串口波特率
dht.begin(); // 启动DHT传感器
}
void loop() {
delay(2000); // 延时2秒
float temperature = dht.readTemperature(); // 读取温度
float humidity = dht.readHumidity(); // 读取湿度
Serial.print(temperature); // 输出温度
Serial.print(","); // 输出逗号分隔符
Serial.println(humidity); // 输出湿度
}
在电脑端,如果已经安装好了Python和pyserial、matplotlib、numpy库,我们只需要自行编写一个Python程序即可。这里就不需要额外安装了。
import serial
import matplotlib.pyplot as plt
import numpy as np
ser = serial.Serial('COM5', 9600) # 使用COM5的串口,波特率9600
fig, ax = plt.subplots()
line, = ax.plot(np.random.randn(100)) # 随机初始化一条线
ax.set_ylim(0, 100) # 设置Y轴范围
while True:
data = ser.readline().decode('utf-8')
print(data.strip())
temperature, humidity = map(float, data.strip().split(',')) # 将读取到的数据转换为浮点数
line.set_ydata(np.append(line.get_ydata(), temperature)) # 将新数据添加到线的数据中
ax.relim() # 重新计算坐标系的范围
ax.autoscale_view(True, True, True) # 自适应坐标系范围
plt.pause(0.001) # 暂停0.001秒,使图像更新
这里,我们使用matplotlib库实时绘制温度曲线。图像将实时更新,直到我们按下Ctrl-C终止程序。
示例2:使用硬件加速计实时绘制加速度曲线
我们使用Arduino板子并连接ADXL345三轴加速计,再将数据通过串口发送到电脑。Arduino接线示例:
- ADXL345 SDA引脚连接到Arduino UNO的A4引脚
- ADXL345 SCL引脚连接到Arduino UNO的A5引脚
- ADXL345 GND引脚连接到Arduino UNO的GND引脚
- ADXL345 VCC引脚连接到Arduino UNO的5V引脚
下面给出Arduino程序示例:
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);
void displaySensorDetails(void)
{
sensor_t sensor;
accel.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" m/s^2");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" m/s^2");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" m/s^2");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
void displayDataRate(void)
{
Serial.print("Data Rate: ");
switch( accel.getDataRate() )
{
case ADXL345_DATARATE_3200_HZ:
Serial.print("3200 ");
break;
case ADXL345_DATARATE_1600_HZ:
Serial.print("1600 ");
break;
case ADXL345_DATARATE_800_HZ:
Serial.print("800 ");
break;
case ADXL345_DATARATE_400_HZ:
Serial.print("400 ");
break;
case ADXL345_DATARATE_200_HZ:
Serial.print("200 ");
break;
case ADXL345_DATARATE_100_HZ:
Serial.print("100 ");
break;
case ADXL345_DATARATE_50_HZ:
Serial.print("50 ");
break;
case ADXL345_DATARATE_25_HZ:
Serial.print("25 ");
break;
case ADXL345_DATARATE_12_5_HZ:
Serial.print("12.5 ");
break;
case ADXL345_DATARATE_6_25HZ:
Serial.print("6.25 ");
break;
case ADXL345_DATARATE_3_13_HZ:
Serial.print("3.13 ");
break;
case ADXL345_DATARATE_1_56_HZ:
Serial.print("1.56 ");
break;
case ADXL345_DATARATE_0_78_HZ:
Serial.print("0.78 ");
break;
case ADXL345_DATARATE_0_39_HZ:
Serial.print("0.39 ");
break;
case ADXL345_DATARATE_0_20_HZ:
Serial.print("0.20 ");
break;
case ADXL345_DATARATE_0_10_HZ:
Serial.print("0.10 ");
break;
default:
Serial.print("???? ");
break;
}
Serial.println(" Hz");
}
void setup(void)
{
Serial.begin(9600);
displaySensorDetails();
accel.setDataRate(ADXL345_DATARATE_100_HZ);
displayDataRate();
delay(500);
}
void loop(void)
{
sensors_event_t event;
accel.getEvent(&event);
Serial.print(event.acceleration.x);
Serial.print(",");
Serial.print(event.acceleration.y);
Serial.print(",");
Serial.println(event.acceleration.z);
delay(100);
}
在电脑端,将串口连接到电脑,并使用PySerial库读取数据。这里,我们将使用pyserial
库实时绘制加速度曲线。
import serial
import matplotlib.pyplot as plt
import numpy as np
ser = serial.Serial('COM5', 9600) # 使用COM5的串口,波特率9600
fig, ax = plt.subplots(3, 1)
lines = [ax[i].plot(np.random.randn(100))[0] for i in range(3)] # 随机初始化三条线
while True:
data = ser.readline().decode('utf-8')
print(data.strip())
x, y, z = map(float, data.strip().split(',')) # 将读取到的数据转换为浮点数
for i, line in enumerate(lines):
line.set_ydata(np.append(line.get_ydata(), [x, y, z][i])) # 将新数据添加到线的数据中
ax[i].relim() # 重新计算坐标系的范围
ax[i].autoscale_view(True, True, True) # 自适应坐标系范围
plt.pause(0.001) # 暂停0.001秒,使图像更新
这里,我们使用matplotlib库实时绘制加速度曲线,同时绘制三个方向的曲线。图像将实时更新,直到我们按下Ctrl-C终止程序。
以上就是使用Python串口实时显示数据并绘图的攻略,希望能对您有所帮助。