ESP-8266/ESP32 NodeMCU Lua: азы программирования.

Тема в разделе "ESP8266, ESP32", создана пользователем ИгорьК, 25 июл 2017.

  1. ИгорьК

    ИгорьК Оракул Модератор

    Шаг назад.
    Забудьте про таймер(вообще!) и напишите функцию, первый вызов которой запускает шим, а следующий - останавливает. И так попеременно.
    Дергайте эту функцию вручную, через ESPlorer.

    Забудьте на время о таймере, он здесь не главный.
     
  2. ИгорьК

    ИгорьК Оракул Модератор

    Суть таймера - с заданной периодичностью "дергать" функцию! Это простое и тупое явление.

    Функция - главное!

    Эту функцию вам придётся писать в любом языке программирования. И выглядеть она будет везде приблизительно одинаково.


    Функция должна при вызове проверять текущее состояние исполнительного элемента и менять его на другое. Лучше сделать глобальную переменную, в которое это состояние записывается, читать переменную при вызове функции, менять состояние и записывать новое в переменную.
     
    Последнее редактирование: 29 май 2020
  3. ИгорьК

    ИгорьК Оракул Модератор


    Код (Lua):
    do
    pin = 2
    pwm.setup(pin, 1000, 512)
    pwm.start(pin)
    tmr.create():alarm(1000, tmr.ALARM_SINGLE,
    end
    И все встанет на место.
    При отправке из окна ESPlorer без do...end код предкомпилируется и исполняется построчно, там интерпретатору нужно время на обдумывание. Отправка блока заставляет интерпретатор прочитать сначала весь код
     
    Последнее редактирование: 29 май 2020
  4. Nikomas

    Nikomas Нерд

    Код (Lua):

    do
    flag = true -- глобальная переменная
    cnt = 1 -- счетчик
    function piezo_on()
       if flag == true then -- если глобальная переменная true
         print('Beep ON') -- печатаем Beep ON
         pwm.start() -- запускаем ШИМ
         flag = false -- меняем глобалную переменную на false
         cnt = cnt + 1 -- счетчик запусков ШИМ
         if cnt > 5 then -- если счетчик >5
           pwm.close() -- закрываем ШИМ
           print('Done') -- печатаем Done
         end
       else
         flag = false -- если глобальная переменная false
         print('Beep OFF') -- печатаем Beep OFF
         pwm.stop() -- останавливаем ШИМ
         flag = true -- меняем глобальную переменную на true
       end
    end
    end
     
    Супер. Спасибо.
     
    Последнее редактирование: 29 май 2020
    ИгорьК нравится это.
  5. ИгорьК

    ИгорьК Оракул Модератор

    Отлично. Теперь сделайте следующее:

    1. Создайте таймер, который имеет название, например tmrbeep.
    2. Функцией таймера, а не пищалки проверяйте счетчик.
    3. Если счетчик меньше - вызывается ваша функция. Если счетчик больше необходимого значения, таймер сбрасывает счетчик и останавливает сам себя через внутреннюю ссылку. Читайте мои разъяснения к таймеру, что я привел.
    4. Запуск вашей пищалки будет осуществляться стартом таймера tmrbeep:start()

    upload_2020-5-29_12-27-0.png


    Общая логика. Когда необходимо, вы запускаете таймер, который проверяет счетчик и вызывает функцию работы с бипером. Когда количество писков достигнуто - таймер сбрасывает счетчик и останавливается.

    P.S. Конечно, все это можно сделать и внутри таймера, одной анонимной функцией. И когда-нибудь Вы это сделаете. Но пока слона проще есть кусочками.
     
    Последнее редактирование: 29 май 2020
  6. Nikomas

    Nikomas Нерд

    Код (Lua):

    do
       flag = true -- глобальная переменная
       cnt = 1 -- счетчик
       
       function beep()
         if flag == true then -- если глобальная переменная true  
           print('Beep ON') -- печатаем Beep ON
           pwm.start(2) -- запускаем ШИМ
           flag = false -- меняем глобалную переменную на false
           cnt = cnt + 1 -- счетчик запусков ШИМ
           if cnt > 5 then -- если счетчик >5
             pwm.close(2) -- закрываем ШИМ
             print('Done') -- печатаем Done
           end
         else
           flag = false -- если глобальная переменная false
           print('Beep OFF') -- печатаем Beep OFF
           pwm.stop(2) -- останавливаем ШИМ
           flag = true -- меняем глобальную переменную на true
         end
       end
       if cnt < 5 then -- если счетчик меньше 5, а он меньше, то
         tmrBeep = tmr.create() -- создаем таймер tmrBeep
         tmrBeep:register(2000, tmr.ALARM_AUTO,beep) -- регистрируем чем он будет заниматься
         tmrBeep:start() -- запускаем таймер
         print('Timer starting')
       else
         cnt = 1 -- если счетчик больше 5, то сбрасываем его на знач. по умолчанию
         tmrBeep:stop() -- останавливаем таймер
         tmrBeep:unregister() -- удаляем таймер
       end
    end
     
    Ругается на невозможность запуска PWM - Panic error
     
    Последнее редактирование: 29 май 2020
  7. ИгорьК

    ИгорьК Оракул Модератор

    Если у вас необходимо разное количество "бипов" в зависимости от обстановки , то алгорит
    Конечно. Ибо
    1. вы (малый ребенок?) забыли выполнить pwm.setup(pin, clock, duty)
    2. сделали не так, как я советую.
     
  8. Nikomas

    Nikomas Нерд

    Далеко не малый, но что-то я проглядел. Согласен))
    В таймере уже ведь есть функция beep:
    Код (Lua):
    tmrBeep:register(2000, tmr.ALARM_AUTO,beep)
    как туда можно еще добавить
    Код (Lua):
    if cnt > 5 then
        pwm.close(2)
        print('Done')
    end
     
    Последнее редактирование: 29 май 2020
  9. ИгорьК

    ИгорьК Оракул Модератор

    Код (Lua):
    do
        pin = 2
        flag = true
        cnt = 0
        pwm.setup(pin, 1000, 512)
        tmrBeep = tmr.create()

        function beep()
            if flag == true then
                print('Beep ON')
                pwm.start(2)
                flag = false
            else
                print('Beep OFF')
                pwm.stop(2)
                flag = true
            end
            cnt = cnt - 1
        end

        tmrBeep:register(2000, tmr.ALARM_AUTO, function(t)
            if cnt > 0 then
                beep()  
            else
                t:stop()
                print('Done')
            end
        end)
        -------------------
        -- запускаем на 5 сигналов
        cnt = 10
        tmrBeep:start()
    end
    В таком коде вы можете для разных случаев запускать любое количество сигналов. Установите cnt и стартуйте таймер. Также можете менять длительность, меняя время таймера.
     
    Последнее редактирование: 29 май 2020
    Nikomas нравится это.
  10. Nikomas

    Nikomas Нерд

    Спасибо. Буду вникать.
     
  11. ИгорьК

    ИгорьК Оракул Модератор

    Вникайте сюда:
    Код (Lua):
    do
        -- local beep, beepstart, tmrBeep, pin, flag, cnt
        pin = 2
        flag = true
        cnt = 0
        pwm.setup(pin, 1000, 512)
        tmrBeep = tmr.create()

        beep = function()
            if flag then
                print('Beep ON'); pwm.start(2)
            else
                print('Beep OFF'); pwm.stop(2)
            end
            flag = flag == false and true or false
            cnt = cnt - 1
        end

        tmrBeep:register(1000, tmr.ALARM_AUTO, function(t)
            if cnt > 0 then return beep()
            else t:stop(); print('Done')
            end
        end)

        beepstart = function(count, long)
            cnt = count*2 or 10
            long = long*1000 or 1000
            tmrBeep:interval(long)
            tmrBeep:start()
        end
        beepstart(5, 2)
        --  beepstart(3, 0.1)
        --  beepstart(2, 0.01)
    end
    ... я уж не знаю, на каком языке можно сделать еще проще.
     
    Последнее редактирование: 30 май 2020
    swc и Nikomas нравится это.
  12. sashan

    sashan Нуб

    Как-то быстро пролетела тема про modbus и там был esp32. А реализовать modbus на ESP8266 возможно?
     
  13. ИгорьК

    ИгорьК Оракул Модератор

    Можно но не(так)удобно.
     
    Последнее редактирование: 14 июн 2020
  14. ИгорьК

    ИгорьК Оракул Модератор

    Надо узнать i2c адрес? Узнаем:

    Код (Lua):
    do
        SDA = 6 -- sda pin, GPIO12
        SCL = 5 -- scl pin, GPIO14
        addr = 2
        id = 0
        ans = false
        adrtbl = {}
        i2c.setup(id, SDA, SCL, i2c.SLOW)
        function search(addr)
            print('Ask '..'0x'.. string.format("%0X", addr))
            i2c.start(id)
            ans = i2c.address(id, addr, i2c.TRANSMITTER)
            i2c.stop(id)
            if ans then
                print('Got Address!')
                adrtbl[#adrtbl+1] ='0x'.. string.format("%0X", addr)
            end
        end
        print('\n')    
        tmr.create():alarm(200, 1, function(t)
            addr = addr + 1
            if addr < 127 then
                search(addr)
            else
                t:stop()
                t:unregister()
                t = nil
                print('\nGot addresses:')
                table.foreach(adrtbl, print)
            end
        end)
    end

    upload_2020-6-18_18-52-55.png
     
    Последнее редактирование: 18 июн 2020
  15. Valeriy_esp

    Valeriy_esp Нерд

    Любви и здравия.
    Язык в "никуда". Большинство ваших Игорь примеров и примеры из книги Роберту Иерузалимски не работают. Чему учиться? Лжи?
    У меня NodeMCU Diy Kit V3. И надо-то снять в трёх точках температуру и в двух точках влажность. Пытаюсь разобраться. С помощью первой функции получил адрес датчика (равен 8). А дальше текст скрипта и молчание, хотя в текст включены "принт" для распечатки промежуточных результатов. А принт расположенный в конце файла ds18b20m, говорит о том, что программа была завершена и переменные удалены. nodemcu-firmware скачана последняя, и её версия 3.0 ..., Пробовал версию 2.2.1, как и вы рекомендовали. Но безрезультатно. Забросить его этот модуль что ли?
     
  16. ИгорьК

    ИгорьК Оракул Модератор

    Хороший заход. Ладно я, но профессор университета в немилости...
    Не лгите! Идите честно в среду Ардуино и там обязательно решатся все ваши задачи. (Здесь слона продать уже не получится.)
     
  17. SergeiL

    SergeiL Оракул Модератор

    А может и правда забросить?
    С таким подходом, не думаю что будет положительный результат.
     
  18. ИгорьК

    ИгорьК Оракул Модератор

    Что, и в Ардуино не возьмут? :)
     
  19. SergeiL

    SergeiL Оракул Модератор

    А нужно? :)
    Мы вроде ничего не должны товарищу :)
     
    ИгорьК нравится это.
  20. Valeriy_esp

    Valeriy_esp Нерд

    • 5.10. Запрещено публиковать исходный код без BB-кода — CODE.
    Пример из книги: стр.66
    print(table.unpack{10,20,30}) —- 10 20 30
    a,b = table.unpack!10,20,30} -- a=10, b=20, 30 отбрасывается

    Пример проще не куда:
    а что на мониторе:
    print(table.unpack{10,20,30})
    Lua error: stdin:1: attempt to call field 'unpack' (a nil value)
    stack traceback:
    stdin:1: in main chunk
    [C]: ?
    [C]: ?a,b = table.unpack!10,20,30}
    Lua error: stdin:1: unexpected symbol near '!'
    -----
    А вот ваш пример:
    do
    function callbk(data)
    print("Now Start Callback Function!")
    print(string.format("%.02f", data))
    end

    function getrand(call)
    local sum = 0
    for i = 1, 5000 do
    sum = sum + math.random()
    --print(sum)
    end
    if call then call(sum)end
    end

    getrand(callbk)
    end

    а что на мониторе:
    do
    >> function callbk(data)
    Waiting answer from ESP - Timeout reached. Command aborted.
     
    ИгорьК нравится это.