风筝
发表于: 2018-12-5 21:46:28 | 显示全部楼层

对于喜欢偶尔鼓捣电子产品的工程师来说,他们都希望能有自己的实验室。万用表、钳形表、示波器、LCR表、函数发生器、双模电源和自动变压器都是实验室的基本配置。虽然所有这些都可以购买,但我们也可以轻松地自行制作,如函数发生器和双模电源。


在本篇文章中,我们将学习如何使用Arduino开发板快速轻松地制作自己的函数生成器。该函数发生器又称波形发生器,可产生频率范围为1Hz至2MHz的方波(5V / 0V),波形频率可通过旋钮控制,占空比固定为50%,但在本文中也很容易改变。除此之外,波形发生器还可以通过频率控制产生正弦波。请注意,此波形发生器不是工业级的,不能用于严格的测试。但除此之外,它将为所有业余爱好项目派上用场,您无需等待数周的运输。还有什么比使用我们自己制作的设备更有趣。


所需的材料

●    Arduino Nano开发板

●    字符型图形点阵液晶1602

●    旋转编码器

●    电阻(5.6K,10K)

●    电容(0.1uF)

●    焊接套件


电路原理图

该Arduino函数发生器的完整电路图如下所示。正如您所看到的,我们使用Arduino Nano开发板作为项目的主控,1602 LCD显示当前正在生成的频率值。我们还有一个旋转编码器,可以帮助我们设置频率。

Circuit-Diagram-for-DIY-Waveform-Generator-using-Arduino.png

整个设备由Arduino自身的USB端口供电。我之前使用过的连接由于某些原因并没有达到要求,我们将在本文后面讨论这些原因。因此,我不得不通过改变引脚顺序来接线。无论如何,你不会有任何问题,因为它全部整理好,只需仔细按照电路知道哪个引脚连接到什么。您还可以参考下表来验证您的连接。

Arduino引脚
连接到
D14
连接到LCD的RS
D15
连接到LCD的RN
D4
连接到LCD的D4
D3
连接到LCD的D5
D6
连接到LCD的D6
D7
连接到LCD的D7
D10
连接到旋转编码器的2脚
D11
连接到旋转编码器的3脚
D12
连接到旋转编码器的4脚
D9
输出方波
D2
连接到Arduino的D9
D5
输出SPWM然后转换为正弦

电路非常简单;我们在引脚D9上产生方波,可以这样使用,该方波的频率由旋转编码器控制。然后为了获得正弦波,我们在引脚D5上产生SPWM信号,其频率必须与PWM频率相关,因此我们将这个PWM信号提供给引脚D2作为中断,然后使用ISR来控制正弦波的频率。


您可以在面包板上构建电路,也可以制作一个PCB。但我决定将它焊接在Perf板上以快速完成工作并使其长期可靠使用。所有连接完成后,我的电路板看起来像这样。

Circuit-Hardware-for-DIY-Waveform-Generator-using-Arduino.jpg


如果您想了解更多关于如何使用Arduino生成PWM和正弦波的信息,请阅读以下段落,或者您可以直接向下滚动到编程Arduino部分。


产生变频方波

使用Arduino的人可能很熟悉Arduino只需使用模拟写入函数即可生成PWM信号。但是这个函数仅限于控制PWM信号的占空比而不是信号的频率。但是对于波形发生器,我们需要一个可以控制频率的PWM信号。这可以通过直接控制Arduino的定时器并根据它切换GPIO引脚来完成。但是有一些预先构建的库可以完全相同并且可以这样使用。我们使用的库是Arduino PWM频率库。我们将在代码部分讨论有关此库的更多信息。

Producing-Square-Wave-with-Variable-Frequency.png


这个库也有一些缺点,因为库改变了Arduino中默认的Timer 1和Timer 2设置。因此,您将无法在Arduino上再使用伺服库或任何其他与计时器相关的库。引脚9、10、11和13上的模拟写入函数也使用定时器1和定时器2,因此您将无法在这些引脚上产生SPWM。

这个库的优点是它不会干扰Arduino的定时器0,其比定时器1和定时器2更重要。因此你可以自由地使用延迟函数和millis()函数而没有任何问题。引脚5和6也由定时器0控制,因此我们在这些引脚上使用模拟写或伺服控制操作时不会遇到问题。最初花了一些时间才弄清楚这一点,这就是为什么接线搞砸了。


使用Arduino生成正弦波

我们知道微控制器是数字设备,它们不能仅仅通过编码产生正弦波。但是,在从微控制器获得正弦波的两种流行方法中,一种是使用DAC,另一种是通过创建SPWM。不幸的是,Arduino开发板(除了Due)没有内置DAC来产生正弦波,但你总是可以使用简单的R2R方法构建自己的DAC,然后用它来产生正常的正弦波。但是为了减少硬件工作,我决定使用后面的方法,创建SPWM信号然后将其转换为正弦波。


什么是SPWM信号?

术语SPWM代表正弦脉冲宽度调制。该信号与PWM非常相似,但对于SPWM信号,以这样的方式控制占空比,以获得与正弦波相似的平均电压。例如,在100%占空比时,平均输出电压为5V,在25%时我们将为1.25V,从而控制占空比,我们可以获得预定义的可变平均电压,这只是一个正弦波。这种技术通常用于逆变器。

Sinusoidal-Pulse-Width-Modulation.png

在上图中,蓝色信号是SPWM信号。请注意,波形的占空比在0%到100%之间变化,然后再回到0%。该曲线图绘制为-1.0至+ 1.0V,但在我们的情况下,由于我们使用的是Arduino,因此刻度将为0V至5V。我们将在下面的编程部分学习如何使用Arduino生成SPWM。


将SPWM转换为正弦波

将SPWM单个转换为正弦波需要H桥电路,该电路由最少4个电源开关组成。我们不会深入研究它,因为我们不在这里使用它。这些H桥电路通常用于逆变器。它利用两个SPWM信号,其中一个信号与另一个相移,并且两个信号都被施加到H桥中的电源开关,以使对角线相对的开关同时打开和关闭。通过这种方式,我们可以获得看起来类似于正弦波的波形,但实际上不会更接近上图中显示的任何波形(绿波)。为了获得纯波形输出,我们必须使用像低通滤波器这样的滤波器,它包括一个电感和电容。

Output-waveform-of-DIY-Waveform-Generator-using-Arduino.png

但是在电路中,我们不会使用正弦波来为任何东西供电。我只是想从生成的SPWM信号创建该波形,所以我选择了一个简单的RC-Filter。您也可以尝试使用LC滤波器以获得更好的结果,但为了简单起见,我选择了RC。我的电阻值为620欧姆,电容为10uF。上图显示了引脚5的SPWM信号(黄色)和通过RC滤波器后获得的正弦波(蓝色)。


添加Arduino PWM频率库

点击以下链接即可下载Arduino频率库。

       ●    Arduino PWM频率库

在撰写本文时,Arduino PWM频率库V_05是最新版本,它将以ZIP文件形式供下载。 解压ZIP文件,然后您将得到一个名为PWM的文件夹。 然后导航到Arduino IDE的Libraries文件夹,对于Windows用户,它将位于路径C:\Users\User\Documents\Arduino\libraries中。 将PWM文件夹粘贴到libraries文件夹中。 有时你可能已经有一个PWM文件夹,这时,请确保用这个新文件夹替换旧文件夹。

跳转到指定楼层
风筝
发表于: 2018-12-5 22:13:00 | 显示全部楼层

波形发生器的Arduino编程

与往常一样,本篇文章的完整程序可以在本页的末尾处列出找到。您可以直接使用该代码,但是请确保您已经在Arduino IDE中添加了上面提到的频率库,否则您将编译时收到错误。在本节中,我们将查看代码来理解工作工程。


我们在引脚9上产生可变频率的PWM信号。该频率应使用旋转编码器设置,该值也应显示在液晶屏1602上。一旦在引脚9上产生PWM信号,它将在引脚2上产生中断,因为我们已经短接了两个引脚。使用此中断,我们可以控制在引脚5上生成的SPWM信号的频率。


一如既往,我们首先在程序中包含所需的库。液晶库内置于Arduino中,我们只安装了PWM库。

  1. #include <PWM.h> //PWM librarey for controlling freq. of PWM signal
  2. #include <LiquidCrystal.h>
复制代码

接下来我们声明全局变量,并定义LCD、旋转编码器和信号引脚的引脚名称。如果您按照上面的电路图,可以不用改变这些定义。

  1. const int rs = 14, en = 15, d4 = 4, d5 = 3, d6 = 6, d7 = 7; //Mention the pin number for LCD connection
  2. LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

  3. const int Encoder_OuputA  = 11;
  4. const int Encoder_OuputB  = 12;
  5. const int Encoder_Switch = 10;
  6. const int signal_pin = 9;
  7. const int Sine_pin = 5;
  8. const int POT_pin = A2;      

  9. int Previous_Output;
  10. int multiplier = 1;
  11. double angle = 0;
  12. double increment = 0.2;
  13. int32_t frequency; //frequency to be set
  14. int32_t lower_level_freq = 1; //Lowest possible freq value is 1Hz
  15. int32_t upper_level_freq = 100000; //Maximum possible freq is 100KHz
复制代码

setup()函数中,我们初始化LCD和串行通信以进行调试,然后将Encoder的引脚声明为输入引脚。 我们还在启动期间显示一个介绍消息,以确保一切正常。

  1. lcd.begin(16, 2); //Initialise 16*2 LCD

  2.   lcd.print("Signal Generator"); //Intro Message line 1
  3.   lcd.setCursor(0, 1);
  4.   lcd.print("-CircuitDigest "); //Intro Message line 2
  5.   delay(2000);
  6.   lcd.clear();
  7.   lcd.print("Freq:00000Hz");
  8.   lcd.setCursor(0, 1);
  9.   lcd.print("Inc. by: 1 ");

  10. Serial.begin(9600); //Serial for debugging

  11. //pin Mode declaration
  12.   pinMode (Encoder_OuputA, INPUT);
  13.   pinMode (Encoder_OuputB, INPUT);
  14.   pinMode (Encoder_Switch, INPUT);
复制代码

另一个重要的代码是InitTimerSafe,它初始化定时器1和2以产生可变频率PWM。调用此函数后,Arduino的默认计时器设置将被更改。

  1. InitTimersSafe(); //Initialize timers without disturbing timer 0
复制代码

我们还在引脚2上运行外部中断。因此,只要引脚2的状态发生变化,就会触发中断,从而运行中断服务程序(ISR)函数。这里ISR函数的名称是generate_sine。

  1. attachInterrupt(0,generate_sine,CHANGE);
复制代码

接下来,在void loop()函数中,我们需要检查旋转编码器是否已经转动。只有在它被转动时我们才需要调整PWM信号的频率。我们已经学会了如何将旋转编码器是与Arduino连接。如果你是新手,我会建议你回到那个教程,然后再回到这里。


如果顺时针旋转旋转编码器,我们通过将其与乘数值相加来增加频率值。这样我们可以将频率值增加/减少1、10、100或甚至1000。可以通过按下旋转编码器来设置乘数的值。如果编码器旋转,我们改变频率值并在引脚9上产生一个PWM信号。这里值32768将PWM设置为50%周期。选择值32768,因为65536的50%是32768,类似地,您可以确定所需占空比的值。但这里的占空比固定为50%。最后,函数SetPinFrequencySafe用于设置引脚9的信号引脚的频率。

  1. pwmWriteHR(signal_pin, 32768); //Set duty cycle to 50% by default -> for 16-bit 65536/2 = 32768
  2. SetPinFrequencySafe(signal_pin, frequency);
复制代码

在ISR函数内部,我们编写代码来生成SPWM信号。有很多方法可以生成SPWM信号,甚至可以为Arduino提供预构建的库。我使用了最简单的利用Arduino中sin()函数的方法。如果您有兴趣,也可以尝试使用查找表方法。 sin()返回-1到+1之间的变量值(十进制),这在绘制时间时会给我们一个正弦波。


现在我们要做的就是将-1到+1的值转换为0到25​​5并将其输入到我们的模拟写入函数。我将它与255相乘只是为了忽略小数点,然后使用map函数将-255到+255的值转换为0到+255。最后,使用模拟写入函数将该值写入引脚5。每次调用ISR时,角度值增加0.2,这有助于我们控制正弦波的频率。

  1. double sineValue = sin(angle);
  2.    sineValue *= 255;
  3.    int plot = map(sineValue, -255, +255, 0, 255);
  4.    Serial.println(plot);
  5.    analogWrite(Sine_pin,plot);
  6.    angle += increment;
复制代码

在硬件上测试Arduino函数发生器

按照电路图搭建硬件并上传本文给出的代码。现在,您已准备好测试您的项目。如果你有一个DSO(示波器)会更容易,但你也可以用LED测试它,因为频率范围非常宽。

Testing-DIY-Waveform-Generator-using-Arduino.jpg


将探头连接到电路的方波和正弦波引脚。如果没有示波器,请在这两个引脚上使用两个LED。给电路供电,你应该看到液晶显示屏上的介绍信息。然后改变旋转编码器并设置所需的频率,您应该能够观察示波器上的方波和正弦波,如下所示。如果您使用LED,您应该注意到LED会根据您设置的频率以不同的间隔闪烁。

DIY-Waveform-Generator-using-Arduino.jpg


以上就是本篇文章的全部内容。希望你喜欢本文并从中学到一些有用的东西。如果您遇到任何问题,请在本帖下面进行回复。


代码

以下是本文使用的完整代码: main.rar (1.13 KB, 下载次数: 187)

回复

使用道具 举报

Porket
发表于: 2019-4-8 21:41:44 | 显示全部楼层

PWM库打不开  能不能帮忙解决一下
回复

使用道具 举报

风筝
发表于: 2019-4-9 08:54:10 | 显示全部楼层

Porket 发表于 2019-4-8 21:41
PWM库打不开  能不能帮忙解决一下

已上传zip文件 请查收


Arduino PWM Frequency Library v_05.zip (13.72 KB, 下载次数: 95)

回复

使用道具 举报

VforeverV
发表于: 2019-7-24 09:56:28 | 显示全部楼层

请问可以用uno或者2560的板子吗
回复

使用道具 举报

eee987
发表于: 2020-1-11 23:26:24 | 显示全部楼层

图上的元件和文章里的不一样啊
回复

使用道具 举报

gdgzwqz
发表于: 2020-9-20 13:15:39 | 显示全部楼层

那个十脚芯片是天外来物吗??????
回复

使用道具 举报

gdgzwqz
发表于: 2020-9-20 14:09:44 | 显示全部楼层

西文的全套资料在这里!
ht t p s  : / / w w w . all about circuits.com/projects/how-to-D I Y-waveform-generator-analog-devices-a d 9833-AT mega 328 p/#login Modal
请删除其中空格,因无发链接权限!
回复

使用道具 举报

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

本版积分规则

主题 714 | 回复: 1501



手机版|

GMT+8, 2024-12-22 02:29 , Processed in 0.086564 second(s), 8 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表