Генериране на PWM сигнали с ESP8266 и MicroPython: Практически примери

Генериране на PWM сигнали с ESP8266 и MicroPython Практически примери

PWM (Pulse Width Modulation) или Широчинно-импулсна модулация е широко използвана техника за управление на мощността на електронни компоненти, като например LED диоди и мотори. В тази статия ще разгледаме два примера за генериране на PWM сигнали с ESP8266, използвайки MicroPython.

Генериране на PWM сигнал и отпечатване на резултатите

Примерен код за генериране на PWM сигнал и отпечатване на резултатите:

from machine import Pin, PWM
from time import sleep

frequency = 5000 # честота в Hz
led = PWM(Pin(0), frequency)

while True:
    
  sleep(1)

  for duty_cycle in range(0, 1023):
    led.duty(duty_cycle)
    print(duty_cycle)
    sleep(0.01)
    

Обяснение:

Инициализация на PWM пин
led = PWM(Pin(0), frequency)
  • PWM (Pulse Width Modulation): PWM е техника, при която се генерира цифров сигнал, който редува включване и изключване на определен пин (в случая GPIO0) с определена честота и duty cycle (съотношение между времето, през което сигналът е включен, и общото време на цикъла). Това съотношение управлява средната мощност, подавана на устройството, което е свързано към пина (например светодиод).
  • Pin(0): В този ред Pin(0) посочва GPIO0 на ESP8266, който ще се използва за генериране на PWM сигнала. В този пример се приема, че на този пин е свързан светодиод или друго устройство, което ще бъде управлявано чрез PWM.
  • Честота (frequency): frequency = 5000 задава честотата на PWM сигнала на 5000 Hz. Това означава, че PWM сигналът ще се включва и изключва 5000 пъти в секунда. По-високата честота води до по-плавно управление на устройството, например по-плавна промяна в яркостта на светодиода.
Основен цикъл
while True:
    sleep(1)

    for duty_cycle in range(0, 1023):
        led.duty(duty_cycle)
        print(duty_cycle)
        sleep(0.01)
  • Безкраен цикъл (while True): Този цикъл се изпълнява непрекъснато, докато програмата работи. Това е основният цикъл на програмата, в който се извършват всички операции по генериране и управление на PWM сигнала.
  • Забавяне (sleep(1)): Първото забавяне от 1 секунда позволява на устройството да се стабилизира, преди да започне да променя PWM сигнала. Включването на този ред не е задължително!
  • Промяна на duty_cycle (for duty_cycle in range(0, 1023)): В този вътрешен цикъл се преминава през всички стойности на duty_cycle от 0 до 1023. Тези стойности представляват 10-битова резолюция, където 0 означава, че PWM сигналът е изключен през целия цикъл, а 1023 означава, че е включен през целия цикъл.
  • Задаване на duty cycle (led.duty(duty_cycle)): Тази команда задава стойността на duty_cycle за PWM сигнала. Например, ако duty_cycle = 512, това означава, че сигналът ще бъде включен през половината от времето на цикъла и изключен през останалата част (или ще е на 50%).
  • Принтиране в конзолата (print(duty_cycle)): Всяка стойност на duty_cycle се отпечатва в конзолата, което позволява да следим как се променя PWM сигналът в реално време.
  • Забавяне между промени на duty cycle (sleep(0.01)): След всяка промяна на duty_cycle има кратко забавяне от 0.01 секунди. Това забавяне осигурява плавно и постепенно увеличаване на интензитета на светодиода. Ако не беше приложено това забавяне, светодиодът щеше да променя своя интензитет твърде бързо, което би направило ефекта по-малко забележим.

Управление на PWM чрез аналогов вход

В този пример ще покажем как да използваме потенциометър за управление на duty_cycle на PWM сигнал чрез изчитане на аналогова стойност от ADC (Analog to Digital Converter).

Преди да започнем трябва да разгледаме схемата и да свържем компонентите. За да разгледате пин диаграмта (pinout) на ESP8266 и в нашия случай D1 mini, разгледайте нашето ревю за този процесор на страницата ни: ESP8266 D1 Mini – Малък, но Мощен Wi-Fi Микроконтролер.

Схема на свързване:

Примерен код за управление на PWM чрез аналогов вход:

from machine import ADC, PWM, Pin
from time import sleep

# map function
def _map(x, in_min, in_max, out_min, out_max):
    return int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)

pot = ADC(0)                   # Инициализация на ADC (функционира само с ADC(0) за ESP8266)
frequency = 5000               # Задаване на честота на PWM
led = PWM(Pin(14), frequency)  # Инициализация на PWM pin

while True:
    
    try:
        pot_value = pot.read()  # Прочитане на стойността от потенциометъра (0-1023)
        #print(pot_value)
        
        if pot_value < 10:
            pot_value = 0
            
        map_led = _map(pot_value, 0, 1023, 0, 100)  # Преобразуване на стойността за PWM
        print("pot_value = ", pot_value, "||","duty = ", map_led)
   
        led.duty(pot_value)  # Задаване на PWM duty cycle
      
        sleep(0.05)

    except KeyboardInterrupt:
        print("exit")
        break

Обяснение:

Този код за ESP8266 демонстрира как да се използва аналоговият вход (ADC) за четене на стойността от потенциометър и как тази стойност може да бъде преобразувана и използвана за управление на PWM (Pulse Width Modulation) сигнал, който управлява интензитета на светодиод. В предишната ни статия разгледахме как се изчита аналогова стойност с ESP8266 и MicroPython. Ако сте я пропуснали може първо да я разгледате. Тя ще донесе допълнителна яснота върху този код.

.

Импортиране на библиотеки и инициализация
from machine import ADC, PWM, Pin
from time import sleep
  • from machine import ADC, PWM, Pin: Импортира основните класове от библиотеката machine на MicroPython, които ще бъдат използвани за работа с хардуерните компоненти.
  • ADC: Аналогово-цифров преобразувател (АЦП), който ще чете аналоговите стойности от потенциометъра.
  • PWM: Широчинно-импулсна модулация, която ще управлява интензитета на светодиода.
  • Pin: Позволява достъп до GPIO пиновете на ESP8266.
  • from time import sleep: Импортира функцията sleep, която ще бъде използвана за въвеждане на забавяне между операциите.
Функция _map
def _map(x, in_min, in_max, out_min, out_max):
    return int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
  • Функцията _map е изключително важна, защото позволява преобразуване на една стойност от един диапазон към друг. Това е особено полезно, когато искате да адаптирате аналогова стойност (от АЦП) към подходящ диапазон за PWM.
  • Аргументи на функцията:
  • x: Входна стойност, която ще бъде преобразувана.
  • in_min и in_max: Минималната и максималната стойност на входния диапазон.
  • out_min и out_max: Минималната и максималната стойност на изходния диапазон.
  • Примерно обяснение: Ако потенциометърът подава стойност 512, функцията _map ще я преобразува в нов диапазон, например от 0 до 100, който е подходящ за управление на duty cycle на PWM. Това позволява стойността от потенциометъра да бъде адаптирана към изходен сигнал, който може да управлява светодиод или друг компонент.
Инициализация на ADC и PWM
pot = ADC(0)                   # Инициализация на ADC (функционира само с ADC(0) за ESP8266)
frequency = 5000               # Задаване на честота на PWM
led = PWM(Pin(14), frequency)  # Инициализация на PWM pin
  • ADC(0): Инициализира АЦП на пин 0, който ще чете аналоговите сигнали от потенциометъра. При ESP8266, единствено ADC(0) е валиден.
  • frequency = 5000: Задава честотата на PWM сигнала на 5000 Hz.
  • PWM(Pin(14), frequency): Инициализира PWM на GPIO14 с честота 5000 Hz, който ще управлява интензитета на светодиод или друг компонент.
Основен цикъл
while True:
    try:
        pot_value = pot.read()  # Прочитане на стойността от потенциометъра (0-1023)
        if pot_value < 10:
            pot_value = 0
            
        map_led = _map(pot_value, 0, 1023, 0, 100)  # Преобразуване на стойността за PWM
        print("pot_value = ", pot_value, "||","duty = ", map_led)
   
        led.duty(pot_value)  # Задаване на PWM duty cycle
      
        sleep(0.05)

    except KeyboardInterrupt:
        print("exit")
        break
  • Четене на стойността от потенциометъра:
  • pot_value = pot.read(): Прочита аналоговата стойност от потенциометъра. Стойността е между 0 и 1023.
  • Ако стойността е по-малка от 10, тя се закръгля до 0 (if pot_value < 10: pot_value = 0), за да се избегнат шумове.
  • Превръщане на стойността за PWM:
  • map_led = _map(pot_value, 0, 1023, 0, 100): Преобразува стойността от потенциометъра (0-1023) към диапазон, подходящ за duty cycle на PWM (например 0-100).
  • Управление на PWM:
  • led.duty(pot_value): Задава duty cycle на PWM сигнала спрямо стойността от потенциометъра.
  • Забавяне и обработка на прекъсвания:
  • sleep(0.05): Въвежда малко забавяне между циклите за по-плавна работа.
  • except KeyboardInterrupt: Ако бъде натиснат Ctrl+C, програмата излиза от цикъла и приключва работата си.

Заключение

Тези два примера демонстрират как лесно може да се генерират и управляват PWM сигнали с ESP8266, използвайки MicroPython. В първия пример показахме как се генерира PWM сигнал с променящ се duty_cycle, а във втория пример демонстрирахме как аналогов вход от потенциометър може да се използва за динамично управление на PWM. Това е полезно в различни приложения като контрол на яркостта на LED или регулиране на скоростта на двигатели. Може да разгледате видео инструкции тук.