Using the ATmega PWM Registers Directly
The ATmega168P/328P chip has three PWM timers, controlling 6 PWM outputs. By manipulating the chip’s timer registers directly, you can obtain more control than the analogWrite function provides.
The AVR ATmega328P datasheet provides a detailed description of the PWM timers, but the datasheet can be difficult to understand, due to the many different control and output modes of the timers.
A word on the relationship between the Arduino language and the datasheet may be in order here.
The Atmega 168/328 timers.
The ATmega328P has three timers known as Timer 0, Timer 1, and Timer 2. Each timer has two output compare registers that control the PWM width for the timer’s two outputs: when the timer reaches the compare register value, the corresponding output is toggled. The two outputs for each timer will normally have the same frequency, but can have different duty cycles (depending on the respective output compare register).
Each of the timers has a prescaler that generates the timer clock by dividing the system clock by a prescale factor such as 1, 8, 64, 256, or 1024. The Arduino has a system clock of 16MHz and the timer clock frequency will be the system clock frequency divided by the prescale factor. Note that Timer 2 has a different set of prescale values from the other timers.
The timers are complicated by several different modes. The main PWM modes are “Fast PWM” and “Phase-correct PWM”, which will be described below. The timer can either run from 0 to 255, or from 0 to a fixed value. (The 16-bit Timer 1 has additional modes to supports timer values up to 16 bits.) Each output can also be inverted.
The timers can also generate interrupts on overflow and/or match against either output compare register, but that’s beyond the scope of this article.
Timer Registers
Several registers are used to control each timer. The Timer/Counter Control Registers TCCRnA and TCCRnB hold the main control bits for the timer. (Note that TCCRnA and TCCRnB do not correspond to the outputs A and B.) These registers hold several groups of bits:
- Waveform Generation Mode bits (WGM): these control the overall mode of the timer. (These bits are split between TCCRnA and TCCRnB.)
- Clock Select bits (CS): these control the clock prescaler
- Compare Match Output A Mode bits (COMnA): these enable/disable/invert output A
- Compare Match Output B Mode bits (COMnB): these enable/disable/invert output B
The Output Compare Registers OCRnA and OCRnB set the levels at which outputs A and B will be affected. When the timer value matches the register value, the corresponding output will be modified as specified by the mode.
The bits are slightly different for each timer, so consult the datasheet for details. Timer 1 is a 16-bit timer and has additional modes. Timer 2 has different prescaler values.
Fast PWM
In the simplest PWM mode, the timer repeatedly counts from 0 to 255. The output turns on when the timer is at 0, and turns off when the timer matches the output compare register. The higher the value in the output compare register, the higher the duty cycle. This mode is known as Fast PWM Mode. The following diagram shows the outputs for two particular values of OCRnA and OCRnB. Note that both outputs have the same frequency, matching the frequency of a complete timer cycle.
Fast PWM Mode
The following code fragment sets up fast PWM on pins 3 and 11 (Timer 2). To summarize the register settings, setting the waveform generation mode bits WGM to 011 selects fast PWM. Setting the COM2A bits and COM2B bits to 10 provides non-inverted PWM for outputs A and B. Setting the CS bits to 100 sets the prescaler to divide the clock by 64. (Since the bits are different for the different timers, consult the datasheet for the right values.) The output compare registers are arbitrarily set to 180 and 50 to control the PWM duty cycle of outputs A and B. (Of course, you can modify the registers directly instead of using
, but you do need to set the pins to output.)
pinMode()
1pinMode(3, OUTPUT);2 pinMode(11, OUTPUT);3 TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);4 TCCR2B = _BV(CS22);5 OCR2A = 180;6 OCR2B = 50;
On the Arduino Duemilanove, these values yield:
- Output A frequency: 16 MHz / 64 / 256 = 976.5625Hz
- Output A duty cycle: (180+1) / 256 = 70.7%
- Output B frequency: 16 MHz / 64 / 256 = 976.5625Hz
- Output B duty cycle: (50+1) / 256 = 19.9%
The output frequency is the 16MHz system clock frequency, divided by the prescaler value (64), divided by the 256 cycles it takes for the timer to wrap around. Note that fast PWM holds the output high one cycle longer than the compare register value.
Phase-Correct PWM
The second PWM mode is called phase-correct PWM. In this mode, the timer counts from 0 to 255 and then back down to 0. The output turns off as the timer hits the output compare register value on the way up, and turns back on as the timer hits the output compare register value on the way down. The result is a more symmetrical output. The output frequency will be approximately half of the value for fast PWM mode, because the timer runs both up and down.
Phase-Correct PWM example
The following code fragment sets up phase-correct PWM on pins 3 and 11 (Timer 2). The waveform generation mode bits WGM are set to to 001 for phase-correct PWM. The other bits are the same as for fast PWM.
1pinMode(3, OUTPUT);2 pinMode(11, OUTPUT);3 TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);4 TCCR2B = _BV(CS22);5 OCR2A = 180;6 OCR2B = 50;
On the Arduino Duemilanove, these values yield:
- Output A frequency: 16 MHz / 64 / 255 / 2 = 490.196Hz
- Output A duty cycle: 180 / 255 = 70.6%
- Output B frequency: 16 MHz / 64 / 255 / 2 = 490.196Hz
- Output B duty cycle: 50 / 255 = 19.6%
Phase-correct PWM divides the frequency by two compared to fast PWM, because the timer goes both up and down. Somewhat surprisingly, the frequency is divided by 255 instead of 256, and the duty cycle calculations do not add one as for fast PWM. See the explanation below under “Off-by-one”.
Varying the timer top limit: fast PWM
Both fast PWM and phase correct PWM have an additional mode that gives control over the output frequency. In this mode, the timer counts from 0 to OCRA (the value of output compare register A), rather than from 0 to 255. This gives much more control over the output frequency than the previous modes. (For even more frequency control, use the 16-bit Timer 1.)
Note that in this mode, only output B can be used for PWM; OCRA cannot be used both as the top value and the PWM compare value. However, there is a special-case mode “Toggle OCnA on Compare Match” that will toggle output A at the end of each cycle, generating a fixed 50% duty cycle and half frequency in this case. The examples will use this mode.
In the following diagram, the timer resets when it matches OCRnA, yielding a faster output frequency for OCnB than in the previous diagrams. Note how OCnA toggles once for each timer reset.
Fast PWM Mode with OCRA top
The following code fragment sets up fast PWM on pins 3 and 11 (Timer 2), using OCR2A as the top value for the timer. The waveform generation mode bits WGM are set to to 111 for fast PWM with OCRA controlling the top limit. The OCR2A top limit is arbitrarily set to 180, and the OCR2B compare register is arbitrarily set to 50. OCR2A’s mode is set to “Toggle on Compare Match” by setting the COM2A bits to 01.
1pinMode(3, OUTPUT);2 pinMode(11, OUTPUT);3 TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);4 TCCR2B = _BV(WGM22) | _BV(CS22);5 OCR2A = 180;6 OCR2B = 50;
On the Arduino Duemilanove, these values yield:
- Output A frequency: 16 MHz / 64 / (180+1) / 2 = 690.6Hz
- Output A duty cycle: 50%
- Output B frequency: 16 MHz / 64 / (180+1) = 1381.2Hz
- Output B duty cycle: (50+1) / (180+1) = 28.2%
Note that in this example, the timer goes from 0 to 180, which takes 181 clock cycles, so the output frequency is divided by 181. Output A has half the frequency of Output B because the Toggle on Compare Match mode toggles Output A once each complete timer cycle.
Varying the timer top limit: phase-correct PWM
Similarly, the timer can be configured in phase-correct PWM mode to reset when it reaches OCRnA.
Phase-Correct PWM with OCRA top The following code fragment sets up phase-correct PWM on pins 3 and 11 (Timer 2), using OCR2A as the top value for the timer. The waveform generation mode bits WGM are set to to 101 for phase-correct PWM with OCRA controlling the top limit. The OCR2A top limit is arbitrarily set to 180, and the OCR2B compare register is arbitrarily set to 50. OCR2A’s mode is set to “Toggle on Compare Match” by setting the COM2A bits to 01.
1pinMode(3, OUTPUT);2 pinMode(11, OUTPUT);3 TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);4 TCCR2B = _BV(WGM22) | _BV(CS22);5 OCR2A = 180;6 OCR2B = 50;
On the Arduino Duemilanove, these values yield:
- Output A frequency: 16 MHz / 64 / 180 / 2 / 2 = 347.2Hz
- Output A duty cycle: 50%
- Output B frequency: 16 MHz / 64 / 180 / 2 = 694.4Hz
- Output B duty cycle: 50 / 180 = 27.8%
Note that in this example, the timer goes from 0 to 180 and back to 0, which takes 360 clock cycles. Thus, everything is divided by 180 or 360, unlike the fast PWM case, which divided everything by 181; see below for details.//
Off-by-one
You may have noticed that fast PWM and phase-correct PWM seem to be off-by-one with respect to each other, dividing by 256 versus 255 and adding one in various places. The documentation is a bit opaque here, so I’ll explain in a bit of detail.
Suppose the timer is set to fast PWM mode and is set to count up to an OCRnA value of 3. The timer will take on the values 012301230123… Note that there are 4 clock cycles in each timer cycle. Thus, the frequency will be divided by 4, not 3. The duty cycle will be a multiple of 25%, since the output can be high for 0, 1, 2, 3, or 4 cycles out of the four. Likewise, if the timer counts up to 255, there will be 256 clock cycles in each timer cycle, and the duty cycle will be a multiple of 1/256. To summarize, fast PWM divides by N+1 where N is the maximum timer value (either OCRnA or 255).
Now consider phase-correct PWM mode with the timer counting up to an OCRnA value of 3. The timer values will be 012321012321… There are 6 clock cycles in each timer cycle (012321). Thus the frequency will be divided by 6. The duty cycle will be a multiple of 33%, since the output can be high for 0, 2, 4, or 6 of the 6 cycles. Likewise, if the timer counts up to 255 and back down, there will be 510 clock cycles in each timer cycle, and the duty cycle will be a multiple of 1/255. To summarize, phase-correct PWM divides by 2N, where N is the maximum timer value.
The second important timing difference is that fast PWM holds the output high for one cycle longer than the output compare register value. The motivation for this is that for fast PWM counting to 255, the duty cycle can be from 0 to 256 cycles, but the output compare register can only hold a value from 0 to 255. What happens to the missing value? The fast PWM mode keeps the output high for N+1 cycles when the output compare register is set to N so an output compare register value of 255 is 100% duty cycle, but an output compare register value of 0 is not 0% duty cycle but 1/256 duty cycle. This is unlike phase-correct PWM, where a register value of 255 is 100% duty cycle and a value of 0 is a 0% duty cycle.
Timers and the Arduino
The Arduino supports PWM on a subset of its output pins. It may not be immediately obvious which timer controls which output, but the following table will clarify the situation. It gives for each timer output the output pin on the Arduino (i.e. the silkscreened label on the board), the pin on the ATmega chip, and the name and bit of the output port. For instance Timer 0 output OC0A is connected to the Arduino output pin 6; it uses chip pin 12 which is also known as PD6.
Timer output | Arduino output | Chip pin | Pin name |
OC0A | 12 | PD6 | |
OC0B | 11 | PD5 | |
OC1A | 15 | PB1 | |
OC1B | 10 | 16 | PB2 |
OC2A | 11 | 17 | PB3 |
OC2B | PD3 |
The Arduino performs some initialization of the timers. The Arduino initializes the prescaler on all three timers to divide the clock by 64. Timer 0 is initialized to Fast PWM, while Timer 1 and Timer 2 is initialized to Phase Correct PWM. See the Arduino source file wiring.c for details.
The Arduino uses Timer 0 internally for the millis() and delay() functions, so be warned that changing the frequency of this timer will cause those functions to be erroneous. Using the PWM outputs is safe if you don’t change the frequency, though.
The
function sets the appropriate pin to PWM and sets the appropriate output compare register to duty_cycle (with the special case for duty cycle of 0 on Timer 0). The
analogWrite(pin, duty_cycle)
function turns off PWM output if called on a timer pin. The relevant code is wiring_analog.c and wiring_digital.c.
digitalWrite()
If you use
you get a duty cycle of 0%, even though pin 5’s timer (Timer 0) is using fast PWM. How can this be, when a fast PWM value of 0 yields a duty cycle of 1/256 as explained above? The answer is that
analogWrite(5, 0)
“cheats”; it has special-case code to explicitly turn off the pin when called on Timer 0 with a duty cycle of 0. As a consequency, the duty cycle of 1/256 is unavailable when you use `analogWrite“ on Timer0, and there is a jump in the actual duty cycle between values of 0 and 1.
analogWrite
Some other Arduino models use dfferent AVR processors with similar timers. The Arduino Mega uses the ATmega1280 (datasheet), which has four 16-bit timers with 3 outputs each and two 8-bit timers with 2 outputs each. Only 14 of the PWM outputs are supported by the Arduino Wiring library, however. Some older Arduino models use the ATmega8 (datasheet), which has three timers but only 3 PWM outputs: Timer 0 has no PWM, Timer 1 is 16 bits and has two PWM outputs, and Timer 2 is 8 bits and has one PWM output.
Troubleshoot
It can be tricky to get the PWM outputs to work. Some tips:
- You need to both enable the pin for output and enable the PWM mode on the pin in order to get any output. I.e. you need to do pinMode() and set the COM bits.
- The different timers use the control bits and prescaler differently; check the documentation for the appropriate timer.
- Some combinations of bits that you might expect to work are reserved, which means if you try to use them, they won’t work.
- For example, toggle mode doesn’t work with fast PWM to 255, or with output B.
- Make sure the bits are set the way you think. Bit operations can be tricky, so print out the register values with the binary (BIN) formatter and make sure they are what you expect.
- Make sure you’re using the right output pins. See the table above.
- You’ll probably want a decoupling capacitor to avoid spikes on the output.
An oscilloscope is very handy for debugging PWM if you have access to one. If you don’t have one, I recommend using your sound card and a program such as xoscope.
Pulse Width Modulation
Pulse Width Modulation, or PWM, is a technique for getting analog results with digital means. Digital control is used to create a square wave, a signal switched between on and off. This on-off pattern can simulate voltages in between the full Vcc of the board (e.g., 5 V on UNO, 3.3 V on a MKR board) and off (0 Volts) by changing the portion of the time the signal spends on versus the time that the signal spends off. The duration of “on time” is called the pulse width. To get varying analog values, you change, or modulate, that pulse width. If you repeat this on-off pattern fast enough with an LED for example, the result is as if the signal is a steady voltage between 0 and Vcc controlling the brightness of the LED.
Giới thiệu về Arduino Uno R3
Arduino Uno R3 được sử dụng vi điều khiển ATmega328, tương thích với hầu hết các loại Arduino Shield trên thị trường, có thể gắn thêm các module mở rộng để thực hiện thêm các chức năng như điều khiển motor, kết nối wifi hay các chức năng khác.
Sử dụng ngôn ngữ lập trình C,C++ hoặc Arudino, một ngôn ngữ bắt nguồn từ C,C++ trên phần mềm riêng cho lập trình Arduino IDE.
Các chân nguồn
Arduino Uno R3 được cấp nguồn 5V qua cáp usb hoặc cấp nguồn ngoài thông qua Adaptor chuyển đổi , với điện áp khuyên dùng là khoảng 6-9V. Có thể cấp nguồn từ máy tính qua cổng usb về.
- Các chân 5V, 3.3V là chân dùng để cấp nguồn đầu ra cho các thiết bị chứ không phải chân cấp nguồn vào.
- Vin(Voltage Input): Dùng để cấp nguồn ngoài cho Arduino Uno, nối dương cực vào chân nà và cực âm vào chân GND.
- GND(Ground): Cực âm của nguồn điện cấp cho Arduino Uno. Khi sử dụng các thiết bị sử dụng những nguồn điện riêng biệt thì phải nối các chân này.
- IOREF: Điện áp hoạt động của Arduino, có mức điện áp là 5V. Không được sử dụng để lấy nguồn từ chân này.
- RESET: Việc nhấn nút RESET trên mạch arduino tương tự như khi nối chân RESET với GND qua điện trở 10KΩ.
Các chân vào/ra của Arduino Uno R3
Arduino Uno R3 có 14 chân digital dùng để đọc ghi dữ liệu. Chúng chỉ hoạt động ở 2 mức điện áp 0V và 5V với các dòng vào/ra tối đa trên mỗi chân là 40 mA.
Một số chân digital có chức năng đặc biệt như:
2 chân Serial: 0(RX) và 1(TX): dùng để gửi (transmit – TX) và nhận (Receive – RX) dữ liệu TTL Serial. Arduino Uno có thể giao tiếp với các thiết bị khác thông qua 2 chân này, như gắn thêm màn hình LCD để hiển thị.
Chân PWM: 3, 5,6,9, 10 và 11: Cho phép bạn xuất xung PWM với độ phân giải 8 bit( giá trị từ 0 -> 28-1 tương ứng với 0 – 5V.
Chân giao tiếp SPI: 10(SS), 11(MOSI), 12(MISO), 13(SCK). Ngoài chức năng thông thường, 4 chân này có thể truyền phát dữ liệu bằng giao thức SPI tới các thiết bị khác.
LED 13: Trên arduino có 1 đèn led, khi bấm nút reset thì đèn led này sẽ nhấp nháy để báo hiệu. Nó được nối với chân số 13. Khi chân này được sử dụng, đèn led sẽ sáng.
Arduino Uno R3 có 6 chân analog(A0 -> A5) cung cấp độ phân giải 10 bit(0 → 210-1) để đọc giá trị điện áp trong khoảng 0 -> 5V.
Arduino Uno còn có 2 chân A4(SDA) và A5(SCL) để hỗ trợ giao tiếp I2C/TWI với các thiết bị khác.
Ứng dụng của Arduino Uno R3
Aruino Uno R3 được sử dụng phổ biến trong việc tự thiết kế ra các mạch điện tử như điều khiển led, gửi dữ liệu lên lcd, điều khiển motor,… hay được gắn thêm các Shield để kết nối nhiều module cảm biến khác để thực hiện thêm nhiều chức năng mở rộng như gửi dữ liệu qua wifi.
Ngoài ra, trên thị trường còn có nhiều biến thể của Arduino Uno để thực hiện thêm các tính năng chuyên dụng, ví dụ như mCore, Orion trên mBot được chuyên dụng với việc dễ dàng phân biệt các loại module nào có thể sử dụng cắm vào trên các cổng để trẻ dễ dàng sử dụng.
Vi điều khiển | ATmega328 |
Điện áp hoạt động | 5V(cấp qua cổng usb) |
Điện áp khuyến nghị | 6-9V |
Số chân digital I/O | 14 chân( 6 chân PWM) |
Số chân analog | 6 chân |
Dòng ra tối đa trên mỗi chân I/O | 30 mA |
Dòng ra tối đa (5V) | 500 mA |
Dòng ra tối đa(3.3V) | 50 mA |
Bộ nhớ Flash | 32 KB (ATmega328) với 0.5 KB dùng bởi bootloader |
SRAM | 2 KB(ATmega328) |
EEPROM | 1 KB(ATmega328) |
Giao động của thạch anh | 16 MHz |
Trong bài viết này, bạn sẽ tìm hiểu về PWM là gì và làm thế nào bạn có thể nhận được ngõ ra PWM từ các chân số của Arduino. Để thấy được ứng dụng của PWM, đầu tiên chúng ta sẽ điều khiển độ sáng của một đèn LED thông qua chương trình và sau đó chúng ta sẽ điều khiển bằng tay bằng cách thêm biến trở.
PWM là gì?
PWM là viết tắt của Pulse Width Modulation (Điều chế độ rộng xung) và nó là một kỹ thuật phổ biến được sử dụng để thay đổi độ rộng của các xung trong một chuỗi xung. PWM có nhiều ứng dụng như điều khiển độ sáng của đèn LED, điều khiển tốc độ của động cơ DC, điều khiển động cơ servo hoặc nơi bạn phải lấy ngõ ra analog bằng các thiết bị kỹ thuật số.
Các chân số của Arduino cung cấp cho chúng ta 5V (khi ở mức CAO) hoặc 0V (khi ở mức THẤP) và ngõ ra là một tín hiệu sóng vuông. Vì vậy, nếu chúng ta muốn làm mờ đèn LED, chúng ta không thể lấy điện áp trong khoảng từ 0 đến 5V từ chân số này nhưng chúng ta có thể thay đổi thời gian ON và OFF của tín hiệu. Nếu chúng ta thay đổi thời gian ON và OFF đủ nhanh thì độ sáng của đèn LED sẽ bị thay đổi.
Trước khi tiếp tục những nội dung khác, chúng ta hãy cùng thảo luận về một số thuật ngữ liên quan đến PWM.
Điều chế độ rộng xung về cơ bản là một sóng vuông với thời gian cao và thấp khác nhau. Một tín hiệu PWM cơ bản được hiển thị trong hình dưới đây.
Có một số thuật ngữ liên quan đến PWM mà chúng ta cần phải biết, đó là:
Ton (On-Time): Khoảng thời gian khi tín hiệu ở mức CAO (5V).
Toff (Off Time): Khoảng thời gian khi tín hiệu ở mức THẤP (0V).
Chu kỳ (Period):
Như trong hình trên, Ton biểu thị thời gian ON (thời gian ở mức CAO) và Toff biểu thị thời gian OFF (thời gian ở mức THẤP) của tín hiệu. Chu kỳ là tổng của cả thời gian ON và OFF và được tính theo công thức như sau
Ttotal = Ton + Toff
Chu kỳ làm việc (Duty Cycle):
Chu kỳ làm việc được tính là thời gian ON trong một chu kỳ của tín hiệu. Sử dụng công thức tính chu kỳ ở trên, chu kỳ làm việc được tính như sau
D = (Ton /Ton + Toff) = Ton/Ttotal
Vì vậy, ở chu kỳ làm việc 50% và tần số 1Hz, đèn LED sẽ sáng trong nửa giây và sẽ tắt trong nửa giây còn lại. Nếu chúng ta tăng tần số lên 50Hz (50 lần ON và OFF mỗi giây), thì đèn LED sẽ được nhìn thấy phát sáng ở một nửa độ sáng bằng mắt người.
Biểu đồ sau đây cho thấy sự so sánh của các chu kỳ làm việc khác nhau và mức điện áp tương ứng của chúng.
Từ biểu đồ, rõ ràng là khi tăng chu kỳ làm việc, điện áp ngõ ra (hoặc công suất được cung cấp) cũng tăng lên. Đối với chu kỳ làm việc 100%, điện áp tương ứng là 5V và đối với chu kỳ làm việc 50%, điện áp là 2,5V, v.v…
Arduino và PWM
Arduino IDE có một hàm được tích hợp sẵn “analogWrite()”, có thể được sử dụng để tạo ra một tín hiệu PWM. Nó có thể được sử dụng để điều khiển độ sáng của đèn LED hoặc điều khiển động cơ ở nhiều tốc độ khác nhau. Sau lệnh gọi hàm analogWrite (), chân này sẽ tạo ra một sóng vuông ổn định với chu kỳ làm việc xác định cho đến khi lệnh tiếp theo analogWrite () hoặc digitalRead () hoặc digitalWrite () trên cùng một chân.
Trên Arduino UNO, các chân PWM là 3, 5, 6, 9, 10 và 11. Tần số của tín hiệu PWM trên các chân 5 và 6 sẽ là khoảng 980Hz và trên các chân khác sẽ là 490Hz. Các chân PWM được dán nhãn với dấu ~.
analogWrite(0) có nghĩa là tín hiệu có chu kỳ làm việc 0%.
analogWrite(127) có nghĩa là tín hiệu có chu kỳ làm việc 50%.
analogWrite(255) có nghĩa là tín hiệu có chu kỳ làm việc 100%.
Linh kiện yêu cầu
Bây giờ, chúng ta cần xây dựng một mạch nhỏ để tìm hiểu ứng dụng của điều chế độ rộng xung PWM. Các linh kiện cần thiết cho mạch này được liệt kê dưới đây.
- Arduino UNO
- LED
- Điện trở 220Ω
- Biến trở 10kΩ
- Breadboard
- Dây cắm Breadboard
Điều khiển độ sáng của đèn LED thông qua chương trình
Đầu tiên, thực hiện các kết nối như hình dưới đây.
Kết nối chân anode của đèn LED với chân số 6 của Arduino. Sau đó kết nối điện trở 220Ω với chân cathode của LED và kết nối đầu kia của điện trở với chân nối đất của Arduino.
Bây giờ, chúng ta sẽ viết một đoạn chương trình để thay đổi độ sáng của đèn LED bằng cách sử dụng PWM.
Chương trình Arduino
Nạp chương trình này vào Arduino bằng phần mềm Arduino IDE và đèn LED sẽ bắt đầu mờ dần.
int led_pin = 6; //LED được kết nối với chân số 6 của Arduino
void setup() {pinMode(led_pin, OUTPUT); //Khai báo chân nối LED là chân ngõ ra}
void loop() {//Làm mờ dần LEDfor (int i = 0; i < 255; i++) {analogWrite(led_pin, i);delay(5);}
for (int i = 255; i > 0; i–) {analogWrite(led_pin, i);delay(5);}}
Chương trình Arduino để điều khiển độ sáng của đèn LED bằng biến trở
Trong mạch ở trên, thêm biến trở 10kΩ và kết nối hai đầu biến trở với 5V và GND của Arduino và sau đó kết nối chân giữa của biến trở với chân A0 của Arduino.
Chương trình Arduino
Nạp chương trình này vào Arduino bằng phần mềm Arduino IDE và xoay biến trở, độ sáng của đèn LED sẽ thay đổi.
int led_pin = 6; //LED được nối với chân số 6 của Arduinoint pot_pin = A0; //Chân giữa của biến trở được kết nối với chân tương tự A0 của Arduinoint output;int led_value;
void setup() {pinMode(led_pin, OUTPUT);}
void loop() {//Đọc giá trị từ biến trởoutput = analogRead(pot_pin);//Ánh xạ các giá trị từ 0 đến 255 vì chúng ta có thể đưa ra ngõ ra//giá trị từ 0 -255 bằng cách sử dụng hàm analogwriteled_value = map(output, 0, 1023, 0, 255);analogWrite(led_pin, led_value);delay(1);}
Bit-Banging Pulse Width Modulation
You can “manually” implement PWM on any pin by repeatedly turning the pin on and off for the desired times. e.g.
1void setup()2{3 pinMode(13, OUTPUT);4}56void loop()7{8 digitalWrite(13, HIGH);9 delayMicroseconds(100); // Approximately 10% duty cycle @ 1KHz10 digitalWrite(13, LOW);11 delayMicroseconds(1000 – 100);12}
This technique has the advantage that it can use any digital output pin. In addition, you have full control the duty cycle and frequency. One major disadvantage is that any interrupts will affect the timing, which can cause considerable jitter unless you disable interrupts. A second disadvantage is you can’t leave the output running while the processor does something else. Finally, it’s difficult to determine the appropriate constants for a particular duty cycle and frequency unless you either carefully count cycles, or tweak the values while watching an oscilloscope.
A more elaborate example of manually PWMing all pins may be found here.
Simple Pulse Width Modulation with analogWrite
analogWrite
The Arduino’s programming language makes PWM easy to use; simply call
, where
analogWrite(pin, dutyCycle)
is a value from 0 to 255, and pin is one of the PWM pins (3, 5, 6, 9, 10, or 11). The
dutyCycle
function provides a simple interface to the hardware PWM, but doesn’t provide any control over frequency. (Note that despite the function name, the output is a digital signal, often referred to as a square wave.)
analogWrite()
Probably 99% of the readers can stop here, and just use
, but there are other options that provide more flexibility.
analogWrite
Conclusion
This article helps explain the PWM modes of the Arduino. I found the documentation of the different modes somewhat opaque, and the off-by-one issues unexplained.
Suggested changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. You can read more on how to contribute in the contribution policy.
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.
Arduino Uno R3
Dòng Arduino Uno là dòng phổ thông nhất trong các mạch arduino, hiện nay thế hệ thứ 3(R3) đang là mạch được sử dụng phổ biến, được sử dụng để tự thiết kế các mạch điện tử như điều khiển led, đo nhiệt độ – độ ẩm hiển thị lên lcd hay các ứng dụng khác.
PWM Examples
PWM has several uses:
- Dimming an LED
- Providing an analog output; if the digital output is filtered, it will provide an analog voltage between 0% and 100%.
- Generating audio signals.
- Providing variable speed control for motors.
- Generating a modulated signal, for example to drive an infrared LED for a remote control.
Keywords searched by users: arduino uno r3 pwm
Categories: Tóm tắt 61 Arduino Uno R3 Pwm
See more here: kientrucannam.vn
See more: https://kientrucannam.vn/vn/