認識了 mbed 的類比訊號輸入之後,我們接下來要看的是 mbed 的類比輸出啦~
稍有基礎的朋友應該會把類比訊號輸出和 PWM 輸出連想在一起,但這兩者的動作實際上是不相同的。
PWM 是藉由調整脈波寬度來達到調整電壓高低的目的(可參考 Arduino 之軟體 PWM 這篇文章的內容),而 AnalogOut 則是直接將電壓輸出至指定比例的電壓,兩者在根本上有非常大的差距。
不過,最後輸出結果都屬於類比訊號的一種,也因此今天的文章將會把 mbed 的類比輸出以及 PWM 輸出一併介紹給你認識。
這次要準備的東西比較麻煩一些,因為有個設備不容易取得,但這個可以不準備沒關係。
#include "mbed.h"
// 這個腳位會產生一個正弦波訊號
AnalogOut aout(p18);
int main()
{
const double pi = 3.141592653589793238462;
const double amplitude = 0.5f;
const double offset = 65535/2;
double rads = 0.0;
uint16_t sample = 0;
while(1) {
// 輸出正弦波
for (int i = 0; i < 360; i++) {
rads = (pi * i) / 180.0f;
sample = (uint16_t)(amplitude * (offset * (cos(rads + pi))) + offset);
aout.write_u16(sample);
}
}
}
這個範例程式的執行結果如下圖:
幾乎完整的重現一個漂亮的正弦波形呢!
下面這個範例程式的版本是用 LED 做為展示,你應該可以看到這兩顆 LED 以互補的方式交替漸亮與漸暗。
#include "mbed.h"
// 這個腳位會產生一個正弦波訊號
AnalogOut aout(p18);
int main()
{
const double pi = 3.141592653589793238462;
const double amplitude = 0.5f;
const double offset = 65535/2;
double rads = 0.0;
uint16_t sample = 0;
while(1) {
// 輸出正弦波
for (int i = 0; i < 360; i++) {
rads = (pi * i) / 180.0f;
sample = (uint16_t)(amplitude * (offset * (cos(rads + pi))) + offset);
aout.write_u16(sample);
// 等待 10ms 降低更新速度
wait(0.01);
}
}
}
接線方式如開頭的硬體接線方式。
會這樣的原因是因為正弦波的特性的關係,這邊產生的正弦波理論上是一個從 0V ~ 3.3V 的一個信號,所以當你利用如上的接法去接時,就會有如影片的效果。
#include "mbed.h"
PwmOut led(LED1);
int main() {
while(1) {
for(float p = 0.0f; p < 1.0f; p += 0.1f) {
led = p;
wait(0.1);
}
for(float p = 1.0f; p > 0.0f; p -= 0.1f) {
led = p;
wait(0.1);
}
}
}
在 PwmOut 這個範例程式中,值得注意的是,我用的並非 mbed LPC1768 接線上的外部接腳,而是用板子上的 LED1 來作為輸出。這是因為 mbed LPC1768 LED 1 ~ LED 4 是接於它的 PWM 1 ~ PWM 4 上,所以才能這樣設定,你可以參考如下的對照表格。
PWM H/W Channel | Pinout Options |
---|---|
PWM_1 | p26 or LED1 |
PWM_2 | p25 or LED2 |
PWM_3 | p24 or LED3 |
PWM_4 | p23 or LED4 |
PWM_5 | p22 |
PWM_6 | p21 |
範例執行結果如影片
從影片中你可以發現 LED 雖然也會漸亮漸暗,但在較暗時會有閃爍的現象產生,這原因是因為 PWM 是靠調整脈波來調整整體電壓平均值所造成的。當 LED 較暗時,脈波的工作週期是拉長的,所以人眼暫留視覺看時會覺得 LED 是暗的。
當然,這跟 PWM 預設的頻率有點關係,在 mbed LPC178 中的預設週期是 0.02 秒,預設脈波寬度是 0。
你可以透過它提供的方法來調整這些參數
方法名稱 | 敘述 |
---|---|
write (float value) | 設定工作週期 |
period (float seconds) | 以秒為單位設定週期 |
period_ms (int ms) | 以毫秒為單位設定週期 |
period_us (int us) | 以微秒為單位設定週期 |
pulsewidth (float seconds) | 以秒為單位設定脈寬 |
pulsewidth_ms (int ms) | 以豪秒為單位設定脈寬 |
pulsewidth_us (int us) | 以微秒為單位設定脈寬 |
事實上, mbed 的類比輸出是用模擬的方式達成的,也就是所謂的 DAC 轉換,因此它並沒有辦法作到相當細緻的輸出控制,但對於 LED 的亮度控制以及馬達的轉速控制來說,這樣的方式已經非常的足夠了。
是說這內建的 ADC 應該可以做出一個相當不錯的隨身聽?改天來試試。