一、基本概念
1. 脈寬調制
PWM(Pulse Width Modulation)即脈寬調制,是一種通過調節信號的占空比來控制電路的技術。 在 PWM 技術中,信號的周期保持不變,但是信號的占空比可以隨時間變化而改變。 當信號的占空比為 0% 時,表示信號一直處于低電平狀態; 當占空比為 100% 時,表示信號一直處于高電平狀態; 而在占空比為中間值時,信號將以一定的頻率在低電平和高電平之間切換。
在電路應用中,PWM 技術常用于控制電機的轉速、控制 LED 的亮度和顏色、實現音頻數字化等方面。 例如,在控制 LED 亮度時,可以通過調節 PWM 信號的占空比來控制 LED 的亮度,占空比越大,LED 燈亮度越高,反之亦然。
在微控制器中,通過定時器和計數器等硬件模塊,可以實現高精度的 PWM 信號輸出。 許多單片機和嵌入式系統都提供了 PWM 功能,并且在軟件層面提供了相應的 API 和庫函數,方便開發者使用。 在使用 PWM 技術時,需要根據具體的應用場景選擇合適的 PWM 頻率和分辨率,以及合適的占空比范圍和切換速率,以達到最優的控制效果。
2. ESP8266 的 PWM功能
ESP8266 是一款高度集成的 Wi-Fi SoC 芯片,內部集成了許多硬件模塊,其中包括一個靈活的 PWM 控制器,即 LEDC(LED 控制器)。 LEDC 可以用于實現高精度的 PWM 輸出,適用于控制 LED 的亮度、顏色和閃爍等效果。
ESP8266 的 LEDC 控制器可實現同頻率、不同占空比的PWM波形輸出。 LEDC 模塊的主要特點包括:
- 高精度:LEDC 支持高達 20 位的 PWM 分辨率,可實現非常精細的 PWM 控制。
- 多路輸出:LEDC 可以同時控制多達 16 個 PWM 通道,滿足多路 PWM 輸出的需求。
- 靈活配置:LEDC 可以配置不同的 PWM 頻率和分辨率,以適應不同的應用場景。
- 低成本:LEDC 是 ESP8266 芯片內置的硬件模塊,使用 LEDC 功能無需外接任何外部元器件,節省了硬件成本。
在使用 ESP8266 的 PWM 功能時,可以使用 ESP8266 的官方庫文件 ESP8266WiFi.h 中提供的 LEDC 相關函數進行配置和控制。 例如,可以使用 ledcSetup() 函數來初始化 PWM 通道,并使用 ledcWrite() 函數來設置 PWM 占空比。 此外,ESP8266 的開發環境也提供了豐富的示例代碼和庫函數,方便開發者快速上手使用 PWM 功能。
要注意的是,GPIO1和GPIO3作為調試串口的TX和RX,一般不做PWM使用。
3. node-mcu 引腳圖
4. 模擬寫入
(1)模擬寫入
要實現輸出PWM信號,可以使用analogWrite()函數:
analogWrite(pin,value)
1
- pin:GPIO引腳
- value:默認0-1023
當值為0時,該引腳禁用PWM。 值為1023時 占空比100%。
(2)修改頻率 analogWriteFreq
analogWriteFreq(new_frequency);
(3)調節分辨率
可以用于調節模擬輸出的 PWM 范圍。
在 ESP8266 中,analogWriteRange() 函數用于設置 PWM 的分辨率。 默認情況下,ESP8266 的 PWM 分辨率為 10 位,即占空比范圍為 0~1023。 通過調用 analogWriteRange() 函數,可以將 PWM 分辨率調節為 8 位或 9 位,以擴大或縮小 PWM 占空比范圍。
二、使用analogWrite實現PWM
const int ledPin = 2;
void setup() {
}
void loop() {
// 增加LED亮度
for(int dutyCycle = 0; dutyCycle < 1023; dutyCycle++){
// 通過PWM改變LED亮度
analogWrite(ledPin, dutyCycle);
delay(10);
}
// 降低LED亮度
for(int dutyCycle = 1023; dutyCycle > 0; dutyCycle--){
// 通過PWM改變LED亮度
analogWrite(ledPin, dutyCycle);
delay(10);
}
}
三、發送紅外信號
1. 紅外通信原理
紅外通信是一種無線通信方式,它通過發射紅外線來傳輸數據或控制信號,通常用于紅外遙控器、紅外傳感器等場景。
紅外信號是一種電磁輻射,其頻率在可見光波和微波之間,一般波長為0.75至1000微米,其中,可見光波長為0.38至0.78微米。 紅外線被稱為"熱線",因為物體溫度越高,發射的紅外線輻射就越多。
在紅外通信中,通過對載波信號進行調制,將數字信號轉換為紅外信號,從而實現數據或控制信號的傳輸。 調制方式主要有兩種:幅度調制和頻率調制。
- 幅度調制:通過改變載波信號的幅度,將數字信號轉換為紅外信號。 在幅度調制中,通常用一個二進制信號來控制紅外發射器的開關狀態,從而實現傳輸數據。
- 頻率調制:通過改變載波信號的頻率,將數字信號轉換為紅外信號。 在頻率調制中,常用的方式是將數字信號和一個固定的載波信號進行異或運算,從而得到一個頻率變化的信號,用來控制紅外發射器的開關狀態,實現傳輸數據。
接收端通過紅外接收器接收到紅外信號,然后通過解調的方式提取出攜帶的數據或控制信號。 解調的過程就是將紅外信號轉化為電信號,然后提取出載波信號,再將其與一個固定的頻率進行比較,從而恢復出原始的數字信號。
2. 載波頻率
紅外信號的載波頻率(Carrier Frequency)指的是紅外信號中用于攜帶信息的載波波形的頻率。 在紅外通信中,常用的載波頻率一般在 20 kHz 到 50 kHz 之間。
將信息信號和載波信號進行調制后,就可以通過紅外發射器將帶有載波信號的紅外信號發送出去。 接收器可以通過解調過程,將攜帶的信息信號提取出來。
在紅外遙控器中,一般使用一定的載波頻率進行通信。 這樣可以提高通信的可靠性,同時也可以避免干擾,因為很少有其他的設備會使用相同的載波頻率進行通信。
3. 發送周期
紅外信號的發送周期是指一個完整的紅外信號周期所需的時間。 在紅外通信中,為了確保通信的可靠性,每一個紅外信號周期中一般包含多個載波周期。 具體來說,發送周期包括兩部分時間:載波周期和調制周期。
- 載波周期:指載波信號一個完整的波形所需的時間,它是紅外信號的基本單位。 在紅外通信中,載波周期通常為一個固定的時間,一般在38kHz左右。
- 調制周期:指一個完整的紅外信號周期所需的時間,它包括了載波周期和數字信號的調制。 在紅外通信中,調制周期的長度取決于傳輸的數據長度和傳輸速率。 一般來說,調制周期越長,傳輸速率就越慢,但是數據傳輸的可靠性會更高。
在紅外遙控器中,每一個按鍵通常對應一個特定的紅外信號,這個紅外信號的發送周期一般是固定的,以確保遙控器能夠正確地發送信號,并且接收器能夠正確地解碼信號。
4. 使用
(1)安裝庫
庫開源地址:
https://github.com/crankyoldgit/IRremoteESP8266
(2)代碼實現
#include
#include
IRsend irsend(4); // 初始化IRsend對象并設置輸出引腳,GPIO4=D2
void setup()
{
Serial.begin(115200);
delay(1000);
}
void loop()
{
Serial.println("Sending IR signal...");
irsend.sendSony(0xA90, 12); // 發送SONY紅外信號,傳輸數據為0xA90,數據長度為12位
delay(1000); // 等待1秒鐘
}
5. 紅外接收示例
#include
#include
#include
#include
// An IR detector/demodulator is connected to GPIO pin 14(D5 on a NodeMCU
// board).
// Note: GPIO 16 won't work on the ESP8266 as it does not have interrupts.
// Note: GPIO 14 won't work on the ESP32-C3 as it causes the board to reboot.
#ifdef ARDUINO_ESP32C3_DEV
const uint16_t kRecvPin = 10; // 14 on a ESP32-C3 causes a boot loop.
#else // ARDUINO_ESP32C3_DEV
const uint16_t kRecvPin = 14;
#endif // ARDUINO_ESP32C3_DEV
IRrecv irrecv(kRecvPin);
decode_results results;
void setup() {
Serial.begin(115200);
irrecv.enableIRIn(); // Start the receiver
while (!Serial) // Wait for the serial connection to be establised.
delay(50);
Serial.println();
Serial.print("IRrecvDemo is now running and waiting for IR message on Pin ");
Serial.println(kRecvPin);
}
void loop() {
if (irrecv.decode(&results)) {
// print() & println() can't handle printing long longs. (uint64_t)
serialPrintUint64(results.value, HEX);
Serial.println("");
irrecv.resume(); // Receive the next value
}
delay(100);
}
-
led
+關注
關注
242文章
23153瀏覽量
658617 -
PWM
+關注
關注
114文章
5153瀏覽量
213454 -
脈寬調制
+關注
關注
3文章
216瀏覽量
38289 -
Arduino
+關注
關注
187文章
6464瀏覽量
186677 -
ESP8266
+關注
關注
50文章
962瀏覽量
44852
發布評論請先 登錄
相關推薦
評論