【Follow me第二季第2期】+ 基础任务 点阵LED+DAC正弦波+OPAMP+波形显示
[复制链接]
本帖最后由 cqut面码 于 2024-9-30 00:39 编辑
1、前言
前面学习了环境的搭建、LED的点亮翻转、以及串口的输出。接着就来学习基础任务里面的一些内容, 驱动12x8点阵LED和用DAC生成正弦波。
2、 驱动12x8点阵LED
先放官方的链接https://docs.arduino.cc/tutorials/uno-r4-wifi/led-matrix/,官方给出了详细的这个LED矩阵点亮的实现方式,我们可以通过官方的文档来进行学习,
并完成这个矩阵LED的实验,嵌入式就是得多看看官方资料,不要一个人闭门造车。快速实现了,再去了解原理,深入消化,才不会打击学习的积极性。
官方已经给出一个驱动点了这个矩阵LED库函数,我们只需要包含使用就好了。如下是输出一个爱心的框图,详细的各个功能都在代码中进行了注释说明
核心思想就是通过把自己要显示的LED矩阵相关的数据,直接写入就好,实际就是通过IO通过LED矩阵的亮灭。
画出一个心形的代码如下:
#include "Arduino_LED_Matrix.h" /*包含官方的驱动库*/
ArduinoLEDMatrix led_matrix; //实例化一个对象
/*串口初始化函数*/
void uart_init(uint32_t baud)
{
Serial.begin(baud);
}
/* 爱心的框图 */
byte frame[8][12] = {
{ 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
void setup() {
// put your setup code here, to run once:
pinMode(13, OUTPUT); /* 设置13引脚为输出模式 */
digitalWrite(13, HIGH); /* 默认输出为高*/
Serial.begin(115200);
led_matrix.begin(); //初始化启动这个对象
led_matrix.renderBitmap(frame, 8, 12); //把LED矩阵的数据写入
}
void loop() {
// put your main code here, to run repeatedly:
delay(500);
digitalWrite(13, !digitalRead(13)); /* 每500ms进行一次LED灯的翻转*/
}
实际效果如下:
3、 用DAC生成正弦波
Arduino UNO R4 WiFi 内置DAC(数模转换器),用于将数字信号转换为模拟信号。这里我们直接用DAC输出一个正弦波,然后用示波器去观察器输出的波形
先看原理图DAC的输出口是哪个,从原理图上可以看到,开发板上引出的DAC引脚为A0,等会我们直接用示波器测量A0即可。
然后,参考官网的代码 https://docs.arduino.cc/tutorials/uno-r4-wifi/dac/,完成DAC正弦波的输出,代码我们在前面的基础上继续完善,具体如下:
这里只是生成可一个50HZ的sin波形并没有在循环中去改变频率或者波形等其他进操作
#include "Arduino_LED_Matrix.h" /*包含官方的驱动库*/
#include "analogWave.h" // 包含波形输出的模拟文件
ArduinoLEDMatrix led_matrix; //实例化一个对象
analogWave wave(DAC); //实例化一个对象
/*串口初始化函数*/
void uart_init(uint32_t baud)
{
Serial.begin(baud);
}
/* 爱心的框图 */
byte frame[8][12] = {
{ 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
void setup() {
// put your setup code here, to run once:
pinMode(13, OUTPUT); /* 设置13引脚为输出模式 */
digitalWrite(13, HIGH); /* 默认输出为高*/
Serial.begin(115200);
led_matrix.begin(); //初始化启动这个对象
led_matrix.renderBitmap(frame, 8, 12); //把LED矩阵的数据写入
wave.sine(50); //产生一个50HZ的sin波形
}
void loop() {
// put your main code here, to run repeatedly:
delay(500);
digitalWrite(13, !digitalRead(13)); /* 每500ms进行一次LED灯的翻转*/
}
实际示波器测试的效果如下,可以看出最大值为4.6v,最小值为-13mv,频率为49.9HZ左右,波形确实比较难看,锯齿状态还是很严重的,按理说这个板子的12位的DAC性能应不止这样,
应该是内部封装的效果导致一个周期数据输出太少的原因,看来还是得上IDF编程才行。
另外还有一个问题就是,为啥最大值为4.6V,而不是5V,我怀疑是设计缺陷,DAC的参考电压不准,不是5V。时间原因就不去验证了
4、 使用OPAMP对上面的DAC信号放大
OPAMP 实际用处还是很大的,在性能要求不高的情况下,直接使用板载的OPAMP进行放大信号,可以节约成本,避免外部在接一个运放。
当然OPAMP还有一个作用就是做电压跟随器,电压跟随器具有高输入阻抗和低输出阻抗——这是它们缓冲作用的本质,它们增强信号,从而允许高阻抗源驱动低阻抗负载。
这里我们就只展示放大的作用。具官方文档可以参考学习https://docs.arduino.cc/tutorials/uno-r4-wifi/opamp
从前面的实验已经看出了,直接输出的波形已经幅度值已经达到了4.7V,这已经是DAC输出的最大值了。如果我们再在这个基础上去放大这个信号,无疑就会超过4.7V。
就会出现两种情况 1、会出现削波 2、可能损坏电路板。为了后续放大实验方便,我们限制一下幅度值,输出到最大值的1/4即可,便于后续放大波形:
代码很简单,实际就是在setup中多了一个对波形幅值的限制, wave.amplitude(0.25); //设置幅度值为4.7 的1/4
#include "Arduino_LED_Matrix.h" /*包含官方的驱动库*/
#include "analogWave.h" // 包含波形输出的模拟文件
ArduinoLEDMatrix led_matrix; //实例化一个对象
analogWave wave(DAC); //实例化一个对象
/*串口初始化函数*/
void uart_init(uint32_t baud)
{
Serial.begin(baud);
}
/* 爱心的框图 */
byte frame[8][12] = {
{ 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
void setup() {
// put your setup code here, to run once:
pinMode(13, OUTPUT); /* 设置13引脚为输出模式 */
digitalWrite(13, HIGH); /* 默认输出为高*/
Serial.begin(115200);
led_matrix.begin(); //初始化启动这个对象
led_matrix.renderBitmap(frame, 8, 12); //把LED矩阵的数据写入
wave.sine(50); //产生一个50HZ的sin波形
wave.amplitude(0.25); //设置幅度值为4.7 的1/4
}
void loop() {
// put your main code here, to run repeatedly:
delay(500);
digitalWrite(13, !digitalRead(13)); /* 每500ms进行一次LED灯的翻转*/
}
实际示波器实测效果如果下,还是挺符合4.7V的 1/4 波形的。
好了,有了基础波形,我们就来搭建运放把。额,为了搭建运放的电路,我去找了好久的电阻,建议下次不搞这种,薄膜电阻真的很难找呀,还得找块面包板。
运算放大器放大电路示意图如下所示:
实际用于两个10K的电阻和洞洞板搭建的电路图如下所示:
下面是搭建了2倍放大后的示波器效果图:黄色为放大前的波形图,蓝色为经过放大后的波形图。
最后附上本次实验的代码:
相对于前面而言,只是添加了一句代码。打开了OPAMP
OPAMP.begin(OPAMP_SPEED_HIGHSPEED); //开启放大器
#include "Arduino_LED_Matrix.h" /*包含官方的驱动库*/
#include "analogWave.h" // 包含波形输出的模拟文件
#include <OPAMP.h>
ArduinoLEDMatrix led_matrix; //实例化一个对象
analogWave wave(DAC); //实例化一个对象
/*串口初始化函数*/
void uart_init(uint32_t baud)
{
Serial.begin(baud);
}
/* 爱心的框图 */
byte frame[8][12] = {
{ 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
void setup() {
// put your setup code here, to run once:
OPAMP.begin(OPAMP_SPEED_HIGHSPEED); //开启放大器
pinMode(13, OUTPUT); /* 设置13引脚为输出模式 */
digitalWrite(13, HIGH); /* 默认输出为高*/
Serial.begin(115200);
led_matrix.begin(); //初始化启动这个对象
led_matrix.renderBitmap(frame, 8, 12); //把LED矩阵的数据写入
wave.sine(50); //产生一个50HZ的sin波形
wave.amplitude(0.25); //设置幅度值为4.7 的1/4
}
void loop() {
// put your main code here, to run repeatedly:
delay(500);
digitalWrite(13, !digitalRead(13)); /* 每500ms进行一次LED灯的翻转*/
}
5、上位机波形展示
我们使用A4 和 A5 引脚分别采集DAC的输出,和经过OPAMP放大之后的信号输出。然后通过串口发送到上位机进行波形的展示。
使用了 analogReadResolution(14); //change to 14-bit resolution 配置ADC的分辨率最高为14bit
使用了 float Rvalue1 = analogRead(A4) * 4.7/16383; //读取A4的引脚电压
实际的代码如下:
#include "Arduino_LED_Matrix.h" /*包含官方的驱动库*/
#include "analogWave.h" // 包含波形输出的模拟文件
#include <OPAMP.h>
ArduinoLEDMatrix led_matrix; //实例化一个对象
analogWave wave(DAC); //实例化一个对象
/*串口初始化函数*/
void uart_init(uint32_t baud)
{
Serial.begin(baud);
}
/* 爱心的框图 */
byte frame[8][12] = {
{ 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
void setup() {
// put your setup code here, to run once:
OPAMP.begin(OPAMP_SPEED_HIGHSPEED); //开启放大器
pinMode(13, OUTPUT); /* 设置13引脚为输出模式 */
digitalWrite(13, HIGH); /* 默认输出为高*/
Serial.begin(2000000);
led_matrix.begin(); //初始化启动这个对象
led_matrix.renderBitmap(frame, 8, 12); //把LED矩阵的数据写入
wave.sine(50); //产生一个50HZ的sin波形
wave.amplitude(0.25); //设置幅度值为4.7 的1/4
//配置ADC的分辨率最高为14bit
analogReadResolution(14); //change to 14-bit resolution
}
void loop() {
float Rvalue1 = analogRead(A4) * 4.7/16383; //读取A4的引脚电压
float Rvalue2 = analogRead(A5) * 4.7/16383; //读取A5的引脚电压
Serial.print(Rvalue1);
Serial.print(",");
Serial.println(Rvalue2);
delay(2);
}
最后我们把我们的波形在IDE上自带的串口绘图仪展示出来,可以看到基本上波形2是波形1的2倍数据关系。
这个实验中,为了方便展示波形,我们把串口的波特率调整到了最高
6、源代码以及展示视频
|