ESP8266 Basic управляем реле GPIO и PCF8574 через web и http

Использование системы в различных ситуациях, вопросы программирования сценариев.

Модератор: immortal

Ответить
immortal
Сообщения: 1138
Зарегистрирован: Вт янв 29, 2013 9:16 am
Откуда: Белозерск
Благодарил (а): 16 раз
Поблагодарили: 400 раз
Контактная информация:

ESP8266 Basic управляем реле GPIO и PCF8574 через web и http

Сообщение immortal » Вс янв 22, 2017 1:30 am

Среди множества языков для ESP8266 нашлось место и языку Basic, при чем в отличии от программирования на языке Lua писать Basic программы мы будем прямо через браузер не используя com порт компьютера и UART разъем модуля ESP8266.

На официальном сайтекачаем прошивку и прошиваем модуль, для Windows сделан прошивальщик, для Linux имеются bin файлы, но прошив их в Linux мне не удалось запустить модуль, поэтому пришлось искать машину с Windows и прошивать Windows прошивальщиком.
Запустив модуль первый раз он работает в режиме точки доступа, подключаемся к точке доступа ESP и заходим по адресу http://192.168.4.1, увидим главную страницу
на странице SETTINGS настраиваем параметры подключения к нашей точке доступа.
Выделение_036.png
Выделение_036.png (36.08 КБ) 4030 просмотров
если Вы установите галочку Menu bar Disable то меню не будет отображаться на главной странице, если установите галочку Run default.bas at startup то будет запускаться программа на Basic из файла default.bas
Файлы можно посмотреть на странице FILE MANAGER, отредактировать файл default.bas можно на странице EDIT
Its work!
Заходим на страницу EDIT и пишем в поле кода:

Код: Выделить всё

print "I'ts work!" 
чтобы посмотреть результат нажмите на вкладку RUN или если у Вас установлена галочка Run default.bas at startup то перезагрузите модуль и зайдите на главную страницу.
Управление GPIO
Управлять GPIO можно разными способами, в описанном примере мы будем управлять GPIO с помощью кнопок.
Управление состоянием GPIO осуществляется командой io которая имеет следующий сиснаксис

Код: Выделить всё

io(РЕЖИМ,GPIO_НОМЕР,СОСТОЯНИЕ) 
где РЕЖИМ может принимать следующие значения
po - режим выхода СОСТОЯНИЕ может принимать значение 0 или 1
pwo - режим PWM, СОСТОЯНИЕ может принимать значение от 0 до 1023
servo - режим управления сервоприводом, СОСТОЯНИЕ от 0 до 180
таким образом команда подать на GPIO12 логическую единицу будет выглядеть следующим образом

Код: Выделить всё

io(po,12,1) 
В самом начале выполняется программа до команды wait
кнопка добавляется командой

Код: Выделить всё

button ИМЯ_КНОПКИ, МЕТКА
ИМЯ_КНОПКИ - это значение или переменная, МЕТКА - это название метки по которой произойдет переход при нажатии.
Программа будет начинаться с заголовка и содержать 4 кнопки.

Код: Выделить всё

print "<b>ESP8266</b></br>"
button "GPIO12 on", [1]
button "GPIO12 off", [2]
button "GPIO13 on", [3]
button "GPIO13 off", [4]
wait
результатом будет web страница с 4-я кнопками
но кнопки ещё ничего не делают, чтобы они делали нам надо написать 4 подпрограммы в которых будет выполняться код включения/выключения GPIO, весь код будет выглядеть так:

Код: Выделить всё

print "<b>ESP8266</b></br>"
button "GPIO12 on", [1]
button "GPIO12 off", [2]
button "GPIO13 on", [3]
button "GPIO13 off", [4]
wait
[1]
io(po,12,1) 
wait
[2]
io(po,12,0) 
wait
[3]
io(po,13,1) 
wait
[4]
io(po,13,0) 
wait
каждая подпрограмма заканчивается командой wait, теперь у нас включаются/выключаются GPIO12 и GPIO13
Но не удобно управлять одним GPIO двумя кнопками, поэтому состояние GPIO мы зададим в переменной и будем использовать логическое исключение оператор XOR и перед переключением выхода мы будем определять состояние выхода командой

Код: Выделить всё

io(laststat,GPIO_НОМЕР) 
Получиться следующий код

Код: Выделить всё

print "<b>ESP8266</b></br>"
button "GPIO12", [1]
button "GPIO13", [2]
wait
[1]
gpio = io(laststat,12) 
gpio = gpio xor 1
io(po,12,gpio) 
wait
[2]
gpio = io(laststat,13)
gpio = gpio xor 1
io(po,13,gpio) 
wait
Теперь у нас всё то же самое делается двумя кнопками но значительно меньшим кодом, для расширения управления остальными GPIO просто добавьте кнопки и подпрограммы.
Код для управления всеми GPIO
СпойлерПоказать

Код: Выделить всё

print "<b>ESP8266</b></br>"
button "GPIO0", [0]
button "GPIO1", [1]
button "GPIO2", [2]
button "GPIO3", [3]
button "GPIO4", [4]
button "GPIO5", [5]
button "GPIO12", [12]
button "GPIO13", [13]
button "GPIO14", [14]
button "GPIO15", [15]
wait

[0]
gpio = io(laststat,0) 
gpio = gpio xor 1
io(po,0,gpio) 
wait
[1]
gpio = io(laststat,1) 
gpio = gpio xor 1
io(po,1,gpio) 
wait
[2]
gpio = io(laststat,2) 
gpio = gpio xor 1
io(po,2,gpio) 
wait
[3]
gpio = io(laststat,3) 
gpio = gpio xor 1
io(po,3,gpio) 
wait
[4]
gpio = io(laststat,4) 
gpio = gpio xor 1
io(po,4,gpio) 
wait
[5]
gpio = io(laststat,5) 
gpio = gpio xor 1
io(po,5,gpio) 
wait
[12]
gpio = io(laststat,12) 
gpio = gpio xor 1
io(po,12,gpio) 
wait
[13]
gpio = io(laststat,13) 
gpio = gpio xor 1
io(po,13,gpio) 
wait
[14]
gpio = io(laststat,14) 
gpio = gpio xor 1
io(po,14,gpio) 
wait
[15]
gpio = io(laststat,15) 
gpio = gpio xor 1
io(po,15,gpio) 
wait
если у Вас реле используется инверсное, то в начале надо добавить чтобы на всех GPIO была логическая единица командой

io(po,GPIO_НОМЕР,1)

иначе при первом нажатии реле не включится, поскольку состояние измениться на 1.
Управление расширителем портов PCF8574

работа с i2c шиной на GPIO0 и GPIO2 соответственно SDA и SCL, но можно переназначить GPIO командой

Код: Выделить всё

i2c.setup({SDA}, {SCL}) 
напишем сканер i2c устройств

Код: Выделить всё

for address = 1 to 127
   i2c.begin(address)
   stat = i2c.end()
   if stat < 1 then
     ' print stat
      wprint "I2C device: 0x" & hex(address)
      wprint " - > " & address
      wprint " <br>"
 endif
next
wait
у меня подключено 2 микросхемы PCF8574 поэтому результатом выполнения программы будет
Теперь добавим кнопки для включения/выключения GPIO и подпрограммы - обработчики этих кнопок
СпойлерПоказать

Код: Выделить всё

let address = 32 'PCF8574 I2C Address
i2c.begin(address)
ss = 0 xor 255
i2c.write(ss)
i2c.end()
button "1", [p1]
button "2", [p2]
button "3", [p3]
button "4", [p4]
button "5", [p5]
button "6", [p6]
button "7", [p7]
button "8", [p8]
button "OFF", [p0]
wait
[p0]
i2c.begin(address)
ss = 0 xor 255
i2c.write(ss)
i2c.end()
wait
[p1]
i2c.begin(address)
ss = ss xor 1
i2c.write(ss)
i2c.end()
wait
[p2]
i2c.begin(address)
ss = ss xor 2
i2c.write(ss)
i2c.end()
wait
[p3]
i2c.begin(address)
ss = ss xor 4
i2c.write(ss)
i2c.end()
wait
[p4]
i2c.begin(address)
ss = ss xor 8
i2c.write(ss)
i2c.end()
wait
[p5]
i2c.begin(address)
ss = ss xor 16
i2c.write(ss)
i2c.end()
wait
[p6]
i2c.begin(address)
ss = ss xor 32
i2c.write(ss)
i2c.end()
wait
[p7]
i2c.begin(address)
ss = ss xor 64
i2c.write(ss)
i2c.end()
wait
[p8]
i2c.begin(address)
ss = ss xor 128
i2c.write(ss)
i2c.end()
wait
Ну и код для 2-х модулей PCF8574
СпойлерПоказать

Код: Выделить всё

print "<b>ESP8266</b><br>"
for address = 1 to 127
   i2c.begin(address)
   stat = i2c.end()
   if stat < 1 then
     ' print stat
      wprint "I2C device: 0x" & hex(address)
      wprint " - > " & address
      wprint " <br>"
 endif
next


let address = 32 'PCF8574 I2C Address
let address2 = 33 'PCF8574 I2C Address

i2c.begin(address)
ss = 0 xor 255
i2c.write(ss)
i2c.end()
i2c.begin(address2)
ss2 = 0 xor 255
i2c.write(ss2)
i2c.end()


button "1", [p1]
button "2", [p2]
button "3", [p3]
button "4", [p4]
button "5", [p5]
button "6", [p6]
button "7", [p7]
button "8", [p8]
button "9", [p9]
button "10", [p10]
button "11", [p11]
button "12", [p12]
button "13", [p13]
button "14", [p14]
button "15", [p15]
button "16", [p16]
print ""
button "OFF", [p0]
wait

[p0]
i2c.begin(address)
ss = 0 xor 255
i2c.write(ss)
i2c.end()
i2c.begin(address2)
ss2 = 0 xor 255
i2c.write(ss2)
i2c.end()
wait

[p1]
i2c.begin(address)
ss = ss xor 1
i2c.write(ss)
i2c.end()
wait

[p2]
i2c.begin(address)
ss = ss xor 2
i2c.write(ss)
i2c.end()
wait

[p3]
i2c.begin(address)
ss = ss xor 4
i2c.write(ss)
i2c.end()
wait

[p4]
i2c.begin(address)
ss = ss xor 8
i2c.write(ss)
i2c.end()
wait

[p5]
i2c.begin(address)
ss = ss xor 16
i2c.write(ss)
i2c.end()
wait

[p6]
i2c.begin(address)
ss = ss xor 32
i2c.write(ss)
i2c.end()
wait

[p7]
i2c.begin(address)
ss = ss xor 64
i2c.write(ss)
i2c.end()
wait

[p8]
i2c.begin(address)
ss = ss xor 128
i2c.write(ss)
i2c.end()
wait

[p9]
i2c.begin(address2)
ss2 = ss2 xor 1
i2c.write(ss2)
i2c.end()
wait

[p10]
i2c.begin(address2)
ss2 = ss2 xor 2
i2c.write(ss2)
i2c.end()
wait

[p11]
i2c.begin(address2)
ss2 = ss2 xor 4
i2c.write(ss2)
i2c.end()
wait

[p12]
i2c.begin(address2)
ss2 = ss2 xor 8
i2c.write(ss2)
i2c.end()
wait

[p13]
i2c.begin(address2)
ss2 = ss2 xor 16
i2c.write(ss2)
i2c.end()
wait

[p14]
i2c.begin(address2)
ss2 = ss2 xor 32
i2c.write(ss2)
i2c.end()
wait

[p15]
i2c.begin(address2)
ss2 = ss2 xor 64
i2c.write(ss2)
i2c.end()
wait

[p16]
i2c.begin(address2)
ss2 = ss2 xor 128
i2c.write(ss2)
i2c.end()
wait
Название меток я сделал отличными от меток в коде управления GPIO модуля для возможности совмещения кода.

Управление с помощью http запросов.

Для принятия модулем данных используется команда

Код: Выделить всё

msgbranch МЕТКА
msgbranch переходит по МЕТКЕ когда имеется URL запрос вида ESP-IP-address/msg?

Код обработки будет выглядеть так

Код: Выделить всё

print "<b>ESP8266</b></br>"
msgbranch [mybranch]
wait
[mybranch]
pinNo = val(msgget("pin"))
wait
в данном примере переменной pinNo присваивается значение переданное значение pin, в примере передается pin=2

http://192.168.4.1/msg?pin=2

для опроса состояния GPIO мы воспользуемся командой

Код: Выделить всё

io(laststat,GPIO_НОМЕР) 
Сделаем по команде переключение состояния GPIO

Код: Выделить всё

print "<b>ESP8266</b></br>"
msgbranch [mybranch]
wait

[mybranch]
pinNo = val(msgget("pin"))
gpio = io(laststat,pinNo)
gpio = gpio xor 1
io(po,pinNo,gpio) 
wait
теперь GPIO будут переключаться по http

Теперь совместим все программы, управление кнопками, управление PCF8574 и управление по http, получаем следующий код
СпойлерПоказать

Код: Выделить всё

print "<b>ESP8266</b><br>"
msgbranch [mybranch]
let address = 32 'PCF8574 I2C Address
let address2 = 33 'PCF8574 I2C Address

i2c.begin(address)
ss = 0 xor 255
i2c.write(ss)
i2c.end()
i2c.begin(address2)
ss2 = 0 xor 255
i2c.write(ss2)
i2c.end()
'у меня инвертированные реле поэтому на всех выходах делаем логическую единицу
io(po,1,1) 
io(po,1,3) 
io(po,1,4) 
io(po,1,5) 
io(po,1,12) 
io(po,1,13) 
io(po,1,14) 
io(po,1,15) 
'кнопки
button "GPIO1", [1]
button "GPIO3", [3]
button "GPIO4", [4]
button "GPIO5", [5]
button "GPIO12", [12]
button "GPIO13", [13]
button "GPIO14", [14]
button "1", [p1]
button "2", [p2]
button "3", [p3]
button "4", [p4]
button "5", [p5]
button "6", [p6]
button "7", [p7]
button "8", [p8]
button "9", [p9]
button "10", [p10]
button "11", [p11]
button "12", [p12]
button "13", [p13]
button "14", [p14]
button "15", [p15]
button "16", [p16]
print ""
button "OFF", [p0]
wait

[mybranch]
pinNo = msgget("pin")
if pinNo = "1" then goto [1]
if pinNo = "2" then goto [3]
if pinNo = "4" then goto [4]
if pinNo = "5" then goto [5]
if pinNo = "12" then goto [12]
if pinNo = "13" then goto [13]
if pinNo = "14" then goto [14]
if pinNo = "p1" then goto [p1]
if pinNo = "p2" then goto [p2]
if pinNo = "p3" then goto [p3]
if pinNo = "p4" then goto [p4]
if pinNo = "p5" then goto [p5]
if pinNo = "p6" then goto [p6]
if pinNo = "p7" then goto [p7]
if pinNo = "p8" then goto [p8]
if pinNo = "p9" then goto [p9]
if pinNo = "p10" then goto [p10]
if pinNo = "p11" then goto [p11]
if pinNo = "p12" then goto [p12]
if pinNo = "p13" then goto [p13]
if pinNo = "p14" then goto [p14]
if pinNo = "p15" then goto [p15]
if pinNo = "p16" then goto [p16]
wait

[1]
gpio = io(laststat,1) 
gpio = gpio xor 1
io(po,1,gpio) 
wait
[3]
gpio = io(laststat,3) 
gpio = gpio xor 1
io(po,3,gpio) 
wait
[4]
gpio = io(laststat,4) 
gpio = gpio xor 1
io(po,4,gpio) 
wait
[5]
gpio = io(laststat,5) 
gpio = gpio xor 1
io(po,5,gpio) 
wait
[12]
gpio = io(laststat,12) 
gpio = gpio xor 1
io(po,12,gpio) 
wait
[13]
gpio = io(laststat,13) 
gpio = gpio xor 1
io(po,13,gpio) 
wait
[14]
gpio = io(laststat,14) 
gpio = gpio xor 1
io(po,14,gpio) 
wait
[p0]
i2c.begin(address)
ss = 0 xor 255
i2c.write(ss)
i2c.end()
i2c.begin(address2)
ss2 = 0 xor 255
i2c.write(ss2)
i2c.end()
wait
[p1]
i2c.begin(address)
ss = ss xor 1
i2c.write(ss)
i2c.end()
wait
[p2]
i2c.begin(address)
ss = ss xor 2
i2c.write(ss)
i2c.end()
wait
[p3]
i2c.begin(address)
ss = ss xor 4
i2c.write(ss)
i2c.end()
wait
[p4]
i2c.begin(address)
ss = ss xor 8
i2c.write(ss)
i2c.end()
wait
[p5]
i2c.begin(address)
ss = ss xor 16
i2c.write(ss)
i2c.end()
wait
[p6]
i2c.begin(address)
ss = ss xor 32
i2c.write(ss)
i2c.end()
wait
[p7]
i2c.begin(address)
ss = ss xor 64
i2c.write(ss)
i2c.end()
wait
[p8]
i2c.begin(address)
ss = ss xor 128
i2c.write(ss)
i2c.end()
wait
[p9]
i2c.begin(address2)
ss2 = ss2 xor 1
i2c.write(ss2)
i2c.end()
wait
[p10]
i2c.begin(address2)
ss2 = ss2 xor 2
i2c.write(ss2)
i2c.end()
wait
[p11]
i2c.begin(address2)
ss2 = ss2 xor 4
i2c.write(ss2)
i2c.end()
wait
[p12]
i2c.begin(address2)
ss2 = ss2 xor 8
i2c.write(ss2)
i2c.end()
wait
[p13]
i2c.begin(address2)
ss2 = ss2 xor 16
i2c.write(ss2)
i2c.end()
wait
[p14]
i2c.begin(address2)
ss2 = ss2 xor 32
i2c.write(ss2)
i2c.end()
wait
[p15]
i2c.begin(address2)
ss2 = ss2 xor 64
i2c.write(ss2)
i2c.end()
wait
[p16]
i2c.begin(address2)
ss2 = ss2 xor 128
i2c.write(ss2)
i2c.end()
wait
теперь можно управлять реле подключенными к GPIO модуля или к PCF8574 командой
http://192.168.1.172/msg?pin=НОМЕР_ПИНА
где НОМЕР_ПИНА - номер GPIO модуля (1,3,4,5,12,13,14,15) или номер вывода на PCF8574 (p1,p2,p3...p16)
Поскольку GPIO0 и GPIO2 заняты шиной i2c по которой подключены PCF8574 то мы их исключили, так же исключен GPIO15 поскольку при подключении инверсированного реле к GPIO15 модуль не загружается.
За это сообщение автора immortal поблагодарили (всего 7):
ToteMeiSter (Вс янв 22, 2017 5:06 am) • Руслан (Вс янв 22, 2017 6:16 am) • serghei (Вс янв 22, 2017 12:19 pm) • banderos (Вс янв 22, 2017 1:00 pm) • Victor_S (Пн янв 23, 2017 8:47 am) • Ko/|xo3HUk (Ср янв 25, 2017 2:00 pm) • omelchuk890 (Пт май 12, 2017 9:04 am)
Рейтинг: 8.14%
Lubuntu на cubieboard2 + ds9490R
DietPi на Orange Pi PC + 1wire на esp8266 с прошивкой Homes-smart.ru
Ответить