447|2

163

帖子

3

TA的资源

一粒金砂(高级)

楼主
 

【Follow me第二季第2期】+ 基础任务【驱动LED矩阵+DAC正弦波+放大信号+ADC数据采集】 [复制链接]

  本帖最后由 御坂10032号 于 2024-9-7 21:19 编辑

前言

 

        在上一个章节中我们学习到了如何使用R4来Blink 和 使用串口输出数据, 那么本章节我们来研究以下如何驱动R4的LED矩阵和使用DAC生成正弦波,然后用OPAMP放大DAC信号。最后用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线。

 


 

一、驱动LED矩阵

 

 

R4上有一个LED矩阵,根据官方的文档得知, 如果我们想使用LED矩阵主要为以下几步。

 

1- 引入头文件

#include "Arduino_LED_Matrix.h"

2-定义matrix对象

ArduinoLEDMatrix matrix;

3-在setup中调用matrix的start函数

matrix.begin();

代码如下所示

#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;

void setup() {
  Serial.begin(115200);
  matrix.begin();
}

 

那么上述的起始工作我们已经完成了,但是具体怎么来驱动矩阵呢? 由于这个LED矩阵是一个8*12的, 所以每一个LED灯都占用了一个bit用来存储led的状态。 如下代码所示

 

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 }
};

 

上面的矩阵是一个爱心的形状, 如果想让这个形状更加清晰的话, 可以使用ctrl + f 然后搜索1, 此时你会更清晰的看到这个爱心。 如下图所示

 

 

 

紧接着我们便可以通过 matrix.renderBitmap(frame, 8, 12); 加载这个矩阵数组。 如下代码所示

 

// To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;


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() {
  Serial.begin(115200);
  matrix.begin();
  matrix.renderBitmap(frame, 8, 12);
}

void loop() {

}

 

实验现象如下:

 

 

 

我们也可以换一种方式来表示LED的状态, 比如说使用16进制

 

unsigned long frame[] = {
  0x3184a444,
  0x42081100,
  0xa0040000
};

 

为什么它可以表示LED的状态呢? 首先我们需要把他转换成2进制便得到如下数据

 

110001100001001010010001000100
1000010000010000001000100000000
10100000000001000000000000000000

 

然后32位对齐(高位补0保持原本数据不变)

 

00110001100001001010010001000100
01000010000010000001000100000000
10100000000001000000000000000000

 

之后呢, 再将其分成8*12的原始矩阵,便得到了如下数据

 

001100011000
010010100100
010001000100
001000001000
000100010000
000010100000
000001000000
000000000000

 

它还是上面我们定义的爱心矩阵。之后我们便可以通过matrix.loadFrame() 函数来加载这个定义的矩阵, 代码如下所示

 

// To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;


const uint32_t heart[] = {
    0x3184a444,
    0x44042081,
    0x100a0040
};

void setup() {
  Serial.begin(115200);
  matrix.begin();
  matrix.loadFrame(heart);
  
}

void loop() {

}

 

实验现象如下所示

 

 

 

 

  那么基础的原理理解的话,我们便可以看一下今天写的第一个代码, 通过数据帧的方式打印Hello EEworld and Digikey

 

1 - 首先定义一个头文件eeworld.h 用来存储每一个字母的状态

 

const uint32_t animation[][4] = {
	{
		0x8808,
		0x880f80,
		0x88088088,
	},
	{
		0xf808,
		0x800f80,
		0x800800f8,
	},
	{
		0x8008,
		0x800800,
		0x800800f8,
	},
	{
		0x8008,
		0x800800,
		0x800800f8,
	},
	{
		0x6009,
		0x900900,
		0x90090060,
	},
		{
		0xf808,
		0x800f80,
		0x800800f8,
	},
		{
		0xf808,
		0x800f80,
		0x800800f8,
	},
	{
		0xf808,
		0x800f80,
		0x800800f8,
	},
	{
		0x40,
		0x12221540,
		0x88000000,
	},
	{
		0x6009,
		0x900900,
		0x90060000,
	},
	{
		0xf009,
		0x900f00,
		0xc00a0090,
	},
	{
		0x8008,
		0x800800,
		0x800f8000,
	},
  	
	{
		0xc00a,
		0x900900,
		0xa00c0000,
	},
  {
		0x00,
		0x00,
		0x00,
	},
	{
		0x400a,
		0xa00e00,
		0xa00a0000,
	},
	{
		0xe00a,
		0xa00a00,
		0xa00a0000,
	},
	{
		0xc00a,
		0x900900,
		0xa00c0000,
	},
  {
		0x00,
		0x00,
		0x00,
	},
	{
		0xc00a,
		0x900900,
		0xa00c0000,
	},
	{
		0xe004,
		0x400400,
		0x400e0000,
	},
	{
		0x1e012,
		0x1201601,
		0x101f0000,
	},
	{
		0xe004,
		0x400400,
		0x400e0000,
	},
	{
		0x900a,
		0xc00a00,
		0x90000000,
	},
	{
		0xf008,
		0x800f00,
		0x800800f0,
	},
	{
		0x1100a,
		0x400400,
		0x40040000,
	},
  {
		0x00,
		0x00,
		0x00,
	},
  {
		0x00,
		0x00,
		0x00,
	}
};

 

2- 在主程序中引入头文件

 

#include "eeworld.h"

 

3- 完整代码如下所示

 

#include "eeworld.h"
#include "Arduino_LED_Matrix.h"  

ArduinoLEDMatrix matrix;         
const int frameCount = sizeof(animation) / sizeof(animation[0]);  // 获取总帧数
int currentFrame = 0;             // 当前帧计数器

void setup() {
  Serial.begin(115200);          
  matrix.begin();               
}

void loop() {
  matrix.loadFrame(animation[currentFrame]);  // 加载并显示当前帧
  delay(500);  // 延迟 500 毫秒
  // 更新帧计数器以显示下一个帧
  currentFrame++;
  if (currentFrame >= frameCount) {
    currentFrame = 0;  // 如果达到最后一帧,则返回到第一帧
  }
}

 

实验现象如下所示:

9月7日 (1)

 

附件代码:

sketch_sep7a.ino (621 Bytes, 下载次数: 8)
eeworld.h (1.27 KB, 下载次数: 2)

 

 

当然还有第二种方式, 比如说使用Arduino 官方提供的LED滚屏的效果, 代码如下所示

 

// To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;

void setup() {
  Serial.begin(115200);
  matrix.begin();

  matrix.beginDraw();
  matrix.stroke(0xFFFFFFFF);
  // add some static text
  // will only show "UNO" (not enough space on the display)
  const char text[] = "UNO r4";
  matrix.textFont(Font_4x6);
  matrix.beginText(0, 1, 0xFFFFFF);
  matrix.println(text);
  matrix.endText();

  matrix.endDraw();

  delay(2000);
}

void loop() {

  // Make it scroll!
  matrix.beginDraw();

  matrix.stroke(0xFFFFFFFF);
  matrix.textScrollSpeed(50);

  // add the text
  const char text[] = "    Hello EEWorld and DigiKey!    ";
  matrix.textFont(Font_5x7);
  matrix.beginText(0, 1, 0xFFFFFF);
  matrix.println(text);
  matrix.endText(SCROLL_LEFT);

  matrix.endDraw();
}

 

实验现象如下:

 

9月7日 (1)(1)

 

下面我再简单的介绍一下动画的矩阵是怎么实现的。我们可以借助官方的LED tool 来快速自定义我们自己的动画(删除掉持续时间的话就是加载单独帧)

 

 

 

 

我们可以使用笔刷直观的绘制我们想要的动画, 比如说我这里绘制了一个正方形(起始我们可以使用这个工具直接把绘制的动画烧录到Arduino中,但是谷歌好像不支持这个工具,并且我使用了火狐也没有成功)

 

 

 

 

绘制完成后点击右上角, 把代码下载下来。

 

 

 

 

把这个文件放到你Arduino的工程目录下, 并且引入到项目里。 代码如下

 

#include "Arduino_LED_Matrix.h"   //Include the LED_Matrix library
#include "animation2.h"
// Create an instance of the ArduinoLEDMatrix class
ArduinoLEDMatrix matrix;  

void setup() {
  Serial.begin(115200);
  // you can also load frames at runtime, without stopping the refresh
  matrix.loadSequence(animation2);
  matrix.begin();
  matrix.play(true);
}

void loop() {
}

实验现象如下

cab33554025ea7066c0f3c540fe2d9a3

 



 

二、DAC 输出正弦波,放大信号,并且使用ADC采集显示在串口绘图中

 

这个任务主要分为三个部分, 分别是使用DAC输出正弦波, 然后使用信号放大器放大DAC输出,然后使用ADC采集输入.

 

1- DAC 输出

 

根据官方文档,得知 实现DAC比较简单, 我们只需要使用下面的代码并且按照图示搭建好电路

 

 

/*
  SineWave

  Generates a pre-generated sawtooth-waveform.

  See the full documentation here:
  https://docs.arduino.cc/tutorials/uno-r4-wifi/dac
*/

#include "analogWave.h" // Include the library for analog waveform generation

analogWave wave(DAC);   // Create an instance of the analogWave class, using the DAC pin

int freq = 10;  // in hertz, change accordingly

void setup() {
  Serial.begin(115200);  // Initialize serial communication at a baud rate of 115200
  wave.sine(freq);       // Generate a sine wave with the initial frequency
}

void loop() {
  // Read an analog value from pin A5 and map it to a frequency range
  freq = map(analogRead(A5), 0, 1024, 0, 10000);

  // Print the updated frequency to the serial monitor
  Serial.println("Frequency is now " + String(freq) + " hz");

  wave.freq(freq);  // Set the frequency of the waveform generator to the updated value
  delay(1000);      // Delay for one second before repeating
}

 

那么程序就会读取滑动变阻器的输出端(ADC)动态调整A0 (蜂鸣器输出的频率)

 

 

 

串口助手输出如下所示

 

 

 

由于比较拮据手头没有示波器,便使用了STC的试验箱,烧录了老梁示波器的代码。用来测量A0的输出

 

 

 

 

虚拟示波器输出如下所示

 

 

 

 

之后我们使用 opamp 对输出的数据进行放大。 参考官方文档, 我们可以使用下面的电路进行两倍的输出放大。

 

 

 

 

简单的搭建一下电路, 注意R0,也就是接地的电阻需要再10K欧姆, 另一个电阻则为30K欧姆

 

 

 

代码如下(此时我们已经完成了正弦波和放大信号,那么现在我们将使用ADC来读取放大后的信号)

 

#include "analogWave.h" // Include the library for analog waveform generation
#include <OPAMP.h>
analogWave wave(DAC);   // Create an instance of the analogWave class, using the DAC pin

int freq = 10;  // in hertz, change accordingly

void setup() {
  OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
  Serial.begin(115200);  // Initialize serial communication at a baud rate of 115200
  wave.sine(freq);       // Generate a sine wave with the initial frequency
}

void loop() {
  // Read an analog value from pin A5 and map it to a frequency range
  freq = map(analogRead(A5), 0, 1024, 0, 10000);

  // Print the updated frequency to the serial monitor
  Serial.println("Frequency is now " + String(freq) + " hz");

  wave.freq(freq);  // Set the frequency of the waveform generator to the updated value
  delay(50);      // Delay for one second before repeating
}

 

示波器输出如下所示(4V左右,滑动变阻器仍然可以调整输出频率):

 

 

 

参考官方文档, 我们可以使用如下API来配置ADC功能

1- analogReadResolution()

2- analogRead()

如果不需要修改分辨率的话, 可以不使用第一个API。我们在我们的代码上稍微修改下,使其可以把输出被串口绘图正确解析,同时可以获取A4的ADC输入

#include "analogWave.h" // Include the library for analog waveform generation
#include <OPAMP.h>
analogWave wave(DAC);   // Create an instance of the analogWave class, using the DAC pin

int freq = 10;  // in hertz, change accordingly
int reading = 0;
void setup() {
  OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
  Serial.begin(115200);  // Initialize serial communication at a baud rate of 115200
  analogWriteResolution(14); 
  wave.sine(freq);       // Generate a sine wave with the initial frequency
}

void loop() {
  // Read an analog value from pin A5 and map it to a frequency range
  freq = map(analogRead(A5), 0, 1024, 0, 10000);

  // Print the updated frequency to the serial monitor
  Serial.println("Frequency is now " + String(freq) + " hz");
  reading = analogRead(A4);
  Serial.print(reading);
  wave.freq(freq);  // Set the frequency of the waveform generator to the updated value
  delay(50);      // Delay for one second before repeating
}

 

电路如下

 

 

 

串口绘图工具输出如下(蓝色的为ADC读取的值,黄色的为当前的频率)

 

 

 

 

代码如下:

dac.ino (951 Bytes, 下载次数: 0)

最新回复

服气,没有点动手能力还完成不了这个任务  详情 回复 发表于 2024-9-12 14:59
点赞 关注
 
 

回复
举报

24

帖子

9

TA的资源

一粒金砂(中级)

沙发
 
服气,没有点动手能力还完成不了这个任务

点评

哈哈, 是稍微有一点麻烦  详情 回复 发表于 2024-9-12 21:53
 
 
 

回复

163

帖子

3

TA的资源

一粒金砂(高级)

板凳
 
genvex 发表于 2024-9-12 14:59 服气,没有点动手能力还完成不了这个任务

哈哈, 是稍微有一点麻烦

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表