描述
我制作了 2 种不同的示波器,这些都在这个平台上有特色。现在我想到了双通道示波器。这个有主要的微控制器作为 Arduino 和1.3" OLED 显示器。这次我还有电池操作选项和板载充电电路。您可以先在面包板上制作它,然后使用下面给出的 PCB 布局。非常感谢 JLCPCB赞助这个双通道 Arduino 示波器项目。
这不仅是范围,还有 DDS_PWM(具有 8 种不同波形的函数发生器)、脉冲发生器和频率计数器的一些额外功能。我在日语网页上找到了这个项目,但所有的解释都在这里给你们看。
特征:
最大实时采样率为 17.2ksps(2 个通道)和 307ksps(一个通道)。单通道最大等效时间采样率为 16Msps。
单通道-30Khz带宽
屏幕 - 伏特/格和时间/格
占空比监控
小型 1.3 英寸 I2C
交流/直流测量选项
模式改变,保持状态功能
双通道切换模式
脉冲发生器选项
DDS_PWM波形发生器
频率计数器
低电池消耗
便携式和袖珍型
重要的提示:
该项目仅用于教育目的,展示了 16Mhz 8 位微控制器板的功能。此 MCU 可支持 50KHz 以下的频率,因此不适用于商业和专业用途。这样,该项目也可以为我命名为 POOR MAN OSCILLOSCOPE。我还发现这对下面与音频相关的项目很有帮助。
展示:
1.3寸OLED显示屏带I2C功能,有SSD1306和SH1106两种不同型号,可根据需要改码。我们必须取消注释我们在这个项目中使用的是哪个版本的 LCD。并且屏幕能够在两个通道中用占空比和频率来表示波的性质。
使用的组件:
阿杜诺纳米
1M电阻
10k电阻
1.3英寸OLED显示屏
100nF 电容
4个触觉按钮
5v电源
电路图:
与往常一样,这是图示电路,我将电路最小化为一个通道的操作。如果您想使用两个通道,只需按照下面给出的主电路图进行操作即可。
非常感谢“ Cirkit designer ”软件,证明它是一个以图形格式呈现电路和布线的好工具。对于新手或学生来说,这将是一种更容易理解的方法。
目前,cirkit designer 对所有人免费提供(从此处下载),因此没有理由不利用此优惠。作为回顾,我发现这对我的项目非常有帮助。该软件的一些特殊功能是:代码编译、BOM 管理器、面包板和自定义组件创建。
电路图:
1 / 2 •双通道简化示意图
电路说明:
Pin usage A0 oscilloscope probe ch1 A1 oscilloscope probe ch2 A4 I2C SDA A5 I2C SCL D3 PWM output for trigger level D4 Up button D6 trigger level input D8 Down button D9 Right button D10 Pulse generator output D11 PWM DDS output D12 Left button
这种小型示波器可以使用 5volts @200mA 供电。您可以在上面看到两个不同的电路,两者都很好,但我制作的电路经过简化并且在所有情况下都最有用。您可以根据自己的情况修改电路。
看看示波器中那些漂亮的波浪就知道了。
1 / 4 •方形 380HZ
这次电路还具有外部频率测量和 PWM、DDS 脉冲输出选项,具有 2 个通道。4 触觉按钮在下拉时触发。所有的电阻都是为了适当的baising。作为一项改进,您可以制作电路的 PCB 布局,并以 2 美元的价格从JLCPCB订购它们。顺便说一句,如果你想使用我的,下面给出你可以下载。使用我的链接注册将为您提供 PCB 优惠券作为原型 SMT 服务的奖励。为什么不免费使用价值 27 美元的优惠券。
探索菜单:
完整菜单比以前的 arduscope 项目有更多的选项。然而,我没有得到大屏幕。可能下次我会使用 TFT 和 mega2560 板构建一个。
通道切换选项:
不使用时关闭第二个通道,因为这也会增加采样率。
电压读数:
还将显示信号的最大值和最小值,称为幅度。
电压/分区:
时间/部门:
代码:
我得到了十六进制格式的代码,但确认在 INO Arduino 文件中有一些支持文件。我得到了这些支持文件的 Arduino INO 代码。一旦我得到完整的代码,我会分享,你会自己改变它。HEX 文件仍然正常工作。如果您不知道如何使用 HEX文件对 Arduino 进行编程,请查看本教程。从这里下载这个项目的代码。
频率计数器:
//int dataMin; // buffer minimum value (smallest=0) //int dataMax; // maximum value (largest=1023) //int dataAve; // 10 x average value (use 10x value to keep accuracy. so, max=10230) //int dataRms; // 10x rms. value void dataAnalize() { // 波形の分析 get various information from wave form long d; long sum = 0; byte *waveBuff = data[sample+0]; // search max and min value dataMin = 255; // min value initialize to big number dataMax = 0; // max value initialize to small number for (int i = 0; i < SAMPLES; i++) { // serach max min value d = waveBuff[i]; sum = sum + d; if (d < dataMin) { // update min dataMin = d; } if (d > dataMax) { // updata max dataMax = d; } } // calculate average dataAve = (10 * sum + (SAMPLES / 2)) / SAMPLES; // Average value calculation (calculated by 10 times to improve accuracy) // 実効値の計算 rms value calc. // sum = 0; // for (int i = 0; i < SAMPLES; i++) { // バッファ全体に対し to all buffer // d = waveBuff[i] - (dataAve + 5) / 10; // オーバーフロー防止のため生の値で計算(10倍しない) // sum += d * d; // 二乗和を積分 // } // dataRms = sqrt(sum / SAMPLES); // 実効値の10倍の値 get rms value } void freqDuty() { // 周波数とデューティ比を求める detect frequency and duty cycle value from waveform data int swingCenter; // center of wave (half of p-p) float p0 = 0; // 1-st posi edge float p1 = 0; // total length of cycles float p2 = 0; // total length of pulse high time float pFine = 0; // fine position (0-1.0) float lastPosiEdge; // last positive edge position float pPeriod; // pulse period float pWidth; // pulse width int p1Count = 0; // wave cycle count int p2Count = 0; // High time count boolean a0Detected = false; // boolean b0Detected = false; boolean posiSerch = true; // true when serching posi edge swingCenter = (3 * (dataMin + dataMax)) / 2; // calculate wave center value for (int i = 1; i < SAMPLES - 2; i++) { // scan all over the buffer if (posiSerch == true) { // posi slope (frequency serch) if ((sum3(i) <= swingCenter) && (sum3(i + 1) > swingCenter)) { // if across the center when rising (+-3data used to eliminate noize) pFine = (float)(swingCenter - sum3(i)) / ((swingCenter - sum3(i)) + (sum3(i + 1) - swingCenter) ); // fine cross point calc. if (a0Detected == false) { // if 1-st cross a0Detected = true; // set find flag p0 = i + pFine; // save this position as startposition } else { p1 = i + pFine - p0; // record length (length of n*cycle time) p1Count++; } lastPosiEdge = i + pFine; // record location for Pw calcration posiSerch = false; } } else { // nega slope serch (duration serch) if ((sum3(i) >= swingCenter) && (sum3(i + 1) < swingCenter)) { // if across the center when falling (+-3data used to eliminate noize) pFine = (float)(sum3(i) - swingCenter) / ((sum3(i) - swingCenter) + (swingCenter - sum3(i + 1)) ); if (a0Detected == true) { p2 = p2 + (i + pFine - lastPosiEdge); // calucurate pulse width and accumurate it p2Count++; } posiSerch = true; }
脉冲发生器:
void dataAnalize() { // 波形の分析 get various information from wave form long d; long sum = 0; byte *waveBuff = data[sample+0]; // search max and min value dataMin = 255; // min value initialize to big number dataMax = 0; // max value initialize to small number for (int i = 0; i < SAMPLES; i++) { // serach max min value d = waveBuff[i]; sum = sum + d; if (d < dataMin) { // update min dataMin = d; } if (d > dataMax) { // updata max dataMax = d; } } // calculate average dataAve = (10 * sum + (SAMPLES / 2)) / SAMPLES; // Average value calculation (calculated by 10 times to improve accuracy) // 実効値の計算 rms value calc. // sum = 0; // for (int i = 0; i < SAMPLES; i++) { // バッファ全体に対し to all buffer // d = waveBuff[i] - (dataAve + 5) / 10; // オーバーフロー防止のため生の値で計算(10倍しない) // sum += d * d; // 二乗和を積分 // } // dataRms = sqrt(sum / SAMPLES); // 実効値の10倍の値 get rms value } void freqDuty() { // 周波数とデューティ比を求める detect frequency and duty cycle value from waveform data int swingCenter; // center of wave (half of p-p) float p0 = 0; // 1-st posi edge float p1 = 0; // total length of cycles float p2 = 0; // total length of pulse high time float pFine = 0; // fine position (0-1.0) float lastPosiEdge; // last positive edge position float pPeriod; // pulse period float pWidth; // pulse width int p1Count = 0; // wave cycle count int p2Count = 0; // High time count boolean a0Detected = false; // boolean b0Detected = false; boolean posiSerch = true; // true when serching posi edge swingCenter = (3 * (dataMin + dataMax)) / 2; // calculate wave center value for (int i = 1; i < SAMPLES - 2; i++) { // scan all over the buffer if (posiSerch == true) { // posi slope (frequency serch) if ((sum3(i) <= swingCenter) && (sum3(i + 1) > swingCenter)) { // if across the center when rising (+-3data used to eliminate noize) pFine = (float)(swingCenter - sum3(i)) / ((swingCenter - sum3(i)) + (sum3(i + 1) - swingCenter) ); // fine cross point calc. if (a0Detected == false) { // if 1-st cross a0Detected = true; // set find flag p0 = i + pFine; // save this position as startposition } else { p1 = i + pFine - p0; // record length (length of n*cycle time) p1Count++; } lastPosiEdge = i + pFine; // record location for Pw calcration posiSerch = false; } } else { // nega slope serch (duration serch) if ((sum3(i) >= swingCenter) && (sum3(i + 1) < swingCenter)) { // if across the center when falling (+-3data used to eliminate noize) pFine = (float)(sum3(i) - swingCenter) / ((sum3(i) - swingCenter) + (swingCenter - sum3(i + 1)) ); if (a0Detected == true) { p2 = p2 + (i + pFine - lastPosiEdge); // calucurate pulse width and accumurate it p2Count++; } posiSerch = true; } }
从这里下载代码文件,目前为十六进制格式。要在 Arduino 中上传十六进制文件,请参阅我们之前的教程。
电路板文件:
感谢积联电路和EasyEda赞助并生成了如此优质的PCB 原型。订购过程也很简单,如下所示。
下载我的 Gerber 文件,转到 JLCPCB,然后选择厚度颜色参数,只需 2 美元即可订购 5 个 pcb。
测量:
这里的大问题是获得正确的频率,正如我所说,最好先使用音频频率。所以我将它与在线音调生成器工具配对。这将使我们能够检查精度以及不同的波形。
此处显示了不同频率下的正弦波测量值。
1 / 2
测量 2:
1 / 2
测量3:
1 / 2
观察:
回到最大频率和振幅,它能够以 5Khz 的最大频率测量高达 50v 的电压。是的,波在这个频率以上是扭曲的。
下一个更新:
下次我们将返回一个更大的微控制器 (2560),也许还有一个 TFT 屏幕。顺便说一句,这是我上一个 Arduscope 项目的链接,该项目支持高达 10khz 频率的 1 通道和Raspberry pi Pico 项目,模拟信号带宽为 200Khz。再次感谢 JLCPCB。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !