使用Python串口实时显示数据并绘图的例子

  • Post category:Python

下面是使用Python串口实时显示数据并绘图的完整攻略。

确定开发环境和需要的第三方库

  1. Python环境(推荐Python 3.x版本)。
  2. pyserial(Python的串口通讯库,用于与串口进行通讯)。
  3. matplotlib(Python的可视化库,用于数据的绘图)。
  4. 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串口实时显示数据并绘图的攻略,希望能对您有所帮助。