MicroPython:Платы/ESP8266/Краткий справочник по ESP8266

Материал из Онлайн справочника
Версия от 20:05, 23 мая 2023; EducationBot (обсуждение | вклад)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Краткий справочник по ESP8266[1]

Плата Adafruit Feather HUZZAH (источник изображения – Adafruit).

Материал ниже – краткий справочник по платам на базе ESP8266. Если вы впервые работаете с такой

платой, советуем сначала прочесть вот эти разделы:

Установка MicroPython

Читайте соответствующий раздел «Подготовка к работе с MicroPython на ESP8266». Там также есть подраздел «Решение проблем с установкой» (1.7).

Общее управление платой

REPL MicroPython работает на порте UART0 (GPIO1=TX, GPIO3=RX) на скорости 115200 бод. Чтобы узнать, какие методы есть в объекте, используйте автодополнение с помощью клавиши  Tab ⇆ . Чтобы вставить в REPL большой кусок Python-кода, используйте режим вставки ( Ctrl + E ).

Модуль machine:

import machine

machine.freq()          # узнать текущую частоту CPU
machine.freq(160000000) # задать частоту CPU на 160 МГц

Модуль esp:

import esp

esp.osdebug(None)       # отключить отладочные сообщения ОС
esp.osdebug(0)          # перенаправить отладочные сообщения ОС на 
                          UART(0)

Сеть

Модуль network:

import network

wlan = network.WLAN(network.STA_IF) # создать интерфейс для работы
                                    # в режиме станции
wlan.active(True)       # активировать интерфейс
wlan.scan()             # сканировать точки доступа
wlan.isconnected()      # проверить, подключена ли станция 
                        # к точке доступа
wlan.connect('essid', 'пароль') # подключиться к точке доступа
wlan.config('mac')      # прочесть MAC-адрес интерфейса
wlan.ifconfig()         # прочесть IP, маску подсети
                        # сетевой шлюз и DNS-сервер интерфейса

ap = network.WLAN(network.AP_IF) # создать интерфейс для работы
                                 # в режиме точки доступа
ap.active(True)         # активировать интерфейс
ap.config(essid='ESP-AP') # задать ESSID точки доступа

Полезная функция для подключения к вашей локальной WiFi-сети:

def do_connect():
    import network
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print('подключение к сети...')
        wlan.connect('essid', 'пароль')
        while not wlan.isconnected():
            pass
    print('настройки сети:', wlan.ifconfig())

Выполнив подключение к сети, вы сможете использовать модуль socket, позволяющий в обычном режиме использовать TCP/UDP-сокеты.

Задержки и синхронизация

Используйте модуль time.

import time

time.sleep(1)           # войти в режим сна на 1 секунду
time.sleep_ms(500)      # войти в режим сна на 500 миллисекунд
time.sleep_us(10)       # войти в режим сна на 10 микросекунд
start = time.ticks_ms() # прочесть показания счетчика миллисекунд
delta = time.ticks_diff(time.ticks_ms(), start) # рассчитать 
                                                # разницу времени

Таймеры

MicroPython поддерживает использование виртуальных RTOS-таймеров. Используйте для этого класс machine.Timer с ID таймера «-1».

from machine import Timer

tim = Timer(-1)
tim.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1))
tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(2))

Значение в переменной period рассчитывается в миллисекундах.

Контакты и GPIO

Используйте класс machine.Pin.

from machine import Pin

p0 = Pin(0, Pin.OUT)    # создать выходной контакт на GPIO0
p0.on()                 # задать контакту значение «вкл» или «1»
p0.off()                # задать контакту значение «выкл» или «0»
p0.value(1)             # задать контакту значение «вкл» или «1»

p2 = Pin(2, Pin.IN)     # создать входной контакт на GPIO2
print(p2.value())       # прочесть значение («0» или «1»)

p4 = Pin(4, Pin.IN, Pin.PULL_UP) # включить встроенный
                                 # подтягивающий резистор
p5 = Pin(5, Pin.OUT, value=1) # создать выходной контакт 
                              # и присвоить ему значение «1»

Для использования доступны контакты 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16 – все они соответствуют номерам GPIO-контактов на чипе ESP8266. Помните, что у многих плат имеется собственная нумерация контактов (с обозначениями вроде D0, D1 и т.д.). Поскольку MicroPython поддерживает разные платы и модули, эта нумерация, привязанная к физическим контактам чипа, была выбрана в качестве наименьшего общего знаменателя. Поэтому, чтобы узнать точное соответствие между физическими и логическими контактами своей модели, проконсультируйтесь у производителя платы.

Помните, что контакты 1 и 3 – это, соответственно, передающий (TX) и приемный (RX) UART-контакты для REPL. Также помните, что 16-ый контакт – это специальный контакт (используемый для выхода из режима глубокого сна), который может быть не доступен для использования высокоуровневыми классами вроде Neopixel.

UART (последовательная шина)

См. machine.UART.

from machine import UART
uart = UART(0, baudrate=9600)
uart.write('привет')
uart.read(5) # прочесть до пяти байтов

MicroPython поддерживает использование двух UART-портов. UART0 находится на контактах 1 (TX) и 3 (RX). Это порт, работающий в обоих направлениях, и по умолчанию он используется для REPL. Порт UART1 работает на контактах 2 (TX) и 8 (RX), но контакт 8 также используется для подключения к чипу флеш-памяти, поэтому у UART1 только передающий (TX) контакт.

Когда UART0 подключен к REPL, все символы, приходящие на этот порт, идут прямиком в stdin, поэтому uart.read() всегда будет возвращать None. Поэтому, если вам нужно прочесть символы из UART0, но он уже используется для REPL, используйте sys.stdin.read() (или отключите REPL от UART0, прочтите данные, а потом снова подключите). Когда REPL отключен от UART0, его можно использовать и для других целей.

Если при запуске REPL (будь то мягкая или полная перезагрузка) в dupterm-слотах нет объектов, UART0 будет подключен по умолчанию. Без UART0 и REPL единственный способ восстановить плату – это полностью стереть и перезаписать прошивку (что установит стандартный «boot.py», в котором REPL будет уже подключен).

Чтобы отключить REPL от UART0, используйте:

import uos
uos.dupterm(None, 1)

По умолчанию REPL подключен к UART0. Если вы отключили его, то подключить обратно можно вот так:

import uos, machine
uart = machine.UART(0, 115200)
uos.dupterm(uart, 1)

ШИМ (широтно-импульсная модуляция)

ШИМ можно включить на всех контактах, кроме 16-го, но на всех этих каналах можно передавать лишь одну частоту в диапазоне между 1 и 1000 Гц. Коэффициент заполнения – между 0 и 1023 включительно.

Используйте класс machine.PWM:

from machine import Pin, PWM

pwm0 = PWM(Pin(0))      # создать ШИМ-объект на контакте 0
pwm0.freq()             # прочесть текущую частоту
pwm0.freq(1000)         # задать частоту
pwm0.duty()             # прочесть текущий коэффициент заполнения
pwm0.duty(200)          # задать коэффициент заполнения
pwm0.deinit()           # выключить ШИМ на контакте

pwm2 = PWM(Pin(2), freq=500, duty=512) # создать ШИМ-объект
                                       # и сразу же настроить его

АЦП (аналогово-цифровое преобразование)

Для АЦП используется специальный контакт. Помните, что входное напряжение на АЦП должно быть в диапазоне между 0 и 1 вольтом.

Используйте класс machine.ADC:

from machine import ADC

adc = ADC(0)            # создать АЦП-объект на АЦП-контакте
adc.read()              # прочесть значение («0-1024»)

Программная шина SPI

В MicroPython для ESP8266 реализовано два SPI-драйвера. Один реализован программно (с помощью технологии «bit-banging»), работает на всех контактах и доступен через класс machine.SPI.

from machine import Pin, SPI

# создаем SPI-шину на заданных контактах;
# значение «polarity» отвечает за то, 
# находится ли линия SCK в состоянии простоя или нет; 
# «phase=0» значит, что выборка данных происходит
# на переднем фронте тактового сигнала, а «phase=1» - на заднем.
spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))

spi.init(baudrate=200000) # задать скорость коммуникации в бодах

spi.read(10)            # прочесть 10 байт на MISO-линии
spi.read(10, 0xff)      # прочесть 10 байт, попутно передавая
                        # на MOSI-линию значение «0xff»

buf = bytearray(50)     # создать буфер 
spi.readinto(buf)       # сохранить считанные данные в заданный буфер
                        # (в данном случае его размер будет 50 байт)
spi.readinto(buf, 0xff) # сохранить считанные данные в заданный буфер
                        # и передать на MOSI-линию значение «0xff» 

spi.write(b'12345')     # записать 5 байт на MOSI-линию

buf = bytearray(4)      # создать буфер
spi.write_readinto(b'1234', buf) # записать на MOSI-линию
                                 # и прочесть из MISO-линии в буфер
spi.write_readinto(buf, buf) # записать данные буфера в MOSI-линию
                             # и сохранить данные из MISO в буфер

Аппаратная шина SPI

Аппаратный SPI работает быстрее (до 80 МГц) программного, но только на следующих контактах: GPIO12 (MISO), GPIO13 (MOSI) и GPIO14 (SCK). У него те же методы, что и у программного SPI (см. раздел выше), кроме параметров контактов для конструктора и init() (т.к. они фиксированные):

from machine import Pin, SPI

hspi = SPI(1, baudrate=80000000, polarity=0, phase=0)

SPI(0) используется для FlashROM и недоступен пользователям.

Шина I2C

Драйвер I2C реализован программно, работает на всех контактах и доступен через класс machine.I2C:

from machine import Pin, I2C

# создать шину I2C:
i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000)

i2c.readfrom(0x3a, 4)   # прочесть 4 байта с ведомого устройства
                        # с адресом «0x3a»
i2c.writeto(0x3a, '12') # записать «12» на ведомое устройство
                        # с адресом «0x3a»

buf = bytearray(10)     # создать буфер с 10 байтами
i2c.writeto(0x3a, buf)  # записать данные из заданного буфера
                        # на ведомое устройство

Часы реального времени (RTC)

См. класс machine.RTC.

from machine import RTC

rtc = RTC()
rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # задать дату и время
rtc.datetime() # прочесть дату и время

# синхронизация с NTP (нужно подключение к WiFi):
import ntptime
ntptime.settime() # задать RTC-данные о дате и времени
                  # на основе данных дистанционного сервера
rtc.datetime()    # прочесть RTC-данные о дате и времени
                  # в стандарте всемирного координированного времени

Примечание: В этом классе реализованы не все методы: RTC.now(), RTC.irq(handler=*)(в параметре можно задать пользовательскую функцию), RTC.init() и RTC.deinit() в данный момент не поддерживаются.

Режим глубокого сна

Код ниже можно использовать для входа в режим глубокого сна, пробуждения и проверки того, является ли причиной перезагрузки выход из режима глубокого сна. Но для этого контакт GPIO16 сначала нужно подключить к контакту сброса (на HUZZAH это «RST»):

import machine

# настроить RTC.ALARM0, чтобы устройство 
# можно было вывести из режима глубокого сна:
rtc = machine.RTC()
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)

# проверить, является ли причиной перезагрузки
# выход из режима глубокого сна:
if machine.reset_cause() == machine.DEEPSLEEP_RESET:
    print('woke from a deep sleep')

# настроить RTC.ALARM0 на запуск
# через 10 секунд (пробуждение устройства):
rtc.alarm(rtc.ALARM0, 10000)

# перевести устройство в режим глубокого сна:
machine.deepsleep()

Шина OneWire

Драйвер OneWire реализована программно и работает на всех контактах:

from machine import Pin
import onewire

ow = onewire.OneWire(Pin(12)) # создать шину OneWire на GPIO12
ow.scan()               # вернуть список устройств,
                        # подключенных к шине
ow.reset()              # сбросить шину
ow.readbyte()           # прочесть байт
ow.writebyte(0x12)      # записать байт на шину
ow.write('123')         # записать байты на шину
ow.select_rom(b'12345678') # выбрать устройство по его ROM-коду

Есть также специальный драйвер для устройств DS18S20 и DS18B20:

import time, ds18x20
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
ds.convert_temp()
time.sleep_ms(750)
for rom in roms:
    print(ds.read_temp(rom))

Убедитесь, что на линии данных включен подтягивающий резистор на 4.7 кОм. И помните, что при каждом считывании данных о температуре нужно вызывать метод convert_temp().

Драйвер для NeoPixel

Используйте модуль neopixel:

from machine import Pin
from neopixel import NeoPixel

pin = Pin(0, Pin.OUT)   # перевести GPIO0 в режим вывода данных
                        # для управления устройствами NeoPixel
np = NeoPixel(pin, 8)   # создать NeoPixel-драйвер
                        # на GPIO0 для 8 пикселей
np[0] = (255, 255, 255) # сделать первый пиксель белым
np.write()              # записать данные на все пиксели
r, g, b = np[0]         # прочесть цвет первого пикселя

Для низкоуровневого управления устройствами NeoPixel:

import esp
esp.neopixel_write(pin, grb_buf, is800khz)

Драйвер для APA102

Используйте модуль apa102:

from machine import Pin
from apa102 import APA102

clock = Pin(14, Pin.OUT)     # перевести GPIO14 в режим вывода данных
                             # для управления тактовой частотой
data = Pin(13, Pin.OUT)      # перевести GPIO13 в режим вывода данных 
                             # для управления данными
apa = APA102(clock, data, 8) # создать драйвер APA102 на контактах
                             # для тактовой частоты и данных
                             # для 8 пикселей 
apa[0] = (255, 255, 255, 31) # сделать первый пиксель белым
                             # с максимальной яркостью «31»
apa.write()                  # записать данные на все пиксели 
r, g, b, brightness = apa[0] # задать цвет первого пикселя

Для низкоуровневого управления APA102:

import esp
esp.apa102_write(clock_pin, data_pin, rgbi_buf)

Драйвер для DHT-датчиков

DHT-драйвер реализован программно и работает на всех контактах:

import dht
import machine

d = dht.DHT11(machine.Pin(4))
d.measure()
d.temperature() # например, 23 (градуса Цельсия)
d.humidity()    # например, 41 (% относительной влажности)

d = dht.DHT22(machine.Pin(4))
d.measure()
d.temperature() # например 23.6 (градуса Цельсия)
d.humidity()    # например, 41.3 (% относительной влажности)

WebREPL (интерактивная браузерная командная строка)

WebREPL (REPL, реализованная через WebSockets и доступная через браузер) – это экспериментальная функция порта MicroPython для ESP8266. Загрузите веб-клиент отсюда (или воспользуйтесь клиентом, уже развернутом на сервере сайта micropython.org), а затем настройте его, выполнив следующее…

import webrepl_setup

…а затем следуя инструкциям на экране. Подключиться к WebREPL можно будет после перезагрузки. Если у вас отключен автоматический запуск WebREPL при загрузке, вы всегда можете запустить демон WebREPL сами при помощи:

import webrepl
webrepl.start()

В MicroPython поддерживается WebREPL через подключение к точке доступа ESP8266, но если режим станции активен, демон WebREPL запустится и на нем, поэтому если ваш роутер настроен и исправно работает, вы можете использовать WebREPL, будучи подключенным к обычной точке доступа в интернет (если у вас возникли какие-то проблемы, используйте подключение к точке доступа ESP8266).

Помимо доступа к командной строке (терминалу), в WebREPL также есть функционал для загрузки (и отправки, и получения) файлов. В веб-клиенте для этих функций есть соответствующие кнопки, или же вы можете воспользоваться клиентом командной строки webrepl_cli.py из репозитория выше.

Также есть другие способы для отправки и получения файлов на ESP8266, созданные и поддерживаемые сообществом MicroPython. Ищите эти альтернативы на форуме MicroPython.

См.также

Внешние ссылки