先看看硬件,上图是两个零件。
波形发生器、蓝牙电压表各用一个ESP32(注意不是ESP32-S2-S3-C3,因为 ESP32有两个DAC, ESP8266 和 ESP32-C3 没有。)。
用杜邦线连接各自的 GPIO25。
注意:上传程序时最好一个一个传,同时插上电脑的话注意分清楚串口号。
波形发生器
先对比下别人做的,没有 DAC 那是相当的麻烦,PWM模拟准不准先不说,还需要滤波的:
为什么要做这个波形发生器,因为下面的蓝牙电压表需要一个信号源。小变压器也可以作为信号源。
实测频率上限 “高达300Hz"(程序里注释掉延迟部分),你没看错,不是KHz,不是MHz。
我只需要50Hz,堪堪够用。更高频率需要另外想办法,或是降低输出品质 (slice 降低到 60 可以提高到1KHz,锯齿状的正弦波也是正弦波嘛)
虽然简单,还是需要对三角函数和 ADC DAC PWM 都有些了解才行。
这里有几个常识:
1. sin 函数值的范围是 +1 -1 , 但是 ESP32 的 ADC 只能采集 0 - 3.3v ,采集不到负值。
2. 于是 给 sin +1, 让其值在 0-2 之间,相当于示波器直流偏移,波形往上移动如下图。
3. ESP32 有两个真 8位 DAC ,输出值 0-255 , 所以 Sin() 值乘以125 在范围 0-250 。
超过“削顶失真”,太低则失去细节。
下图是该 波形发生器 接在 真示波器 上的照片:
一下程序是正弦波,需要其他的方波、锯齿波、三角波什么的也可以修改公式实现,用数组也行。
float Pi = 3.1415926; // 圆周率(Pi)是圆的周长与直径的比值,一般用希腊字母 π 表示
float f = 0; // 输出值
int step = 0; // 波形空循环变量
int slice = 360; // 粒度,一个周期分割为360度,减小此值可增加频率,但牺牲平滑度
void setup() {
}
void loop() {
f = 120*(sin( step * 2 * Pi/slice)+1); // 角度的大小有两种表示方法,即“角度制”和“弧度制”两种. sin() 默认使用弧度,一个周期为2π 。
dacWrite(25, f); // GPIO25 GPIO26 为内置 DAC ,其他GPIO 为PWM
step = step + 1 ; // 按 360度 循环
if ( step >= slice) step = 0; // 按 360度 循环
delayMicroseconds(35); // 微秒延时,越大频率越低 35 为 50Hz
}
蓝牙电压表
“蓝牙电压表” 来自开源软件 phyphox.org 。
分两部分:
手机APP:国内谷歌商店没戏,网页下载 apk 安装。
太老的手机平板可以安装 app,但提示不支持低功耗蓝牙,所以尽量用新一些的设备,至少 Android 4.3 以上。
Arduino:在线安装 phyphox BLE 库,直接写入库自带的例程即可使用(不用修改),相当方便。
电压表的输入为IO的输入范围0-3.3v ,测量高一些的电压使用对应的分压电路。
如有 1:100 的示波器探头,“蓝牙电压表” 在 电池供电 的情况下(为什么百度),应该可以直接测量交流电(尚未验证),看到50Hz半波。【注意安全,没经验人士须在专业电工指导下测量交流电 !】
这个是电压表,不太适合高频率,当示波器用还是需要另外接高速ADC。本次实验50Hz就好。测量些电池充放电曲线还是可以的。
蓝牙示波器 暂时没找到开源,网页版示波器也能打
Esp32_oscilloscopehttps://github.com/BojanJurca/Esp32_oscilloscope具体玩法需要仔细看其说明。
简单提示下:
1. 打包下载 github 里这堆文件,解压放在 Esp32_oscilloscope 目录里 (注意默认压缩包有后缀 -master,直接拖目录需要修改的)
2. 用 Arduino 打开 Esp32_oscilloscope\Esp32_oscilloscope.ino 。修改 wifi STA 参数后就可以上传,上传时注意开发板参数选FATFS,其他不用修改。
3. 然后串口可以看到 IP, 按说明用 FTP 上传几个文件(需要在 Esp32_oscilloscope目录打开CMD),然后可以任意浏览器输入 ip 就可以使用这个示波器了。
4. 该网页对手机优化比较好,电脑上看怪怪的。虽然是英文页面,浏览器不是可以自动翻译嘛。
5. 实测上面的50Hz正弦波可以稳定显示的。看设置有10KHz档,回头找信号源测试吧。
TFT 示波器
考虑到示波器这样的应用,有块TFT显示波形也是极好的,之前做过OLED的,实在太小,于是在基础平台(左)一条连接线就可以显示本文开始做的 50Hz正弦波(右),因为考虑了触发,还比较稳定。
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#define TFT_SCLK D4 // Clock out
#define TFT_MOSI D3 // Data out
#define TFT_RST D2
#define TFT_DC D1
#define TFT_CS D0
//______TFT_BL 不接
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
void setup(void) {
tft.initR(INITR_BLACKTAB);
tft.setRotation(1);
tft.fillScreen(ST7735_BLACK);
}
int i = 0;
int j = 0;
int t1 = 0;
int t2 = 0;
int n = 2;
int adc[1000];
void loop(void) {
t1 = analogRead(A0);
t2 = analogRead(A0);
while (((t2 > t1) and (t2 > 512)and(t2 < 520)) != 1){t1 = analogRead(A0);t2 = analogRead(A0);}
for ( i = 0 ; i < 320 ; i++){
adc[i] = int(analogRead(A0)/9);
//delayMicroseconds(40);
}
for ( i = 1 ; i < 160 ; i++){tft.drawLine(i-1,adc[n*(i-1)],i, adc[n*i], ST7735_GREEN);}
delay(200);
for ( i = 1 ; i < 160 ; i++){tft.drawLine(i-1,adc[n*(i-1)],i, adc[n*i], ST7735_BLACK);}
}
代码里三个 for 循环 其实功能上可以一个循环就实现,为什么要分开写呢 ?试试就知道了。
ESP8266只有1个A0,不能够实现双通道,后续改进迁移到ESP32-C3,这里实现基本波形显示就不再更新。