• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь Вложенные функции

CyanoFresh

New member
Всем привет. Задача сделать плавный переход на led 'e по цветам радуги - 8 раз. Функция для запуска выглядит так:
Код:
function doRainbow()
    -- Fade to red
    fadeRgbTo(1023, 0, 0, function()
        -- Fade to orange
        fadeRgbTo(1023, 512, 0, function()
            -- Fade to yellow
            fadeRgbTo(1023, 1023, 0, function()
                -- Fade to green
                fadeRgbTo(0, 1023, 0, function()
                    -- Fade to blue
                    fadeRgbTo(0, 1023, 1023, function()
                        -- Fade to full blue
                        fadeRgbTo(0, 0, 1023, function()
                            -- Fade to violet
                            fadeRgbTo(512, 0, 1023, function()
                                -- Fade to magenta
                                fadeRgbTo(1023, 0, 1023, function()
                                    -- Repeat again
                                    doRainbow()
                                end)
                            end)
                        end)
                    end)
                end)
            end)
        end)
    end)
end
но при запуске плата зависает при запуске основного файла. если убрать последние 3 функции - работает некоторое время, но при попытке отправить heap() - ресетится. Если оставить только 1 функцию - все работает, кроме самого перехода ))
Как можно исправить? Возможно есть другие методы плавного перехода по цветам?
Нашел похожую тему на гитхабе: Too many levels of nested functions causes a reset · Issue #254 · nodemcu/nodemcu-firmware · GitHub там сказано смириться
 

pvvx

Активный участник сообщества
Всем привет. Задача сделать плавный переход на led 'e по цветам радуги - 8 раз.
У ESP стек мал. Он и так переполняется в NodeMCU Lua и затирает переменные ROM-BIOS, а потом к ним обращается :)
А тут ещё вы вложение стека делаете...
rom_bss_end = 0x3FFFEB30 /* staсk: 0x3FFFEB30..0x3FFFFFFF 0x14D0 = 5328 bytes */ на всё!
Внутренний "буфер" у Lau на ESP для функций тоже мал и очень быстро переполняется.
Для среднего уровня интерпретатора Lua на ESP8266 не хватает дополнительных сотни килобайт. По этому он урезан по всему функционалу. Т.е. считать что это Lua уже не приходится.
 
Последнее редактирование:

nikolz

Well-known member
Всем привет. Задача сделать плавный переход на led 'e по цветам радуги - 8 раз. Функция для запуска выглядит так:
Код:
function doRainbow()
    -- Fade to red
    fadeRgbTo(1023, 0, 0, function()
        -- Fade to orange
        fadeRgbTo(1023, 512, 0, function()
            -- Fade to yellow
            fadeRgbTo(1023, 1023, 0, function()
                -- Fade to green
                fadeRgbTo(0, 1023, 0, function()
                    -- Fade to blue
                    fadeRgbTo(0, 1023, 1023, function()
                        -- Fade to full blue
                        fadeRgbTo(0, 0, 1023, function()
                            -- Fade to violet
                            fadeRgbTo(512, 0, 1023, function()
                                -- Fade to magenta
                                fadeRgbTo(1023, 0, 1023, function()
                                    -- Repeat again
                                    doRainbow()
                                end)
                            end)
                        end)
                    end)
                end)
            end)
        end)
    end)
end
но при запуске плата зависает при запуске основного файла. если убрать последние 3 функции - работает некоторое время, но при попытке отправить heap() - ресетится. Если оставить только 1 функцию - все работает, кроме самого перехода ))
Как можно исправить? Возможно есть другие методы плавного перехода по цветам?
Нашел похожую тему на гитхабе: Too many levels of nested functions causes a reset · Issue #254 · nodemcu/nodemcu-firmware · GitHub там сказано смириться
Попробуйте применить табличный способ описания состояний.
т е делаете таблицу с набором значений и потом перебираете таблицу по строкам.
Затраты памяти и времени сократятся раз в 100.
 

CyanoFresh

New member
У ESP стек мал. Он и так переполняется в NodeMCU Lua и затирает переменные ROM-BIOS, а потом к ним обращается :)
А тут ещё вы вложение стека делаете...
rom_bss_end = 0x3FFFEB30 /* staсk: 0x3FFFEB30..0x3FFFFFFF 0x14D0 = 5328 bytes */ на всё!
Внутренний "буфер" у Lau на ESP для функций тоже мал и очень быстро переполняется.
Для среднего уровня интерпретатора Lua на ESP8266 не хватает дополнительных сотни килобайт. По этому он урезан по всему функционалу. Т.е. считать что это Lua уже не приходится.
Ясно, спасибо за объяснение.
 

CyanoFresh

New member
Попробуйте применить табличный способ описания состояний.
т е делаете таблицу с набором значений и потом перебираете таблицу по строкам.
Затраты памяти и времени сократятся раз в 100.
Можно пример, пожалуйста? lua не мой основной язык, но вроде понимаю, о чем вы
 

nikolz

Well-known member
Можно пример, пожалуйста? lua не мой основной язык, но вроде понимаю, о чем вы
Напишите на привычном Вам языке, я перепишу Вам на луа или на Си.
Либо напишите подробно свою задачу, а то из Вашего шедевра выше сложно понять, что вы делаете.
 

CyanoFresh

New member
Напишите на привычном Вам языке, я перепишу Вам на луа или на Си.
Либо напишите подробно свою задачу, а то из Вашего шедевра выше сложно понять, что вы делаете.
Нужно циклически плавно менять цвет на rgb ленте по некоторым цветам(пока что - цвета радуги, но можно изменять). От ленты подключены 3 пина - red, green, blue. Цвет меняется через pwm. Не знаю как еще подробнее можно обьяснить)
Вот, что делает функция fadeRgbTo() из первого поста:

Код:
function fadeRgbTo(toRed, toGreen, toBlue, callback)
    local currentRed = pwm.getduty(redPin)
    local currentGreen = pwm.getduty(greenPin)
    local currentBlue = pwm.getduty(bluePin)

    print("Fading from " .. currentRed .. " to " .. toRed)
    print("Fading from " .. currentGreen .. " to " .. toGreen)
    print("Fading from " .. currentBlue .. " to " .. toBlue)

    local timerID = 3

    tmr.alarm(timerID, 20, tmr.ALARM_AUTO, function()
        if currentRed < toRed then
            currentRed = (currentRed + 1)
            print("Red", currentRed)
            pwm.setduty(redPin, currentRed)
        elseif currentRed > toRed then
            currentRed = (currentRed - 1)
            print("Red", currentRed)
            pwm.setduty(redPin, currentRed)
        end

        if currentGreen < toGreen then
            currentGreen = (currentGreen + 1)
            print("Green", currentGreen)
            pwm.setduty(greenPin, currentGreen)
        elseif currentGreen > toGreen then
            currentGreen = (currentGreen - 1)
            print("Green", currentGreen)
            pwm.setduty(greenPin, currentGreen)
        end

        if currentBlue < toBlue then
            currentBlue = (currentBlue + 1)
            print("Blue", currentBlue)
            pwm.setduty(bluePin, currentBlue)
        elseif currentBlue > toBlue then
            currentBlue = (currentBlue - 1)
            print("Blue", currentBlue)
            pwm.setduty(bluePin, currentBlue)
        end

        if (currentRed == toRed and currentGreen == toGreen and currentBlue == toBlue) then
            tmr.stop(timerID)

            print("Done")

            if callback ~= nil then
                callback()
            end
        end
    end)
end
 

nikolz

Well-known member
Поясните, почему в первом примере функции вложены, а не вызываются последовательно в цикле.
Если надо делать 8 раз, то где цикл на эти 8.
 

nikolz

Well-known member
Более того, у Вас вложены колбеки. Это где Вы такое решение нашли?
 

nikolz

Well-known member
Например, если надо включить 8 различных цветов, то пишем так:
local t={
{1023, 0, 0},
{1023, 512, 0},
{1023, 1023, 0},
{0, 1023, 0},
{0, 1023, 1023},
{512, 0, 1023},
{1023, 0, 1023},
}

for i=1,8,1 do
local t1=t
fadeRgbTo2(t1[1],t1[2],t1[3]) -- эта функция управление светом передаются три числа, которые выбираются из t
end
 

CyanoFresh

New member
Более того, у Вас вложены колбеки. Это где Вы такое решение нашли?
но ведь lua асинхронна, а если вызывать их вместе - они будут выполнятся вместе, или я чего не понимаю?)
Может не указал, но мне нужно пройтись по всем цветам по очереди, то есть первый цвет плавно переходит во второй, потом второй в третий, и т.д.
 

nikolz

Well-known member
но ведь lua асинхронна, а если вызывать их вместе - они будут выполнятся вместе, или я чего не понимаю?)
Может не указал, но мне нужно пройтись по всем цветам по очереди, то есть первый цвет плавно переходит во второй, потом второй в третий, и т.д.
Каким образом реализуется плавность перехода?
 

nikolz

Well-known member
можно написать так
for i=1,#t do
local t1=t
fadeRgbTo2(t1[1],t1[2],t1[3]) -- эта функция управление светом передаются три числа, которые выбираются из t
end
В таблицу t забиваете тройки чисел для плавного перехода и будет Вам плавный переход
 

CyanoFresh

New member
Каким образом реализуется плавность перехода?
вот этим кодом:
Код:
tmr.alarm(timerID, 20, tmr.ALARM_AUTO, function()
        if currentRed < toRed then
            currentRed = (currentRed + 1)
            print("Red", currentRed)
            pwm.setduty(redPin, currentRed)
        elseif currentRed > toRed then
            currentRed = (currentRed - 1)
            print("Red", currentRed)
            pwm.setduty(redPin, currentRed)
        end
        ....
каждые 20мс отнимает от значения pwm единицу - так и получается плавность
 

nikolz

Well-known member
Это конечно, решение, но как по мне слишком костыльно.
Сколько будет весить файл и таблица, если захардкодить значения?
Плавность можете делать как хотите, я лишь показал пример как реализовать любое количество цветов. Учитывая тот факт, что ESP-12 имеет минимум 3 Мбайта свободного флеш, Вы получите фактически бесконечное число цветов.
Применение таблиц - это классика, а вот вложение колбек функций - это костыльно.
-------------------------------------
Не плюй в корытце, пригодится воды напиться.
 

Юрий Ботов

Moderator
Команда форума
На устройствах с небольшой памятью таблицы применялись с испокон веков. Это был единственный разумный способ ОЧЕНЬ БЫСТРО вычислить например SIN X с точностью до градуса.
 
Сверху Снизу