回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

Beetle 树莓派RP2350:简易示波器 简单

头像 豆爸 2025.05.23 23 0

电信号的波形进行图形化显示。借助示波器,技术人员可以对信号的频率、幅度、相位等参数展开分析,进而对电路的工作状态进行评估和调试。

本项目旨在利用 Beetle RP2350 开发板设计一款简易示波器,来实现对电压的测量与波形显示。

 

712f68997dd87b43a97aeba8d087004.jpg

 

 

材料清单

硬件介绍

1、Beetle RP2350 开发板

Beetle RP2350 是一款基于RP2350芯片设计的高性能迷你体积的开发板,有2路ADC,分别是A0对应IO26,A1对应IO27。


2、0.96 OLED屏

1747961033867.png

0.96寸OLED显示模块采用SSD1306驱动芯片,有128x64个自发光的白色像素点,采用I2C通信。

连接电路

未标题-1.jpg

程序编写

1、 安装Beetle RP2350 开发板

步骤 1:添加开发板管理器网址

打开 Arduino IDE 后,点击菜单栏中的 文件 -> 首选项。

在弹出的 首选项 窗口中,找到 附加开发板管理器网址 输入框。

输入 Beetle RP2350 开发板的支持包链接。通常可以在开发板的官方文档或者社区中找到对应的链接。对于 RP2350 开发板,一般使用的链接是 https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json。

点击 确定 保存设置。

image-20250516074502812.png

步骤 2:安装 Beetle RP2350 开发板支持

点击菜单栏中的 工具 -> 开发板 -> 开发板管理器,在开发板管理器窗口中,等待索引更新完成。

在搜索框中输入 RP2350。

在搜索结果中找到 Raspberry Pi Pico/RP2040/RP2350 并点击 安装 按钮。

image-20250516073904537.png

等待安装过程完成,这可能需要一些时间,具体取决于你的网络速度。

步骤 3:选择 Generic RP2350 开发板

安装完成后,点击菜单栏中的 工具 -> 开发板,在开发板列表中选择 Generic RP2350。

4E885EEB-63FA-4447-A72E-A208DD093520.png

步骤 4:选择端口

将 Beetle RP2350 开发板通过 USB 线连接到计算机。点击菜单栏中的 工具 -> 端口,选择与开发板对应的端口。

完成以上步骤后,你就可以在 Arduino IDE 中使用 Beetle RP2350 开发板进行编程和开发了。你可以编写代码并上传到开发板上运行。

2、安装 Adafruit GFX Library库

在库管理器的搜索框中输入 Adafruit GFX Library,然后在搜索结果中找到对应的库。点击 安装 按钮,等待安装完成。这个库是 Adafruit 图形库,提供了基本的图形绘制功能,许多 Adafruit 的显示设备都会依赖这个库。

image-20250516072303169.png

3、安装 Adafruit SSD1306库

在库管理器的搜索框中输入 Adafruit SSD1306,在搜索结果中找到该库后,点击 安装 按钮进行安装。这个库专门用于驱动基于 SSD1306 芯片的 OLED 显示屏,项目中使用的 0.96 寸 OLED 显示屏正是基于此芯片。

image-20250516072543257.png

主要程序代码及说明

代码
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// OLED屏幕定义
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// 引脚定义
#define ADC_PIN A0
#define SDA_PIN 4
#define SCL_PIN 5

// 存储电压值的数组
float voltage_values[SCREEN_WIDTH] = {0};

// 波形偏移
const int WAVEFORM_OFFSET = 10;

// ADC校准参数
const float ADC_MAX_VALUE = 4095.0;
float ADC_ZERO_OFFSET = 0;
const float ZERO_DISPLAY_THRESHOLD = 0.005;      // 低于此值显示为0V
const float ADC_CALIBRATION_FACTOR = 4.141742;   // 校准因子

// 卡尔曼滤波参数
float kalman_x = 0;                              // 状态估计
float kalman_P = 1.0;                            // 估计误差协方差
const float kalman_Q = 0.001;                    // 过程噪声方差
const float kalman_R = 0.01;                     // 测量噪声方差

void setup() {
  Wire.setSDA(SDA_PIN);
  Wire.setSCL(SCL_PIN);
  Wire.begin();
  
  Serial.begin(115200);
  
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306初始化失败"));
    for(;;);
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("精密ADC校准中...");
  display.display();
  
  // 初始校准
  calibrate_adc_zero();
  
  // 微调零点补偿
  ADC_ZERO_OFFSET += 24;  // 补偿约0.02V的残余电压
  
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("零点校准: ");
  display.println(ADC_ZERO_OFFSET);
  display.println("开始监测...");
  display.display();
  delay(1000);
}

// 初始零点校准
void calibrate_adc_zero() {
  const int calibration_samples = 500;
  unsigned long sum = 0;
  
  for (int i = 0; i < calibration_samples; i++) {
    sum += analogRead(ADC_PIN);
    delay(1);
  }
  
  ADC_ZERO_OFFSET = sum / (float)calibration_samples;
  Serial.print("零点校准值: ");
  Serial.println(ADC_ZERO_OFFSET);
}

// 应用零点校准
int apply_zero_calibration(int raw_value) {
  int calibrated = raw_value - ADC_ZERO_OFFSET;
  return max(0, calibrated);
}

// 卡尔曼滤波
float kalman_filter(float measurement) {
  // 预测
  float x_pred = kalman_x;
  float P_pred = kalman_P + kalman_Q;
  
  // 更新
  float K = P_pred / (P_pred + kalman_R);  // 卡尔曼增益
  kalman_x = x_pred + K * (measurement - x_pred);
  kalman_P = (1 - K) * P_pred;
  
  return kalman_x;
}

// 绘制电压曲线
void draw_voltage_curve(float values[]) {
  display.clearDisplay();
  
  for(int x = 0; x < SCREEN_WIDTH - 1; x++) {
    int y1 = SCREEN_HEIGHT - 1 - (int)(values[x] * (SCREEN_HEIGHT - WAVEFORM_OFFSET - 1));
    int y2 = SCREEN_HEIGHT - 1 - (int)(values[x + 1] * (SCREEN_HEIGHT - WAVEFORM_OFFSET - 1));
    display.drawLine(x, y1, x + 1, y2, SSD1306_WHITE);
  }

  float voltage = values[SCREEN_WIDTH - 1] * 3.3;
  
  // 低于阈值时强制显示为0
  if (voltage < ZERO_DISPLAY_THRESHOLD) {
    voltage = 0.0;
  }
  
  display.setCursor(0, 0);
  display.print("V: ");
  display.print(voltage, 3);  // 显示3位小数
  display.print("V  ");
  
  display.display();
}

void loop() {
  // 读取原始ADC值
  int raw_adc = analogRead(ADC_PIN);
  
  // 应用零点校准
  int calibrated_adc = apply_zero_calibration(raw_adc);
  
  // 应用卡尔曼滤波
  float filtered_adc = kalman_filter(calibrated_adc);
  
  // 计算最终电压
  float voltage = (filtered_adc / ADC_MAX_VALUE) * 3.3 * ADC_CALIBRATION_FACTOR;
  
  // 串口打印
  Serial.print("原始ADC值: ");
  Serial.print(raw_adc);
  Serial.print("  零点校准后ADC值: ");
  Serial.print(calibrated_adc); 
  Serial.print("  卡尔曼滤波后ADC: ");
  Serial.print(filtered_adc);
  Serial.print("  计算最终电压: ");
  Serial.print(voltage, 4);  // 串口显示4位小数用于调试
  Serial.println("V");
  
  // 限制电压比例在0-1范围内
  float voltage_ratio = voltage / 3.3;
  voltage_ratio = constrain(voltage_ratio, 0.0, 1.0);

  // 更新电压值数组
  memmove(voltage_values, voltage_values + 1, (SCREEN_WIDTH - 1) * sizeof(float));
  voltage_values[SCREEN_WIDTH - 1] = voltage_ratio;

  // 绘制电压曲线
  draw_voltage_curve(voltage_values);

  delay(50);  // 提高采样率
}

评论

user-avatar