Программирование и обмен данными с «ARDUINO» по WI-FI посредством ESP8266 Часть Первая

    Как и многие другие самоделкины, я регулярно использую микроконтроллеры AVR для всяких разных любительских поделок. А благодаря концепции «Arduino» эти поделки теперь приобретают еще и элегантный вид. Действительно, за какие-то 300-400 рублей мы получаем миниатюрную многослойную плату с маской, шелкографией и с полностью разведенной на ней периферией для микроконтроллера (причем в SMD исполнении!). Я уже не говорю о всевозможных подключаемых модулях этой же «Arduino» серии: датчиках, контролерах, дисплеях и целых наборов, так нужной нам дополнительной периферии. И опять же всё также недорогих и в прекрасном исполнении. Практически уже нет необходимости, что-то разводить и допаивать на «коленке».­­­­­­­­­


    Но все эти разнообразные любительские поделки, требуют естественно, предварительного программирования. Да и в последующем при разных усовершенствованиях, постоянно приходится эти поделки перепрошивать. Понятное дело, что удобнее делать это дистанционно, чем постоянно таскать их к обычному программатору. Вообще, благодаря той же платформе «Arduino», вариантов и здесь много: Bluetooth, ZigBee, радиоканал с вашим личным протоколом, IR, и даже Wi-Fi. Все они позволяют наладить беспроводной контакт с вашим микроконтроллером. Но мы же остановимся на последнем варианте. Основных причин здесь четыре:

    1: современно, интернет вещей же!

    2: беспроводной роутер есть в каждой квартире, регистрируй в домашней сети свои устройства и вуаля!

    3: ваши поделки осуществляют революционный скачок в своём развитии; мало того, что их можно программировать на расстоянии, они теперь ещё и сами могут общаться с окружающим их миром: электронные часы самостоятельно берут точное время с часовых NTP-серверов, исполнительные устройства управляются с другого конца города или страны, регистрирующие девайсы сохраняют накопленные данные в облако и т.д. и т.п.

    4: есть замечательная серия микросхем ESP8266 на которой не очень легко всё это реализовать.

    Далее, в этой статье на примере механической руки на сервоприводах — будет разобрано и продемонстрировано удаленное программирование и обмен данными с ПК (или чего угодно) с устройствами на базе AVR микроконтроллеров. Сразу же хочу отметить, что все программы приведенные в дальнейшем являются чисто демонстрационными и никакой коммерческой ценности не имеют. Поэтому претензии, типа, почему программатор такой кастрированный и мало функциональный или почему нет дополнительных сервисов, которые есть везде, не принимаются. Поскольку коды открытые, любой желающий может допилить их по своему усмотрению, мне же для работы, пока хватает и таких.

    Предполагается, что читатель уже знаком и с «Arduino» модулями (шилдами) и с подключением и прошивкой ESP8266. На самом деле в Сети выложено огромное количество материалов разъясняющих азы работы с этими девайсами и мне не хотелось бы здесь повторяться. Для новичков в конце статьи есть перечень полезных ссылок по этим вопросам, где можно найти кучу информации, почему это всё у вас не работает. По своему опыту бывшего инженера электронщика могу ответственно заявить, что 99 % неполадок сводится к следующему:

    1. Плохие контакты. Поскольку «Arduino» шилды, подразумевают коммутацию с друг другом через провода вида «папа-мама», а не через пайку, то очень часто что-нибудь, где-нибудь, да отходит. Проверяйте. Да и вообще, как говорится, электроника это наука о контактах.

    2. Проблемы с питанием. Не подавайте 5 вольт питания туда, где требуется 3.3. Иногда из ESP8266 от этого идёт дым. Хотя с другой стороны логические сигналы от пятивольтовых устройств она переваривает без проблем.

    3. Проблемы с достаточной мощностью питания. ESP8266 имеет подлую натуру и иногда может потреблять чуть ли не триста миллиампер, хотя до этого могла удовлетворяться и тридцатью. Соответственно хилый стабилизатор 3.3 вольт платы «Arduino», к которому вы ничтоже сумняшеся, её подключили, тут же просаживается до микроскопических значений. А вы не можете понять, почему оно, то работает, то нет.

    4. Путаница с выводами. Всегда проверяйте, какие сигналы куда идут. Приемник RXD должен соединяться с передатчиком TXD, также как и TXD с RXD, но MOSI должно соединяться с MOSI, а MISO с MISO и так далее.

    5. Не рассчитывайте на внутрисхемные подтягивающие резисторы в ESP8266, всегда подтягивайте выводы к нулю или питанию, через 5-10 килоомные внешние резисторы, а не просто перемычкой. Иначе можете в лучшем случае получить невиданный доселе ток потребления, а потом обонять неприятный запах горелого пластика.

    6. Косяки программного обеспечения. Поскольку ПО для индивидуальных юзеров пишется таким же энтузиастами, то периодически вылазят глюки самих прошивок и баги при обновлении версий этих же прошивок. Лечится ползанием по соответствующим форумам, иногда даже англоязычным. Некоторые товарищи даже утверждали, что и сама микросхема ESP сырая как погода в Питере, но с другой стороны существует также мнение что с 2014 (года её первого выпуска) ситуация с этим кардинально улучшилась (в отличие от погоды).

    7. Загадочные глюки. Это редкое, но нервопотребляющее явление. У меня к примеру, не шилось удалённо одно «Arduino»устройство. Вернее шилось но с ошибками. Но шилось без ошибок, если на нем висел шлейф от программатора (но без самого программатора). «АГА», сказал я себе и припаял конденсатор 15 пФ, между выводом передачи данных и выводом синхронизации. Всё заработало. Но день убил.

    Итак, давайте начнем с самого простого. У нас есть механическая конечность MechArm (но не такая какую собрал Говард Воловитс) сделанная в Китае и персональный компьютер с Windows. Задача — удаленная прошивка программы и управление ея с компьютера.

    Для управляющего контроллера возьмем симпатичную миниатюрную платку Arduino Nano c камнем ATmega328P. Эта плата прекрасно впихивается внутрь механической руки.

    Теперь определимся каким образом мы её будем программировать. Существуют три основных способа наиболее подходящих для удаленной прошивки: через интерфейс SPI, через встроенный загрузчик, через порт JTAG.

    Самый простой вариант, это конечно встроенный загрузчик (бутлоадер). Это заранее прописанная во FLASH память, программа, которая по определенному протоколу получает код, (допустим по самому простому UART) и специальными командами записывает его в место расположения загружаемой программы. Так работает, например, сам загрузчик ARDUINO IDE. После сброса или старта, загрузчик ждет какое-то время данные на приём и если не дожидается начинает исполнение программы с нулевого адреса. Если данные приходят, он пишет их в программную секцию. После следующего сброса загруженная программа начинает исполняться. В деталях, возможно, я описал неточно, но суть именно такая. В итоге нам требуется всего три вывода для программирования: приемник RTD, сброс RESET и земля GND. Вообще, используется еще и передатчик TRD, для верификации записанной программы, но для простых демонстрационных приложений (не для атомной электростанции), проверку можно опустить.

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

    Второй вариант, это программирование по последовательному интерфейсу SPI. Тут уж внутреннего загрузчика нет, а программируем мы, посылая специальные команды и затем данные, по вышеупомянутому интерфейсу. Здесь у нас загрузчик уже внешний, но его все равно писать надо. При передаче используются в добавление к RESET и GND уже четыре дополнительных вывода MOSI, MISO — данные, SLK синхронизация, СS — выбор кристалла. Но вообще также можно убрать MISO и СS. Данные будут только приниматься (верификации программы тогда не будет), а кристалл у нас и так всего один.

    У каждого подхода есть свои плюсы и минусы (а JTAG я вообще не рассматривал, поскольку жизнь человеческая коротка). Но в итоге я склонился к SPI поскольку на ассемблере писать было лень, а открытых готовых загрузчиков я не нашел (просто хорошо не искал).

    Для построения беспроводного канала я, как уже говорилось, выбрал крайне широко известную в настоящее время микросхему ESP8266 — микроконтроллер, а точнее целый SoC (System-on-Chip) китайского производителя Espressif с интерфейсом Wi-Fi. Помимо Wi-Fi он отличается возможностью исполнять программы из внешней флэш-памяти. А конкретно для своего проекта я взял ESP8266-07 с 512 Кб памяти на борту.


    Вообще годится любая ESP8266, где есть лишние ноги для реализации SPI. Поэтому самая простая ESP8266-01 нам не подойдет, так как у неё разведено совсем мало ножек для портов ввода-вывода. Но с другой стороны разница в цене на них меньше ста рублей, а доступны они одинаково. Ну и большие отладочные платы с ESP, где для удобства разведена куча периферии, нам тоже не годятся, так как не влазят, туда куда мы их хотим впихнуть, в нашу механическую руку.

    Глобальная суть идеи в общем была такова. С компьютера на ESP без проводов по WI-FI (в рамках вашей домашней сети) передается тело загружаемой в микроконтроллер программы. А ESP уже по проводам с использованием интерфейса SPI записывает эту программу непосредственно во FLASH память микроконтроллера. Потом естественно сбрасывает его и дает возможность загруженной программе выполняться. Кроме того в ESP должен быть независимый блок, который заведует еще и обменом данными с микроконтроллером, так как мы хотим не только программировать, ни и еще обмениваться с ним данными. В частности для проекта с MechArm, после записи программы, мы ещё передаем сигналы управления сервоприводами, дабы привесть эту руку в движение. Поэтому на самой ESP нам желательно поднять TCP сервер для передачи программы и UDP сервер для управления MechArm. Соответственно эти серверы присоединяются к домашней сети и внимательно слушают, нет ли там желающих загрузить новый код в MechaArm или помахать кому-нибудь ею.

    Так-то, я нашел в Сети, прошивки уже позволяющие производить программирование AVR по воздуху, но там главная проблема в том, что для чего другого эту прошивку использовать уже нельзя. А нам хотелось бы после программирования и общаться с AVR также удаленно.

    Какое ПО мы будем использовать:

    Для ПК, я писал всё на JAVA, среда IntelliJ IDEA. Но в принципе, можно на чём угодно, нам там главное написать клиент, который будет отправлять программу для прошивки AVR на ESP8266.

    Сами программки для AVR я пишу в ATMEL STUDIO , на языке С, редко на ассемблере. Скетчи Arduino не использую принципиально, практически любая нужная библиотека пишется за час другой, причем с полным пониманием её работы. Я пробовал скетчи, но пока у вас нет на AVR операционной системы, скетчи так и будут отбирать у друга периферию и регулярно глючить. Да сама IDE Arduino по сравнению с ATMEL STUDIO, конечно вещь весьма примитивная. Но тут вопрос, конечно, спорный, гуманитариям и школьникам веселее и проще будет, наверное, со скетчами.

    Для программирования ESP8266 я использовал прошивку NodeMCU, а программы писал на языке Lua. Нет, я бы с удовольствием писал бы на Java и на С, но их же на ESP нет. Luа язык в применении к нашей задаче не сложный, освоить его пара пустяков. А собственно для загрузки программ и их отладки на ESP, я взял IDE ESPlorer. Отечественный бесплатный продукт (но можете сделать автору donation), который конечно не сравнить со средами упомянутыми выше, но как говорится дарёному коню… Но чтобы пользоваться ESPlorer и писать на LUA, нам сначала необходимо сменить в микросхеме ESP8266 базовую прошивку (поставляемую от производителя) на новую. В этом предприятии нам поможет программа NODE MCU PyFlasher. В смысле, поможет её перепрошить. А саму прошивку мы сами создадим и получим в руки на сайте создателей : NodeMCU .А более подробно об этом процессе вы можете прочесть здесь:

    Всё очень доступно и понятно. К базовым библиотекам добавляем поддержку SPI и битовые операции (в LUA в нашем случае битовые операции перегружены и от них мало толку). Много в прошивку библиотек пихать не следует, так как из-за наличия всякого разнообразного софта на ESP8266 остается совсем мало памяти, какие-то жалкие 20 кБ.

    Конечно, вы можете просто взять готовую прошивку, коих много уже болтается в Интернете, но не рекомендую. Хотя бы потому, что на некоторых нет поддержки битовых операции (а они нам нужны) и нет регулирования скорости передачи данных по SPI.
    Соответственно, они передаются по умолчанию со скоростью 40 Мгц делённые на какой-то небольшой коэффициент и поэтому AVR их переваривать не успевает.

    Кому лень создавать прошивку можете скачать мою из облака.

    Теперь у нас есть прошивка и нам надо загрузить её в ESP8266 вместо базовой. Для этого нам пригодится простейший адаптер USB — UART.

    Присоединяем ножки TXD к RXD, а RXD к TXD, делаем общей землю, но не используем, как казалось, удобный вывод питания 3.3 В на адаптере. В большинстве случаев ESP8266 просадит его напрочь. Поэтому запитываем ёё отдельно. Потом переводим ESP в режим программирования (GP0 на землю, если кто забыл) и запускаем NODE MCU PyFlasher.



    Главное, не забудьте стереть флэш-память (yes, wipes all data), иначе в зависимости от версии прошивки после программирования в памяти может остаться ненужный мусор, который в свою очередь будет сыпать мусор в консоль при дальнейшей работе. До этого я использовал софт, где не было опции стереть предварительно память, намучался жутко, так как ничего не работало. А ларчик просто открывался, только правда на англоязычном форуме создателей NODE MCU.

    Заимев же нужную прошивку мы теперь можем писать и отлаживать программы на языке LUA (там еще MicroPython, но я им не пользовался) используя при этом очень удобные API от NODE MCU. Запускаем уже упомянутый ранее ESPlorer.



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

    Теперь пишем программульку на LUA, кою потом загрузим в ESP8266:

    Загрузчик Lua для AVR, записываемый в ESP8266
    <b>function InstrProgrammingEnable () -- instruction for MC "enable programming"</b>
    
    p=0
    while p<31 do
    p=p+1
    
    pin=8  
    gpio.write(pin, gpio.LOW)
    spi.send(1, 0xAC,0x53)
    read = spi.recv( 1, 8)
    spi.send(1,0,0)
    gpio.write(pin, gpio.HIGH)
    
         if (string.byte(read)== 83) 
            then     
            print("connection established") 
            p=33
                if(p==31)
                then 
                print("no connection")
                end
            end
        end
    end
    
    
    <b>function ProgrammingDisable ()</b>
    
    pin=2--END OF ESET FOR MK
    gpio.mode(pin, gpio.INPUT)
    
    pin=8  
    gpio.mode(pin, gpio.INPUT)
    
    pin=5--CLK MASTER for SPI
    gpio.mode(pin, gpio.INPUT)
    
    pin=6--MISO MASTER  for SPI
    gpio.mode(pin, gpio.INPUT)
    
    pin=7--MOSI MASTER for SPI
    gpio.mode(pin, gpio.INPUT)
    end
    
    
    <b>function ProgrammingEnable ()</b>
    pin=2-- RESET FOR MK
    gpio.mode(pin, gpio.OUTPUT)
    gpio.write(pin, gpio.LOW)
    
    pin=2--POZITIV FOR 4MSEC RESET FOR MK
    gpio.mode(pin, gpio.OUTPUT)
    gpio.write(pin, gpio.HIGH)
    
    tmr.delay(4)
    gpio.mode(pin, gpio.OUTPUT)
    gpio.write(pin, gpio.LOW)
    
    tmr.delay(25000)
    end
    
    
    
    <b>function InstrFlashErase() </b>
    
    pin=8  
    gpio.write(pin, gpio.LOW)
    spi.send(1,0xAC,0x80,0,0)
    gpio.write(pin, gpio.HIGH)
    tmr.delay(15000)
    
    pin=2--RESET FOR MK
    gpio.mode(pin, gpio.OUTPUT)
    gpio.write(pin, gpio.HIGH)
    tmr.delay(20000)
    gpio.write(pin, gpio.LOW)
    
    print( "FLASH is erased")
    InstrProgrammingEnable () 
    end
    
    
    
    <b>function InstrStorePAGE(H, address, data)</b>
    
    pin=8  
    gpio.write(pin, gpio.LOW)
    spi.send(1,H,0,address,data)
    gpio.write(pin, gpio.HIGH)
    tmr.delay(500)
    end
    
    
    
    
    <b>function InstrWriteFLASH(page_address_low,page_address_high)</b>
    
    pin=8  
    gpio.write(pin, gpio.LOW)
    spi.send(1,0x4C,page_address_high,page_address_low,0)
    gpio.write(pin, gpio.HIGH)
    tmr.delay(5000)-- иногда не прописываются флэш при малых задержках
    end
    
    
    
    
    <b>function Programming (payload)</b>
    
    pin=8--CS MASTER for SPI
    gpio.mode(pin, gpio.OUTPUT, gpio.PULLUP)
    pin=4--LED LIGHTS ON LOW
    gpio.mode(pin, gpio.OUTPUT)
    gpio.write(pin, gpio.LOW)
    print(string.len(payload))
    page_count = 7 -- пишем 1 килобайт 
    
    for k =0  ,page_count ,1 do--quantity of pages
    
        for i=0 , 127, 2 do-- -1
        address = i/2
        data=payload:byte(i+1+128*k)
            if data == nil 
            then
            data = 0xff
            end
        InstrStorePAGE(0x40,address,data)
      --  tmr.delay(100)--  otherwise not in time write
        data =payload:byte(i+1+1+128*k)
            if data == nil then
            data = 0xff
            end
        InstrStorePAGE(0x48,address,data)
    --    tmr.delay(100)
        end
    
    page_address_low=bit.band(k ,3)*64 -- 3 это двоичное 11
    page_address_high=k/4+frame1024*2
    
    tmr.delay(1000)
    InstrWriteFLASH(page_address_low,page_address_high)
    tmr.wdclr()
    end
    
    pin=4--LED
    gpio.mode(pin, gpio.OUTPUT)
    gpio.write(pin, gpio.HIGH)
    end
    
    
    
    <b>--MAIN BLOCK</b>
    
    
    
    wifi.setmode(wifi.STATION)
    --wifi.sta.config("имя сети","пароль") -- set SSID and password of your access point
    station_cfg={}
    tmr.delay(30000)
    station_cfg.ssid="имя сети"
    tmr.delay(30000)
    station_cfg.pwd="пароль"
    tmr.delay(30000)
    wifi.sta.config(station_cfg)
    tmr.delay(30000)
    wifi.sta.connect()
    tmr.delay(1000000)
    print(wifi.sta.status())
    print(wifi.sta.getip())
    
    
    
    while ( wifi.sta.status()~=1 ) do
    if( wifi.sta.status()==5)
    then
    break
    end
    end
    
    
    
    
    
    sv=net.createServer(net.TCP,30)
    tmr.delay(100) 
    print("SERVER READY")
    
    sv:listen(4000,function(c)
        c:on("receive", function(c, payload)
            print(payload)
            if (payload =="program\r\n")
            then
                c:send("ready\r\n")
                print("ready for program\r\n")
    
    
                spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8,320,spi.FULLDUPLEX)
                ProgrammingEnable ()
                tmr.delay(100)
                InstrProgrammingEnable ()
                tmr.delay(100)
                InstrFlashErase()
                tmr.delay(100)
                frame1024=0--номер переданого фрей мов
    
    
            
                st=net.createServer(net.TCP,30)
                st:listen(4001,function(c)
            
                c:on("receive", function(c, payload)
                tmr.wdclr()
           
                Programming (payload)
                frame1024=frame1024+1
                 
                end)
                end)
            end
    
             
            if (payload =="data\r\n")
            then
    
                c:send("ready\r\n")
                print("ready for data\r\n")
                srv=net.createServer(net.UDP)
                tmr.delay(1000) 
    
                pin=10
                gpio.write(pin, gpio.HIGH)
    
                uart.setup(0,9600,8,0,1,0) 
    
                srv:listen(5000)
                srv:on("receive", function(srv, pl)
                pl=pl*1
                --print(pl)
                uart.write(0,pl)
    
                tmr.wdclr()
                end)
            end
    
         
            if (payload =="stop\r\n")
            then
                if(st~=nil)
                then
                st:close()
                frame1024=0
                ProgrammingDisable ()
                print("stop program")
                end
    
               if(srv~=nil) 
               then
               srv:close()
               print("stop data")
               end
               
            end
    
            
             
        end)
    end)
    end)
    
    



    Где соответствующие функции выполняют следующие действия:

    function InstrProgrammingEnable () – переводит микроконтроллер в режим программирования специальной командой отправляемой по SPI.

    function ProgrammingEnable () – просто ресетим AVR на 25 мс перед началом программирования

    function ProgrammingDisable () – после окончания программирования, переводим выводы SPI в ESP8266 в неактивное состояние, чтобы они не мешались нам при выполнения кода на микроконтроллере (вдруг они там используются)

    function InstrFlashErase() – затираем флэш-память на микроконтроллере перед началом программирования. Зачем это нужно объяснять не нужно.

    function InstrStorePAGE(H, address, data) – по этой команде во внутренний буфер микроконтроллера записывается байт программы. Но это ещё не сама флэш запись, так как флэш пишется здесь постранично по 128 байт.

    function InstrWriteFLASH(page_address_low,page_address_high) – а вот это уже запись флэш и она требует времени, обратите внимание на временную задержку 5 000 мкс.

    function Programming (payload) – самая большая и важная функция использующая и вышеперечисленные функции. Она берет передаваемую программу кусками по 1024 байт, делит их на байтики и формирует для них адреса, а затем отправляет в микроконтроллер во внутренний буфер и через каждый 128 байт инициализирует запись флэш. Потом берет следующий килобайт кода и повторяет операцию, естественно со смещением в адресах, чтобы писать дальше а не затирать записанное. Вначале, я пробовал пересылать программы целиком, но при превышении 6 килобайт в ESP8266 элементарно кончается доступная память и она вылетает. Один килобайт оказался самой удобной единицей, ибо аккуратно делится на части и удобно передается по TCP (нам же надо его с компьютера ещё получить). Больший размер тоже не нужен, TCP, сами знаете, в текущей версии ограничивает передаваемый пакет, в 1500 что ли байт (но у меня передавался почему-то 1440, вроде).

    Как бы ничего сложного, но несколько подводных камней пришлось преодолеть.

    Далее идет MAIN BLOCK. В нём мы:

    Регистрируемся в беспроводной сети.

    Создаем вначале TCP сервер, который слушает три команды:

    1. “program” (будем программировать),

    2. “data” (будем меняться данными),

    3. ”stop” (всё прекращаем).

    Если мы программируем, то сначала инициализируем SPI и создаем еще один TCP сервер, который хапает данные (код прошиваемой программы) покилобайтно и вызывает под них функции программирования микроконтроллера. Я понимаю, что выглядит глупо создавать второй сервер, но это необходимость, ибо местное API поддерживает создание только одного сокета, а нам необходимо разделять команды ”program” и “data” собственно с передаваемыми данными, ибо на глаз они не различаются, там байты и тут байты.

    Если же мы хотим не программировать, а обмениваться данными, посылая их в нашем случае в микроконтроллер, то мы сначала отправляем по TCP строку ”data”. В ответ на это будет создан уже UDP сервер (я напомню, что мы управляем динамически механической рукой и нам задержки с формированием TCP пакетов не нужны, да и вообще отправлять один байт целым TCP кадром моветон). А UDP дейтаграммы у нас будут маленькими и формироваться будут быстро.

    После инициализируется UART, и каждый принимаемый в беспроводном виде байт, отправляется уже по проводу TXD на микроконтроллер, который обязан, буде там прошита соответствующая программа, его принять. Обмен данными в другом направлении организовать также не сложно, но я пока его не реализовывал.

    Ну и по команде ”stop” вышеупомянутые сервера (кроме самого первого) закрывают соединения и самый главный сервер вновь переходит в состояние ожидания команд ”program” и “data”.

    Поскольку SPI интерфейс программно эмулируется в ESP8266, то порты ввода-вывода для сигналов CS, CLK, MISO,MOSI, RESET (для AVR), можете использовать любые доступные, а не те, что указаны у меня в загрузчике. Кроме того оказалось, что CS и MISO в принципе тоже можно в данном случае оборвать, будет работать и без них. Ну и один вывод задействуется на встроенный в плату ESP8266 светодиод, чтобы мигал иногда и показывал, что программа ещё живая.

    Проверок на ошибки записи не делается (за исключением первого запроса к AVR, но эта информация просто выводится на консоль), EEPROM не программируется, больше 32 Кб не шьется – короче есть ещё над чем поработать. Скорость обмена по SPI примерно 115 Кбит, за несколько секунд всё прошивается, примерно, как у обычного последовательного программатора типа ISP500).

    Берите код, вписывайте свои сети и пароли, компилируйте на ESplorer, обзывайте его “init” (чтобы запускался при рестарте) и отправляйте на ESP8266. Должно работать. В смысле работать беспроводным программатором, как минимум.

    Мы же теперь займемся управляющей стороной – персональным компьютером.

    По сути, нам нужно взять файл формата HEX, в который превращаются ваши программы, написанные в среде ATMEL STUDIO и отправить его по WI-FI на известный нам порт сокета (в данном случае 4000). Маленькая загвоздка в том, что нам нужен двоичный файл BIN для пересылки, а ATMEL STUDIO радует нас только HEXом. Выхода здесь два; или перевести его в формат BIN специальной программой конвертером, типа WinHex или сделать это самим в своей программе. Я пока не сделал, но вроде это не сложно, там надо отрезать заголовок и сделать что-то ещё.

    В итоге программу-загрузчик я написал на JAVA (в основном потому, что больше ни на чем не умею), работая в просто прекрасной и бесплатной среде IntelliJ IDEA. В ней создается TCP клиент, который ищет сервер запущенный на ESP8266. Если находит, то связывается с ним и отправляет ему файл расположенный по такому-то адресу. Код ниже.

    Загрузчик файлов на JAVA, работающий на стороне ПК
    import java.io.*;
    import java.net.*;
    import java.util.ArrayList;
    import java.util.List;
    
    
    public class Net {
      <b>  public static void main(String args[]) {
            new Http_client(4000);
        }</b>
    }
    
    
    class Http_client extends Thread {
        int port;
        String s;
        String Greetings_from_S;
    
    
        Http_client(int port){
         this.port = port;
            start();
    
        }
        public  void run() {
    //192.168.1.113 -это адрес ESP8266 в моей сети. Но вообще, узнается из общения с роутером
    // лучше сделать его статическим, роутеры это умеют
    
            try (Socket socket = new Socket("192.168.1.113", port)) {
               
                PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
                pw.println("program");// Greetings with SERVER
                System.out.println("program");
    
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                Greetings_from_S = br.readLine();
                System.out.println(Greetings_from_S);
    
                if(Greetings_from_S.equals("ready"))
                {
    
                    try
    
                    {
    
                        File file = new File("d:BlinkOUT.bin");// адрес выгружаемого файла
                        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
    
    
                        byte [] data = new byte[bis.available()];
                        bis.read(data);
    
                        byte [] data_buffer = new byte[1024];
    
                        int frames = data.length/1024;
                        System.out.println(frames);
                        int residy = data.length%1024;
    
                        for (int i = 0; i < frames;i++) {
                            for (int k = 0; k< (1024); k++) {
                                data_buffer[k] = data[k+1024*(i)];
                            }
    
                           sendingChunk(data_buffer);
    
                                       
                        }
                        byte [] data_buffer2= new byte[residy];
                        for (int i = 0; i < residy;i++) {
    
                            data_buffer2[i] = data[i+1024*(frames)];
                        }
    
    
                        sendingChunk(data_buffer2);
    
                        pw.println("stop");//
                        System.out.println("stop program");
    
    
                    } catch (Exception e) {
    
                        System.out.println(e);
    
                    }
                }
    
    
            } catch (Exception e) {
    
                System.out.println(e);
    
            }
        }
    
    
        public void sendingChunk (byte [] data_buffer){
            try (Socket socket = new Socket("192.168.1.113", 4001)){
                BufferedOutputStream bos = new BufferedOutputStream((socket.getOutputStream()));
                bos.write(data_buffer);
                bos.flush();
      
                System.out.println(data_buffer.length);
            }
            catch (Exception e) {
    
                System.out.println(e);
    
            }
        }
    }
    



    Тут конечно накручено лишнего, всякие ready, в принципе не нужны. Если уж TCP соединение установлено, то оно установлено. Единственная проблема была в том, что файл никак не хотел отправляться ровными кусками по 1024 байт, как мне очень требовалось, хотя я и явно указывал размер. Видимо там какой-то финальный буфер недоступный из JAVA, и он отправляет пакеты размером, каким ему хочется, что для приемной стороны совершенно неприёмлемо. Сначала я пробовал сделать задержку, чтобы буфер уставал ждать следующие куски и отправлял как есть. Но задержка стала работать, когда достигла 10 секунд, что мне как-то показалось многовато на один передаваемый килобайт.

    Но потом я заметил, что почему-то первый кусок всегда идет ровный, какой был заказан, а уже со второго начинается непредсказуемая вакханалия. Поэтому я сделал так, чтобы клиент открывал соединение, отправлял порцию кода в 1024 байт и закрывал соединение. И так пока не отправится весь файл. Всё успешно заработало.

    Единственное, для запуска необходимо поставить на компьютер среду выполнения JAVA. Но я обычно запускаю сразу из IntelliJ IDEA ибо там в консоли всегда видно, что происходит (но и здесь среда JAVA нужна). Хотя, конечно, по-умному надо сделать GUI. То есть окошко, где выпадает путь к файлу, возможность менять там же в окне номера портов и ну и прочие нужные вещи. И все это собрать в виде исполняемого файла.

    А таперича, как говаривал Коровьев, вернемся граждане, собственно к механической конечности MechArm, что была упомянута в самом начале. У нас теперь есть возможность удаленно её запрограммировать, а затем ею поуправлять. Перейдём к программе управления на стороне микроконтроллера.

    В данном случае нам необходимо контролировать четыре сервопривода. Вот таких.

    Такой привод управляется прямоугольными импульсами, периода 20 мс (50Гц) с коэффициентом заполнения от 2 до 4 процентов. То есть 2% это полный поворот в одну сторону, 4% в другую. Задача как раз для встроенного в AVR ШИМ.



    Один сервопривод используется для движения вправо-влево; второй на себя – от себя; третий вверх-вниз; четвертый – сама клешня, которая должна сжиматься и разжиматься. Всё написано на С и откомпилировано до HEX файла в ATMEL STUDIO. Немного странный вид программы связан с тем, что изначально рука управлялась с клавиатуры привязанной проводами к микроконтроллеру. Но провода вчерашний день, надо эволюционировать дальше.

    Можно конечно использовать скетчи для сервоприводов от ”ARDUINO”, но мне они не понравились. Самому писать интересней. К тому же все четыре сервопривода должны работать одновременно, а не в мультиплексированном режиме, когда ШИМ переключается на каждый сервопривод поочередно. Ибо гравитацию никто не отменял и поднятая вверх конечность, моментально опустится, если на соответствующий сервопривод перестанут поступать управляющие импульсы. Я не уверен, что ”ARDUINO” скетч обеспечивает одновременный режим работы для четырех серво. А вот сами мы вполне можем написать программку отвечающую нужным требованиям. Да и вообще при отсутствии операционной системы, которая отделяет агнцев от козлищ, применение скетчей конкурирующих за периферийные устройства микроконтроллера (а мы даже и не знаем заранее какие) дело слишком багопроизводительное.

    Вот сам код, который мы записываем в Arduino Nano посредством ESP8266-07.

    Программа для управление MechArm для микроконтроллера AVRmega328P
    #define F_CPU 16000000
    
    #include <avr/io.h>
    #include <stdint.h>// стандартные целые числа
    #include <avr/interrupt.h>
    #include <math.h>	// математика
    #include <stdio.h> //стандартный ввод-вывод 
    #include <avr/eeprom.h>
    #include <setjmp.h>
    #include <stdlib.h> //стандартные возможности
    
    
    #define UART_BAUD_RATE 115200
    
    // счетчик Т1 задает временной интервал 20мс
    #define  COUNTER1_OFF TCCR1B=0b00000000 // CS02 CS01 CS00 - 000 - отключен; 001  без делителя; 010 c делителем 8; 011 -64; 100 -256; 101 -1024
    #define  COUNTER1_ON  TCCR1B=0b00000011
    // счетчик Т0 задает ширину управляющего импульса для серво РВ0 и РВ1
    #define  COUNTER0_OFF TCCR0B=0b00000000 // CS02 CS01 CS00 - 000 - отключен; 001  без делителя; 010 c делителем 8; 011 -64; 100 -256; 101 -1024
    #define  COUNTER0_ON  TCCR0B=0b00000100
    // счетчик Т2 задает ширину управляющего импульса для серво РB2(PD6) и РВ3(PD7)
    #define  COUNTER2_OFF TCCR2B=0b00000000 // CS02 CS01 CS00 - 000 - отключен; 001  без делителя; 010 c делителем 8; 011 -64; 100 -256; 101 -1024
    #define  COUNTER2_ON  TCCR2B=0b00000110
    
    
    volatile uint16_t period_20ms;
    volatile uint8_t State_of_keyboard;
    volatile uint8_t  start_position [6];
    volatile int8_t number_servo;
    
    
    ISR(USART_RX_vect)// прерывание для UART
    {
    	
    	State_of_keyboard=UDR0;
    	
    	return;
    }
    
    
    
    
    
    ISR(TIMER0_COMPA_vect)// серво РВ0 ширина управляющего импульса
    {
    	
    	PORTB &=~(1<<0);
    	TIMSK0&=~(1<<OCIE0A);
    	TIFR0 |=(1<<OCF0A);
    	
    	return;
    }
    
    
    ISR(TIMER0_COMPB_vect)  // серво РВ1 ширина управляющего импульса
    {
    	PORTB &=~(1<<1);
    	TIFR0 |=(1<<OCF0B);
    	TIMSK0 &=~(1<<OCIE0B);
    	
    	return;
    }
    
    
    ISR(TIMER2_COMPA_vect)// серво РВ2(PD6) ширина управляющего импульса
    {
    	PORTD &=~(1<<6);
    	TIFR2 |=(1<<OCF2A);
    	TIMSK2 &=~(1<<OCIE2A);
    	
    	return;
    }
    
    ISR(TIMER2_COMPB_vect)// серво РВ3(PD7) ширина управляющего импульса
    {
    	PORTD &=~(1<<7);
    	TIFR2 |=(1<<OCF2B);
    	TIMSK2 &=~(1<<OCIE2B);
    	
    	return;
    }
    
    
    
    ISR(TIMER1_OVF_vect){// формируем период 20 мс и обновляем регистры счетчики
    	
    	COUNTER1_OFF;
    	COUNTER0_OFF;
    	COUNTER2_OFF;
    	
    	TIFR0 |=(1<<OCF0A);
    	TIFR0 |=(1<<OCF0B);
    	TIFR2 |=(1<<OCF2A);
    	TIFR2 |=(1<<OCF2B);
    	
    	TIFR1 |=(1<<TOV1);
    	PORTB |=(1<<0)|(1<<1);
    	PORTD |=(1<<6)|(1<<7);
    	TCNT1 = period_20ms; // период 20 мс
    	TCNT0 = 0;
    	TCNT2 = 0;
    	
    	TIMSK0|=(1<<OCIE0A)|(1<<OCIE0B);
    	TIMSK2|=(1<<OCIE2A)|(1<<OCIE2B);
    		
    	OCR0A=start_position[1];// положение 0 сервопривода	0
    	OCR0B=start_position[2];// положение 0 сервопривода	1
    	OCR2A=start_position[3];// положение 0 сервопривода	2
    	OCR2B=start_position[4];// положение 0 сервопривода	3
    	
    	COUNTER1_ON;
    	COUNTER2_ON;
    	COUNTER0_ON;
    
    	return;
    }
    
    
    
    
    
    
    void time_delay(long i)
    {	cli();sei();
    	long k;
    	i*=2000;
    	for(k=0;k<i;k++){;;};
    	
    	
    }
    
    
    
    void timer_counter0_1_2_INIT()// инициализация таймеров 0,1,2
    
    {
    	
    
    	//таймер Т1
    	TCCR1A &=~(1<<COM1A0)|~(1<<COM1A1)|~(1<<COM1B0)|~(1<<COM1B1);//внешние выводы отключены
    	TCCR1A &=~(1<<WGM10)|~(1<<WGM11);
    	TCCR1B &=~(1<<WGM12)|~(1<<WGM13);// режим простого счёта
    	period_20ms=60575;
    	TCNT1 = period_20ms;
    	TIMSK1|=(1<<TOIE1);//|разрешаем прерывания по переполнению
    	//TIFR0  флаги переполнения  TOV0
    	
    	
    	//таймер Т0
    	TCCR0A &=~(1<<COM0A0)|~(1<<COM0A1)|~(1<<COM0B0)|~(1<<COM0B1);//внешние выводы отключены
    	TCCR0A &=~(1<<WGM00)|~(1<<WGM01);
    	TCCR0B &=~(1<<WGM02);// режим простого счёта
    	
    	
    	
    	//таймер Т2
    	TCCR2A &=~(1<<COM2A0)|~(1<<COM2A1)|~(1<<COM2B0)|~(1<<COM2B1);//внешние выводы отключены
    	TCCR2A &=~(1<<WGM20)|~(1<<WGM21);
    	TCCR2B &=~(1<<WGM22);// режим простого счёта
    	
    	COUNTER1_ON;
    	
    
    }
    
    void servo_reset()
    {
    	
    	
    	
    	start_position[1]=97;// положение 0 сервопривода	0
    	start_position[2]=70;// положение 0 сервопривода	1
    	start_position[3]=92;// положение 0 сервопривода	2
    	start_position[4]=124; //положение 0 сервопривода	3
    	COUNTER1_ON;
    	
    	
    	time_delay(100);
    }
    
    
    
    void servo_go( int8_t moven, uint8_t servo_position_max, uint8_t servo_position_min)//
    
    
    {
    	
    	switch (moven){
    		
    		case 1:
    		start_position[number_servo]++;
    		if(start_position[number_servo]==servo_position_max){start_position[number_servo]--;};// это +90 градусов
    
    		break;
    		case 2:
    		start_position[number_servo]--;
    		if(start_position[number_servo]==servo_position_min){start_position[number_servo]++;};//6 это -90 градусов
    		break;
    	};
    	
    	
    	time_delay(20);
    	
    	return;
    	
    	
    }
    
    
    
    //PORTB-0,1, PORTD - 6,7  - управление сервоприводами, 8-битовый счетчик COUNTER 0
    
    
    
    int main(void)
    
    
    
    {
    	uint8_t servo_positionmin=0, servo_positionmax=0;
    	int8_t const servo_position1max = 122, servo_position1min=58; //по горизонтали
    	int8_t const servo_position2max = 120, servo_position2min=36;//
    	int8_t const servo_position3max = 125, servo_position3min=68;//
    	int8_t const servo_position4max = 129, servo_position4min=108;// клешня128 108
    	
    	
    	sei();
    	DDRD = 0B11000010;	// устанавливаем кнопки D2-D5 на вход, D0 вход RX, D1 выход TX, D6 D7 выходы серво 3 и 4
    	PORTD = 0B00111110; // устанавливаем внутренние подтягивающие резисторы
    	
    	DDRB |=(1<<0)|(1<<1);// устанавливаем выходы порта В для сервоприводов на выход
    	PORTB &=(~1<<0)|(~1<<1);
    	
    
    	
    	UCSR0A=0;//инициализируем UART 
    	UCSR0B=0b10010000;
    	UCSR0C=0b00000110;
    		
    	UBRR0L=103;// НА 115200
    	UBRR0H=0;
    	
    	
    	timer_counter0_1_2_INIT();
    	
    	servo_reset();
    	PORTB |=(1<<5);
    		
    	
    	while (1)	{
    
    		
    		switch (State_of_keyboard)
    		{
    			case 1:// выбран серво  1 PD0(PB0)
    			number_servo=1;
    			servo_positionmin=servo_position1min;
    			servo_positionmax=servo_position1max;
    			break;
    			
    			case 2: // выбран серво  1 PD0(PB0)
    			number_servo=1;
    			servo_positionmin=servo_position1min;
    			servo_positionmax=servo_position1max;
    			break;
    					
    			case 5:
    			number_servo=2; // выбран серво 2   PD1(PB1)
    			servo_positionmin=servo_position2min;
    			servo_positionmax=servo_position2max;
    			break;
    						
    			case 6:			
    			number_servo=2; // выбран серво 2   PD1(PB1)
    			servo_positionmin=servo_position2min;
    			servo_positionmax=servo_position2max;
    			break;
    		
    			case 7:
    			number_servo=3;// выбран серво 3 PD6
    			servo_positionmin=servo_position3min;
    			servo_positionmax=servo_position3max;
    			break;
    			
    			case 8:		
    			number_servo=3;// выбран серво 3 PD6
    			servo_positionmin=servo_position3min;
    			servo_positionmax=servo_position3max;
    			break;
    		
    			case 3:
    			number_servo=4;	// выбран серво 4   PD7
    			servo_positionmin=servo_position4min;
    			servo_positionmax=servo_position4max;
    			break;//  клешня
    			
    			case 4:
    			number_servo=4;	// выбран серво 4   PD7
    			servo_positionmin=servo_position4min;
    			servo_positionmax=servo_position4max;
    			break;//  клешня
    			
    		
    		// cтранный вид программы только из-за того, что адаптировалась клавиатурная версия всего с 4-мя клавишами
    		// то есть сначала мы выбирали номер сервопривода клавишами, а уже затем во второй фазе им управляли
    		
    			}
    
    		if(State_of_keyboard==1||State_of_keyboard==3||State_of_keyboard==5||State_of_keyboard==7)
    			{
    			servo_go(1,servo_positionmax,servo_positionmin);//
    			}
    				
    		if(State_of_keyboard==2||State_of_keyboard==4||State_of_keyboard==6||State_of_keyboard==8) // кнопка в другом направлении
    			{
    			servo_go(2,servo_positionmax,servo_positionmin);//
    			}	
    			
    	    time_delay(20);	
    	
    	}
    	
    }
    



    Суть программы ясна из текста и комментариев. Мы используем счетчик Т1 для образцового периода 20 мс и счетчики Т0, Т2 для выдачи ШИМ сигналов на четыре линии порта ввода-вывода, благо каждый из этих двух счетчиков, может работать на два устройства.
    В программе устанавливаются начальные положения сервоприводов, через загрузку счетных регистров OCR0A, OCR0B, OCR2A,OCR2B. Также вводятся константы ограничители, поскольку нам не всегда нужен размах в 180 градусов. Ну и дальше, по прерыванию от UART, программа ловит число отправленное ESP8266 (от 1 до 8) и переводит его в команду для соответствующего сервопривода. Приводов четыре, каждый работает в двух направлениях, поэтому целых чисел от одного до восьми вполне хватает. Как только число выбрано, содержимое вышеупомянутых регистров счетчиков либо инкрементируется либо декрементируется, соответственно изменяя скважность управляющего импульса и угол поворота выбранного сервопривода. Те приводы, которые мы не выбирали, сохраняют старое значение угла поворота, (поскольку содержимое соответствующих регистров хоть и обновлялось, но не менялось) и продолжают удерживать механическую руку в прежнем положении.

    Теперь нам осталось лишь написать управляющую программу, простите за тавталогию, для управления механической рукой уже непосредственно с компьютера по WI-FI.
    Код также написан на JAVA, но немного облагорожен. Появился GUI и возможность редактировать номера портов и сетевой адрес ESP8266.



    Что там происходит понятно из окошка. Текст программы я здесь не привожу (он доступен на Гитхабе ), по следующей причине: примерно 95% его объема это создание окна и обработка сигналов от клавиатуры. Но суть такая же как и у предыдущей программы на JAVA. Создается клиент, только UDP, который в зависимости от нажатой клавиши шлёт число от 1 до 8, по указанному адресу на указанный порт.
    Или можете сразу взять исполняемый файл отсюда. Для 64 разрядных машин с виндой. Даже установленной среды JAVA не надо. Все уже упихано в 178 Мбайт.

    Итак, механическая ручка была собрана, отлажена и подарена брату на юбилей. Может поднимать пластиковые стопки с водкой, по скайпу из другого города. Хотя для механической руки Говарда Воловитса из сериала ”Теория Большого Взрыва”, ей по-прежнему далеко.

    Но зато в следующих статьях (если кому будет интересно) мы сможем управлять ею с мобильного телефона, делать то же самое с четырех-колесной роботележкой и обновлять в электронных часах время с часовых серверов в Интернете. Потом поставим на тележку старый смартфон и будем гнать с него видео на нейронную сеть с распознаванием образов, а обратно управляющие сигналы на моторчики,ой что-то меня уже несёт...

    И все это с помощью прекрасной ESP8266.
    Буду рад, если кому статья показалась интересной.

    [1] Распиновка и характеристики ESP8266
    [2]Подключение ESP8266. Быстрый старт.
    [3]Обновление прошивки NodeMCU через облако
    [4] NODE MCU PyFlasher
    [5] ESPlorer — IDE для ESP8266
    [6]Программирование на С для AVR
    [7]Обзор статей — «Программирование микроконтроллеров на языке Си»
    [8]Описание NodeMCU API
    [9]Lua Справочник
    [10]Lua скрипты и модули
    [11]IntelliJ IDEA
    [12] Загрузите Java на свой настольный компьютер сейчас!
    [13]Atmel Studio
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 73
    • 0
      А почему не взяли esp-link?
      • 0
        тот же вопрос был :-)
        • 0
          Я о нем упоминал, без названия, правда, сори. Там нет возможности использовать esp8266, для чего либо еще кроме программирования. Я его юзал раньше, но мне захотелось, чтобы с микроконтроллером можно было еще и обмениваться данными.
          • 0
            Хотя может быть наврал. Я работал со ссылкой samopal.pro/arduino-esp8266.
            Там было только про программирование.
            Цитата
            " В ближайшее время я планирую освоить прошивку ESP8266 через другую ESP8266 (для модулей с 512Кбайт флэша это вполне актуально) и подключение Ардуино к MQTT"

            И как-то на этом он остановился.
            • 0
              Не остановился я, а пошел другим путем )))
              Модули 07 и 01 кончились, использую только 12 с 4Мб, которые и без этого по воздуху прошиваются. Ардуины к MQTT передумал подключать, а подключаю сразу ESP
              • 0
                Да эта мюкютата, часто бывает и не нужна. Часто надо просто двоичные данные погонять. И протоколы HTTP тоже в этом случае не требуются. Можно и не пихать ничего поверх TCP. А прямо им и пользоваться.
                • 0
                  Для себя открыл многообразие MQTT приложений, враперов и пр.
                  Данные погонять можно и по сокету, но вот когда нужно все это в базу и ерасиво отображать — тут есть куда развернуться

            • 0
              Как это нет? Как раз возможность программирования там побочная, основная функция ESP-link'a — быть wifi «сопроцессором» и выполнять http-запросы для (например) arduino
              В ардуино для этого есть специальная библиотека el-client
              • 0
                Да есть, есть. Просто в статье было про программирование, а про остальное было «в будущем расскажу». Поэтому не обратил внимания.
                • 0
                  вот поэтому я никогда не пользуюсь русскоязычными источниками
                  • 0
                    Да, даже бы если б дочитал, то не факт что использовал бы. Мне и программирование-то не очень понравилось на esp-link. А куча оберток и виртуализаций и браузер сверху, чтобы два байта переслать…
        • +3
          ESP8266 можно программировать с помощью C++. Есть SDK и Arduino IDE.
          • 0
            Согласен, удобно, быстро и без глюков.
            • +1
              Мне не нравится софт с ардуины. Хард нравится, софт — нет.
              • 0
                visualmicro
                • –2
                  кака.
                  костыль для костыля.
                  • 0
                    Это Вы VisualStudio костылем назвали? Смешно.
                    Связка VisualMicro + VisualStudio опережает Arduino IDE на несколько световых лет.
                    • –1
                      я имел в виду связку VisualMicro и Atmel Studio.
                      Ставил, удалил. Не нужна.
                • 0
                  Есть нативный ESP SDK.
                  • 0
                    Там для меня чересчур сложно. Пока не для моей квалификации. А вот NodeMCU в самый раз.
            • 0
              Я правильно понимаю, что никакой обвязки данный ESP-модуль не требует? Даже на ch_en не надо 3.3в подавать?
              • 0
                Если брать голый чип, как на фото — там обвязка нужна, если брать на плате типа nodemcu — там все уже сделано :)
                Есть специальные платы под чипы esp8266 — там сразу обвязка минимальная есть — только чип напаять надо… но это вероятность плохой пропайки или…
                • +1
                  Спасибо, просто по статье создается впечатление, что Вы взяли модуль и использовали его as is. Про nodemcu я в курсе, лучше wemos d1 mini брать, он очень компактный и там мощный LDO 3.3v (500ma)
                  • 0
                    я брал, который прямо на фото и лепил сверху обвязку — два резистора. просто это уже настолько мелкие детали…
                    Скрытый текст
                    <img src="" alt=«image»/>


                • 0

                  А еще можно взять Raspberry или любой аналог (главное, чтобы был WiFi и USB) и запускать Arduino IDE прямо на нем. Это если временно нужен беспроводный программатор для Arduino.

                  • 0
                    Atmel Studio нет под мак :( Есть какие-нибудь приятные альтернативы Arduino IDE?
                  • 0
                    На фото USB UART адаптер с логикой на 5V, не боитесь убить ЕСПшку?
                    Логика у ЕСП 3.3v. Укажите в статье, что UART адаптер нужен с логикой на 3.3v!
                    • 0
                      Да, не… Не переживайте. У этих адаптеров логический адын где-то 3,2-3,4 Вольта.
                      Они так специально сделаны, чтобы их и трехвольтовые и пятивольтовые понимали.
                      Но вот если у вас 1,8 вольт устройство, тогда да.
                      • 0
                        У ESP по даташиту логика держит до 6В
                        • 0
                          да, вполне. Во всяком случае из-за логики не разу не горели. А вот из-за питания полыхнула один раз.
                          • +1
                            Особенно переполюсовку не любят.
                            • 0

                              Выход ESP от 5В логики выгорал :(

                            • 0
                              это точно? прям так написано?
                              • 0
                                Открыл даташит, написано: maximum VIH = 3.3V. Пришлите ссылку пожалуйста. А то получается, что Вы знаете правду, а сотни тысяч таких как я, не ведающих, делают обвязку на резисторах… Буду очень благодарен.
                            • +1
                              статья кошерна, пишите ещё.
                              • 0
                                Спасибо. Обязательно.
                              • +1
                                По поводу программирования ESP8266 — есть ESP Open SDK + ESP Open RTOS — можно прогать на C с использованием OpenRTOS, + там есть библиотеки для работы с периферией, TCP/IP стек, MQTT и т. д. Если хватает GPIO ног, можно использовать только ESP8266 без ардуины или других контроллеров.
                                • 0
                                  Да, всё можно, кто ж мешает? Делайте.
                                  Но мне лично NodeMCU и LUA за глаза хватает для работы.
                                  Если кому-то интересно ваять с нативным SDK only на ESP, нет проблем, ваяйте.
                                  Без шуток, с интересом и удовольствием почитаю статьи с вашими наработками.
                                  Тем более форум по ESP смотрю регулярно.
                                • 0
                                  А кто-нибудь знает, как связать 2-е Wemos D1 (или2-е [Arduino + ESP]) непосредственно, без использования Wi-Fi-роутера? То есть в случаях, когда НЕТ Интернета?
                                  В Сети искал, но без успеха.
                                  Если у кого есть рабочий код — пожалуйста, поделитесь, если можно.
                                  • 0
                                    Надо третью ESP, чую. Она будет точкой доступа, а две другие будут через нее общаться.
                                    • 0

                                      Один чип в режим WIFI_STA, второй в WIFI_AP (назначит себе адрес, если не ошибаюсь, 192.168.4.1). В чем проблема?

                                      • 0
                                        Тут надо пробовать практически. Как местное API внутри устроено сразу и не скажешь. Для меня допустим необычным оказалось то что в NodeMcu в ТСР сервере можно делать только один сокет, что рубит на корню стандартную модель подключения клиентов, когда после подключения клиенту дается новый номер порта и продолжает слушаться старый порт.
                                        Поэтому теоретически в режиме точки доступа ESP должно позволять и регистрироваться у себя и одновременно адресоваться, а на практике пока не попробуешь, не узнаешь.
                                        • 0

                                          Там внутри не UNIX, 146% ;) И все в 1 потоке. Думаю, что проблема в этом.
                                          А так, датчик температуры в режиме WIFI_STA скоро год как отправляет результаты измерений по http на контроллер в режиме WIFI_AP_STA, проблем не замечено.

                                          • 0
                                            Не, там можно открыть, как минимум три сервера по одному сокету. Так что многопоточность там есть. Просто наверное такая реализация кривая.
                                            • 0

                                              "реализация кривая" == "многопоточности там нет" ;)


                                              Из своего опыта: сделал на lua (с смысле скачал готовый модуль с github ;) ) сервер, который умеет принимать от датчика температуру и отображать на веб-страничке. Работает. Добавил синхронизацию времени по ntp (тоже готовый модуль, вроде как в nodemcu встроенный). В момент синхронизации перезагружается без никакой диагностики. Плюнул, переписал на С.

                                    • 0
                                      >конденсатор 15 пФ, между выводом передачи данных и выводом синхронизации
                                      А что этот конденсатор делает?
                                      • 0
                                        очевидно имитирует емкость
                                        • 0
                                          Да, я знаю, что конденсатор — это ёмкость. Но я вот не понимаю, зачем нужна ёмкость между данными и синхронизацией.
                                          • 0
                                            Я тоже не понимаю, но пока нет возможности разобраться. Фронты корежит, что емкостью, что шлейфом. Видимо удачно.
                                      • 0
                                        По заявкам радиослушателей, надо все-таки зафигачить загрузчик в окошке.
                                        Будет примерно так.

                                        • –1
                                          У ESP настолько больше ресурсов (CPU, RAM, Flash..), что в связке с ESP Arduino имеет смысл ставить разве как расширитель портов. Я бы выкинул Arduino совсем и переписал все на ESP. И управление будет и прошивка по воздуху. А то получилось как привязать мотоцикл к самокату — можно, но смысл?

                                          Кстати не понял фразу: «но пока у вас нет на AVR операционной системы, скетчи так и будут отбирать у друга периферию и регулярно глючить». Скетчи и есть те же самые программы на C. Только там используется своего рода «надстройка» и все. Глючат они только от кривых рук. Во множественном числе на одном устройстве одновременно не встречаются, а «операционные системы» здесь вообще ни при чем.

                                          • 0
                                            Пример — скетч А написаный одним скетчистом использует счетчик Т1 (часто), скетч B, написаный другим, использует счетчик T1(очень редко).
                                            Пользователь, ставит оба и регулярно удивляется глюкам.
                                            Любая ОС, к примеру, на каком-нибудь расбери, просто разделяет подобные вещи на системном уровне не видном для пользователя. На AVR этого естественно нет.

                                            Про ESP и замену им Arduino — гугл и форумы электронщиков для развлечения. Даже не буду повторяться. Этот ваш срач вечен. Нормальные люди в нем не участвуют, а делают как им удобнее.
                                            • 0

                                              Если накопипастить откуда попало разных кусков кода и слепить их вместе… Это проблема кросплатформенная ;)

                                              • –1
                                                Вы путаете «скетч» и «библиотеку». Скетч это вся программа. Нельзя установить на Ардуино сразу две. А проблема с библиотеками решается документацией (если есть) и проверкой того что применяешь перед применением.

                                                ОС для Ардуино бессмысленна в связи с минималистическими ресурсами — для полезной программы ничего не останется, не говоря уже о нескольких.

                                                ESP не замяняет Ардуино — у обоих свои ниши применения. Для например сенсоров на батарейках я бы взял Ардуино (ESP слишком прожорлив), а если нужно WiFi, тогда не следует множить сущности без надобности — ESP прекрасно без Ардуино обойдется. «Удобство» — это для «Мастеров самоделкиных». Профессиональный разработчик не будет ухудшать устройство по всем параметрам (цена, потребление, сложность, устойчивость итд.) вставкой ненужных компонентов. А где вы здесь «срач» увидели — мне неведомо.
                                                • 0
                                                  Кстати насчет «срача» — зачем в карму-то? Склочный вы человек. И к конструктивной критике не способный. Детство какое-то :/
                                                  До свидания, работайте над собой, надежда есть всегда :D
                                              • 0
                                                Про скетч ладно. Речь получается была про библиотеки.

                                                Про остальное — кормить не буду, не надейтесь.
                                                • –1
                                                  Я (как профессиональный разработчик, зарабатывающий этим ремеслом уже более 20 лет) указываю на проблемы вашего решения, чтобы по крайней мере другие пользователи не повторяли тех-же ошибок. Вам это конечно не надо, т.к. вы же уже имеете свое непреложное мнение и не хотите, чтобы вас смущали какими-то там «опытом» «фактами» :D
                                                  Так что начет «надеятся» — не в кассу.

                                                  • 0
                                                    Ошибки это когда не работает. А здесь варианты реализации, дорогой «профессиональный разработчик», у которого в публикации «Умный Дом» стоит та же ардуинка в связке с той же espшкой.
                                                    А что ж на нативном SDK не разработали???
                                                    • 0
                                                      Это не ESP, это nRF24 — радиомодуль, не микроконтроллер. Вы уж читайте, перед тем как написать.

                                                      Я вполне себе использую и ESP и Ардуинки для различных назначений, но не в качестве костылей.
                                                      Например вот: s6z.de/cms/index.php/homeautomation-homecontrol/hardwareplattformen/esp8266/139-onewire-wlan-bridge-auf-basis-esp8266
                                                      и вот: s6z.de/cms/index.php/homeautomation-homecontrol/hardwareplattformen/esp8266/138-mysensors-wlan-gateway-milight-bridge
                                                      • 0
                                                        Да, кто ж спорит. Когда я делаю, тогда это вполне себе использую ардуино и esp. Когда другие эти же занимаются… Ну они только в качестве костылей.
                                                        • 0
                                                          Ардуино и радиомодуль. Финиш. Нет, что бы одну ESP взять и все на ней сделать.
                                                          • 0
                                                            Действительно финиш.
                                                            Вы не знаете разницы между ESP (WLAN) и nRF24L01 (создает легковесную радиосеть). Совершенно разния свойства и области применения.
                                                            • 0
                                                              Легковесную радиосеть? Надо же, какое убогое решение.
                                                              Нет, чтобы на одной ESP по WI-FI все разбросать.
                                                              Все профессионалы на ESP делают, а он на ардуине и прочей ерунде!
                                                              • 0
                                                                А Вы-то, батенька, похоже что троль :D
                                                                Ну и о профессионализме — не с вами говорить. Веселых вам поделок ;)
                                                      • 0

                                                        Опубликовали заметку — готовьтесь получать критику. "Сам дурак" — это конструктивно, даа…
                                                        На то и самодельщики, каждый делает что хочет из того что нравится/умеет/хочет попробовать.

                                                        • 0
                                                          Критика это когда: «У вас так реализовано?» — «Понятно», — «А у меня или у него, то же самое, но вот в таком варианте. Вот работающий пример».
                                                          А не так: «На Луну слетал?» — «Дурак, можно было на Марс. Нет я не летал. Но ведь можно же».
                                                          Тут куча комментов, что можно делать на ESP only. Но вот по сравнению с Arduino + ESP, реальных примеров, совсем как-то мало.
                                                          • 0
                                                            Задача 'беспроводный программатор для Arduino на ESP8266' уже решалась
                                                            .
                                                            А для управления чем-то в realtime… Не уверен что это хорошая идея. Работает — и ладно.
                                                            • 0
                                                              Это жесть. Особенно:

                                                              Given that I had an experimental avrdude.exe, which lacked USB support, i created a whole new Hardware package and modified the platform.txt to allow me to use the modified avrdude, with the correct parameters and to also ensure that I downloaded the bootloader together with the firmware,

                                                              и концовка оптимистичная

                                                              I'll hold off on publishing the .txt files «я пока воздержусь от публикации txt файлов» for the IDE as I am currently not 100% sure if I'm doing something wrong, expecting the wrong behaivour of the IDE or there is a bug in the IDE.

                                                              Полгода уже воздерживается, вроде как.
                                                              • 0

                                                                Самодельщики они такие ;)
                                                                Запилить решение, совместимое с чем-то общепринятым — это прекрасная идея. Но не всегда получается довести это дело до успеха.

                                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.