Bài 4 - Điểu chỉnh độ sáng của đèn LED bằng phương pháp PWM

 

Chương trình của chúng ta sẽ hoạt động như sau: độ sáng đèn LED sẽ tăng dần đến max, sau đó độ sáng từ max sẽ giảm dần về 0, cứ thế lặp lại

Sơ đồ mạch như sau:

 


Để chiều chỉnh độ sáng của đèn LED ta thay đổi điện áp đặt vào nó. Các chân GPIO trên ESP8266 chỉ có thể đặt điện áp ở đầu ra là 0V hoặc 3,3V, không thể cài đặt điện áp ở đầu ra nằm ở giá trị giữa 0V và 3,3V (ví dụ 1V, 1,4V, 2V .. để thay đổi độ sáng). Tuy nhiên, có thể tạo ra điện áp "giả" ở giá trị giữa 0V và 3,3V bằng cách sử dụng điều chế độ rộng xung (PWM). Nếu bật(đặt điện áp 3,3V vào LED) và tắt(đặt điện áp 0V vào LED) đèn LED rất nhanh (tần số bật tắt khoảng 42Hz), mắt của chúng ta không thể theo kịp tốc độ bật và tắt của đèn LED, chúng ta sẽ chỉ thấy sự thay về độ sáng (nếu bật tắt chậm dưới 42Hz, chúng ta sẽ chỉ thấy LED đang nhấp nháy).

Duty cycle là khoảng thời gian LED được bật, hình minh họa cách hoạt động của PWM


              Duty cycle 50% cho kết quả độ sáng của LED là 50%, duty cycle 0% cho độ sáng LED 0%, duty cycle 100% cho độ sáng LED là 100%. Thay đổi  duty cycle sẽ điều chỉnh được độ sáng của LED.

              Để khởi tạo PWM trên ESP8266 chúng ta dùng hàm sau



                trong đó:

                        - uint32 period: là chu kỳ PWM tính bằng μs

                        - uint8 *duty: duty cycle của từng channel

                        - uint32 pwm_channel_num: số channel PWM muốn sử dụng

- uint32 (*pin_info_list)[3]:  tham số GPIO cho các channel, đây là n * 3 array (n là số channel muốn sử dụng), array[3] gồm 3 tham số {GPIO register, GPIO function, GPIO number}  xem hình ở bài trước.

ví dụ: chúng ta dùng GPIO2 làm 1 channel PWM như sau:

uint32 io_info [1][3] = {PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2, 2};.

Còn muốn dùng GPIO2, GPIO5, GPIO12 làm 3 channel PWM thì:

uint32 io_info [3][3] = {{PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2, 2}, {PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5,5}, {PERIPHS_IO_MUX_MTDI_U,FUNC_GPIO12,12} };

            

 Sau khi cài đặt các thông số ta gọi pwm_start();


              Để set duty cylce ta dùng hàm sau:

              trong đó:

- uint32 duty: giá trị duty muốn xuất ra, dãi giá trị duty phụ thuộc vào chu kỳ (period), max duty = Period * 1000 /45.

- uint8 channel: channel PWM muốn xuất ra, nếu dung 3 channel PWM thì các giá trị channel có thể là 0, 1, 2.

 BIÊN DỊCH VÀ NẠP VÀO ESP8266

Copy thư mục 3-blinkLED , đổi tên thành 4-PWM-LED sau đó mở Eclipse import vào (xem hướng dẫn import ở bài trước).

Mở file Makefile trong thư mục 4-PWM-LED/app, thêm dòng -lpwm \ như hình bên dưới




 

Chỉnh sửa file user_main.c trong thư mục 4-PWM-LED/app/user có nội dung toàn bộ như sau:

#include "osapi.h"

#include "user_interface.h"

#include "gpio.h"

#include "ets_sys.h"

#include "pwm.h"

 

 

static os_timer_t pwm_timer; //khởi tạo soft timer cho pwm

uint32 io_info [1][3] = {PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12, 12};//GPIO12 cho channel 1

uint32 period = 1000; // chu kỳ 1000us

int32 duty[1] = {0};//khai báo duty cho 1 channel

int32 max_duty = 1000*1000/45; //công thức tính max_duty = period*1000/45

uint32 pwm_channel_num = 1; //chỉ dùng 1 channel pwm

int32 percent = 10; //phần trăm tỷ lệ tăng hoặc giảm độ sáng

int incre_or_decre = 1; // 1 tăng, -1 giảm

 

void pwm_cb(void)

{

       pwm_set_duty(duty[0], 0); // cài đặt giá trị duty cho channel 0

       pwm_start();

       duty[0] = duty[0] + (max_duty*percent/100)* incre_or_decre;

 

       if (duty[0] > max_duty) {

             duty[0] = max_duty;

             incre_or_decre = -1;   // giảm duty xuống

       }

 

       if (duty[0] < 0) {

             duty[0] = 0;

             incre_or_decre = 1;   // tăng duty lên

       }

}

 

 

void ICACHE_FLASH_ATTR

user_init(void)

{

       uart_init(115200,115200);

       os_printf("\n=======================================\n");

    os_printf("\t\t SDK version: %s \n", system_get_sdk_version());

    os_printf("\n=======================================\n");

 

    pwm_init(period, duty, pwm_channel_num, io_info); //khởi tạo PWM

    pwm_start();

 

    os_timer_disarm(&pwm_timer); //Stop pwm_timer

    os_timer_setfn(&pwm_timer, (os_timer_func_t *)pwm_cb, NULL);//cài đặt hàm được gọi khi pwm_timer đếm xong

    os_timer_arm(&pwm_timer, 250, true);//kích hoạt led_timer với 500ms, true nghĩa lặp đi lặp lại timer 500ms này

}

 

/******************************************************************************

 * FunctionName : user_rf_cal_sector_set

 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.

 *                We add this function to force users to set rf cal sector, since

 *                we don't know which sector is free in user's application.

 *                sector map for last several sectors : ABCCC

 *                A : rf cal

 *                B : rf init data

 *                C : sdk parameters

 * Parameters   : none

 * Returns      : rf cal sector

*******************************************************************************/

uint32 ICACHE_FLASH_ATTR

user_rf_cal_sector_set(void)

{

    enum flash_size_map size_map = system_get_flash_size_map();

    uint32 rf_cal_sec = 0;

 

    switch (size_map) {

        case FLASH_SIZE_4M_MAP_256_256:

            rf_cal_sec = 128 - 5;

            break;

 

        case FLASH_SIZE_8M_MAP_512_512:

            rf_cal_sec = 256 - 5;

            break;

 

        case FLASH_SIZE_16M_MAP_512_512:

        case FLASH_SIZE_16M_MAP_1024_1024:

            rf_cal_sec = 512 - 5;

            break;

 

        case FLASH_SIZE_32M_MAP_512_512:

        case FLASH_SIZE_32M_MAP_1024_1024:

            rf_cal_sec = 1024 - 5;

            break;

 

        case FLASH_SIZE_64M_MAP_1024_1024:

            rf_cal_sec = 2048 - 5;

            break;

        case FLASH_SIZE_128M_MAP_1024_1024:

            rf_cal_sec = 4096 - 5;

            break;

        default:

            rf_cal_sec = 0;

            break;

    }

 

    return rf_cal_sec;

}

 

void ICACHE_FLASH_ATTR

user_rf_pre_init(void)

{

}

 

 Biên dịch vào nạp vào ESP8266, xem bài trước có hướng dẫn nạp.  

Nhận xét

Bài đăng phổ biến từ blog này

Điều khiển đèn bằng router Dlink DIR615C2 thông qua web.

Bài 3 - Blink LED

Mod USB cho Router wifi DLink DIR615 E4