Programmierung und Datenaustausch mit „ARDUINO“ über WI-FI über ESP8266, Teil Zwei

    Sehr geehrte GeekTimes-Leser, der folgende Artikel aus dem Zyklus (hoffentlich nicht der letzte) zur Verwendung des ESP8266-Chips als drahtlose Brücke für AVR-Mikrocontroller, am Beispiel der Arduino Uno (Nano) -Hardwareplattform.

    Nach dem ersten Artikel zu diesem Thema erhielt ich viele freundliche Antworten wie: "Warum zum Teufel haben Sie sich anstrengen, wenn alles ausschließlich auf ESP8266 gemacht werden konnte" oder "Warum haben Sie esp-link nicht verwendet ". "Wirklich warum?" - dachte ich, ich habe diesen Artikel bereits ausgerollt und einige meiner Programme als neue Argumente aktualisiert.

    Also, treffen Sie den kabellosen Programmierer für AVR-Mikrocontroller BABUINO Version 0.9



    Details unter der Katze:

    Die ursprüngliche Version des Programms wurde im vorherigen Artikel veröffentlicht und tat im Prinzip fast das gleiche wie die neue Version. Aber es war äußerst unbequem in der Arbeit. Da jedoch und im Wettbewerb mit esp-Link. Daher habe ich die GUI mit einem Seufzer an JAVA geschraubt. Jetzt können Sie die Datei, die Sie herunterladen möchten, über den Fenstermanager sicher auswählen und die IP-Adresse des Zielgeräts bearbeiten. Ich habe die TCP-Portnummer trotzdem fest genäht (sie wird nur im Code bearbeitet), aber theoretisch muss sie nur geändert werden, wenn dieser Port an anderer Stelle verwendet wird (aber dann müssen Sie ihre Nummer in der ESP8266-Firmware ändern).

    Der Mikrocontroller wird auch verwendet, während derjenige mit einer FLASH-Speichergröße von 32 KB beispielsweise der bekannte Mega328P ist. Wie ich im letzten Artikel erwähnt habe, näht mein Programmierer theoretisch Versionen in 16 KByte und vielleicht sogar 8 KByte. Und natürlich in 64 KB und 128 KB Versionen des AVR, kann er die ersten 32 KB Speicher wahrscheinlich sogar flashen. Aber ich habe keine Mikrocontroller in der Hand und ich kann wirklich nicht sagen, wie es wirklich ist. Der springende Punkt ist, dass 16-Bit-Adressen in Standard-SPI-Programmierbefehlen so geschickt aufgeteilt und geschnitten werden (Bit hier, Bit dort), dass es nicht leicht zu verstehen ist, wie alles mit einer anderen Speichergröße als 32 KByte aussehen wird.

    Ja, das Programm wird nach der Aufnahme nicht verifiziert, die Sonderregister des AVR sind nicht lesbar, das EEPROM schreibt auch nicht. Theoretisch ist es jedoch möglich, auf Probleme zu verzichten (im Gegensatz zu den grundsätzlichen Einschränkungen beim Laden von Code über den UART, wie bei esp-link). Sie können hinzufügen, ich habe nichts dagegen, das Produkt ist nicht kommerziell.

    Hier ist die ausführbare Datei für 64-Bit-Windows . Daraus können Sie Java-Code herausreißen. Oder nimm Gitkhab an

    Also fangen wir an.

    Dann ist alles einfach, öffnen Sie die HEX-Datei, die Sie benötigen (ja, das Programm hat gelernt, das BIN-Format in HEX umzuwandeln, Hurra!) Geben Sie die IP-Adresse des ESP8266 ein, die Sie benötigen, und klicken Sie auf „Hochladen“ (wie Sie die IP-Adresse des ESP-Moduls finden - eine separate Geschichte). Wenn der Programmierer den ESP8266 findet, packt er Ihren Code schnell (viel schneller als esp-link) und schickt ihn selbst über die SPI-Schnittstelle an den AVR-Mikrocontroller. Der Programmierer beschreibt detailliert seine Aktionen im Fenster und kann sogar als vertrauenswürdig eingestuft werden, mit der Ausnahme, dass das Programm im AVR aufgezeichnet wird. Wie ich bereits gesagt habe, gibt es keine Überprüfung des Datensatzes, aber die SPI-Schnittstelle ist rein synchron, es ist in der Regel auf der Trommel, befindet sich jemand am zweiten Ende der Zeile oder nicht. Er wirft die Daten und die Antwort wartet nicht.

    Nachdem Sie das Programm geschlossen haben (über „Stopp“ oder einfach das Fenster schließen), werden die von Ihnen eingegebenen Daten (wenn Sie zuvor auf die Schaltfläche Hochladen geklickt haben) in der Datei tcp_dat.txt im Stammverzeichnis von Laufwerk C gespeichert, damit Sie beim erneuten Öffnen nicht lange leiden müssen rekrutieren. Im Allgemeinen kann das Programmfenster nicht geschlossen werden. Erfahrungsgemäß stört es niemanden.

    Wenden wir uns nun dem ESP-Modul zu und rufen Sie erneut auf, um detailliert zu erfahren, wie Sie es an den AVR anschließen und wie man es flashen kann, um den oben genannten Programmierer verwenden zu können und die Daten auch einfach ohne WLAN über WLAN zu steuern.

    Also zuerst den Schaltplan. Bitte beachten Sie, dass wir ESP8266 in Versionen mit ausreichender GPIO-Menge benötigen. Für die Programmierung auf der SPI-Schnittstelle benötigen wir freie Ausgänge für RESET, MOSI und SLK. Abgesehen davon, dass wir für den Datenaustausch auch den üblichen UART mit RX und TX verwenden. Dafür erschien mir der günstigste Preis und die beste Qualität ESP8266-07.

    Wir nehmen es und löten sofort zwei Widerstände mit einem Nennwert von 5-10 kΩ. Die erste nach EN (CH-PD) und die Stromversorgung, die zweite nach GPIO15 und Erde.



    Jetzt können Sie es an den Adapter anschließen, über den wir die NodeMCU-Firmware hochladen und dann unser Ladeprogramm auf LUA.



    Adapter Millionen, nimm irgendwelche. Verbinden Sie wie gewohnt RX c TX und umgekehrt. Wir machen die Erde gemeinsam. Der ESP8266 wird separat mit Strom versorgt, und der Adapter reicht für den USB-Anschluss aus. Wir werfen Null auf GPIO0 und füllen die neueste NodeMCU-Firmware (Sie können sie hier mitnehmen oder Ihre eigene erstellen) über das NODE MCU PyFlasher-Programm .



    All dies ist im vorherigen Artikel und im Internet oft beschrieben. Entfernen Sie als Nächstes die Null mit GPIO0 (Sie können es einfach hängen lassen, das ist in Ordnung) und öffnen Sie die ESPlorer- Umgebung zum Debuggen und Herunterladen von Programmen in Lua. Diese Infektion ohne die Java-Umgebung funktioniert zwar nicht. Also dieses Ding ( Lade Java jetzt auf deinem Desktop-Computer herunter! ) Muss sowieso gestellt werden.

    Nachdem er sich mit ESPlorer verbunden hat, formatiert er das ESP-Modul leicht und informiert Sie mit den entsprechenden Meldungen. (die Hauptsache, in diesem Moment nichts zu berühren) und dann ESP rebutnet. Sie können mit dem Laden von LUA-Programmen beginnen.



    Und wir werden folgendes Programm haben :

    Lader für AVR nach Lua in ESP8266
    function InstrProgrammingEnable () -- instruction for MC "enable programming"
    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
    function ProgrammingDisable ()
    pin=2--END OF RESET FOR MK GPIO4
    gpio.mode(pin, gpio.INPUT)
    pin=8  
    gpio.mode(pin, gpio.INPUT) -- CE chip enable not used GPIO15
    pin=5--CLK MASTER for SPI GPIO14 used
    gpio.mode(pin, gpio.INPUT)
    pin=6--MISO MASTER  for SPI GPIO 12 may not used
    gpio.mode(pin, gpio.INPUT)
    pin=7--MOSI MASTER for SPI //GPIO13 used
    gpio.mode(pin, gpio.INPUT)
    end
    --PROGRAMMING ENABLE
    function ProgrammingEnable ()
    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
    function InstrFlashErase() 
    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
    function InstrStorePAGE(H, address, data)
    pin=8  
    gpio.write(pin, gpio.LOW)
    spi.send(1,H,0,address,data)
    gpio.write(pin, gpio.HIGH)
    tmr.delay(500)
    end
    function InstrWriteFLASH(page_address_low,page_address_high)
    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
    function Programming (payload)
    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
    --MAIN BLOCK
    wifi.setmode(wifi.STATION)
    --wifi.sta.config("SSID","password ") -- set SSID and password of your access point
    station_cfg={}
    tmr.delay(30000)
    station_cfg.ssid="SSID"
    tmr.delay(30000)
    station_cfg.pwd="Password"
    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
    prog_address="";
    sv=net.createServer(net.TCP,30)
    tmr.delay(100) 
    --print("SERVER READY")
    sv:listen(40000,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")
                tmr.wdclr()
                spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8,80,spi.FULLDUPLEX) -- настройка SPI 320 примерно 115 000 кБод
    --на 80 еще работает это 1 мбит
                ProgrammingEnable ()
                tmr.delay(100)
                InstrProgrammingEnable ()
                tmr.delay(100)
                InstrFlashErase()
                tmr.delay(100)
                frame1024=0--номер переданного фрейма
                st=net.createServer(net.TCP,30)--Сервер для приема файла программы и трансляции ее в AWR, выключается командой stop program
                st:listen(40001,function(c)
                c:on("receive", function(c, payload)
                tmr.wdclr()
                Programming (payload)
                frame1024=frame1024+1
                end)
                end)
            end
            if (payload =="data\r\n")
            then
                tmr.wdclr()
                c:send("ready\r\n")
                --  print("ready for data\r\n")
                c:on("receive", function(c, prog_address_payload)
                prog_address=prog_address_payload--получаем IP адрес UDP хоста для отправки к нему данных
                --  print(prog_address)
                c:send(prog_address) 
                srv=net.createUDPSocket()-- Сервер для приема данных , выключается командой data stop
                srv:listen(50000)
                uart.setup(0,9600,8,0,1,0) 
                srv:on("receive", function(srv, pl) -- принимаем данные с компьютера по UDP
                pl=pl*1
                --     print(pl)
                uart.write(0,pl) -- отправляем их по UART на AVR
                end)
                uart.on("data", 1, function(data) -- принимаем данные по UART из AVR
                srv:send(50000,prog_address,data) -- отправляем их по UDP на компьютер
                end, 0)
                tmr.wdclr()   
                end)
           end
           if (payload =="stop data\r\n") -- здесь закрываем ненужные уже сервера
           then
                 ready = false
                 if(srv~=nil) 
                 then
                    srv:close()
                     --  print("stop data")
                 end
                    collectgarbage()   
           end
           if (payload =="stop program\r\n") 
           then 
                if(st~=nil)
                then
                    st:close()
                    frame1024=0
                    ProgrammingDisable ()
                    -- print("stop program")
                end
                collectgarbage()
           end
        end)
    end)


    Es ist fast dasselbe wie im ersten Teil beschrieben, aber jetzt ist es nicht nur möglich, den Datenstrom vom Computer zum AVR-Mikrocontroller zu übertragen, sondern auch in umgekehrter Richtung.

    Während des Schreibens musste ein interessanter Haken gelöst werden. Wenn wir Daten mit einem UDP-Protokoll von einem Computer auf den ESP8266 herunterladen, treten keine Probleme auf. Die IP-Adresse des ESP-Moduls ist bekannt (wir fahren es am Anfang selbst, wenn das der Fall ist), der Port ist bekannt, alles ist in Ordnung. Wenn wir jedoch versuchen, Daten in die entgegengesetzte Richtung zu senden, können wir dies nicht tun, da das ESP-Modul die IP-Adresse des Computers, auf dem der Programmierer ausgeführt wird, nicht kennt. Er weiß es vielmehr, denn vorher nehmen wir über das TCP-Protokoll Kontakt auf, um Steuerbefehle (Programm, Daten, Stopp) zu senden. Bei Verwendung dieses Protokolls tauschen Geräte ihre Adressen aus, da es bidirektional ist. Aber er wird es uns nicht erzählen. In jedem Fall habe ich keine Funktion in der NodeMCU-API gefunden, um sie herauszuziehen. Natürlich können Sie die IP-Adresse des Computers direkt in den Bootloader des ESP8266 eintreiben. Dies ist jedoch keine Option. Plötzlich führen wir ein Programm aus, um Daten auf einem anderen Computer auszutauschen. Oder er hat keine Netzwerkkarte.

    Also machte ich eine Krücke. Wir übertragen die IP des Computers, auf dem das Programm läuft, explizit vor dem Datenaustausch. Glücklicherweise gibt es in der JAVA-API eine Funktion zum Bestimmen der Netzwerkadresse des Hosts, auf dem das Programm ausgeführt wird. Nachdem der ESP8266 diese Adresse erhalten hat, kann er nun problemlos Daten nicht nur an den AVR senden, sondern auch von diesem. Was das Programm bei LUA angeht, so ist es sehr eichelig, naiv und simpel. Dies liegt daran, dass ich in dieser Sprache immer noch sehr schlecht orientiert bin.

    Also registrieren wir den aktualisierten Bootloader mit Hilfe von ESPlorer in ESP8266. Vergessen Sie nicht, die Datei zunächst als init.lua aufzurufen oder über ESPlorer umzubenennen, andernfalls wird sie nicht gestartet . Nun, natürlich schlagen Sie in den Körper (wo MAIN BLOCK) des Bootloaders Ihren Netzwerknamen und Ihr Kennwort.

    Als nächstes müssen wir die IP-Adresse des ESP-Moduls in unserem internen Netzwerk ermitteln und festlegen. Wir gehen unter Administratorrechten zum lokalen Router und sehen so etwas.



    Diese Adresse ist immer noch dynamisch (dh eine andere kann nach der Wiederverbindung zugewiesen werden). Daher stellen wir die Bindung an die ESP8266-MAC-Adresse an derselben Stelle im Router her.



    Sie können es sogar (die letzten Ziffern) auf das Modul selbst schreiben, wenn Sie Sklerose haben.



    Das ESP-Modul ist betriebsbereit, Sie können es mit dem AVR-Mikrocontroller verbinden.



    Führen Sie BABUINO aus, geben Sie die IP-Adresse des ESP-Moduls ein, wählen Sie die HEX-Datei (einige BLINK) aus, klicken Sie auf „Upload“ und genießen Sie die blinkende LED. Der Programmierer schreibt so etwas in sein Fenster:



    Manchmal kann es jedoch passieren, wenn das ESP-Modul aus irgendeinem Grund den Mund hält:



    Nun sehen wir, wie unser Bootloader in ESP8266 Daten in beide Richtungen austauschen kann. Zu diesem Zweck verwalten wir den Roboterwagen über die Tastatur des Computers und senden uns einen eigenen Verfahrweg. Mein erster Allrad-Robo-Wagen starb am Tod des Mutigen, erhielt ein Signal vom Weltraum und fiel vom Tisch (diese astrale Tatsache wird später erklärt). Bis ein neuer Acrylrahmen aus China kommt, werden Experimente an einem zweirädrigen Roboterwagen durchgeführt, den ich übrigens seit ungefähr einem Jahr versucht, auf zwei Rädern zu balancieren, jedoch bisher ohne Erfolg. Gemäß dem Schaltplan der Elektronik und dem Programm für den AVR unterscheiden sich diese Wagen nicht, die wir verwenden werden.



    Das Programm für die Arbeit des Wagens ist in C geschrieben und sollte keine großen Verständigungsschwierigkeiten verursachen. Wir schreiben ständig den neuen Geschwindigkeitswert in die PWM-Controller-Register und geben Signale an die Motoren. Am internen Mikrocontroller-ADC befindet sich eine Rückkopplungsschaltung. Wenn die Batteriespannung abfällt, erhöht sich die Geschwindigkeit programmatisch. Daher rollt der Wagen bis zu einer vollständigen Absenkung mit konstanter Geschwindigkeit. Unterm Strich gilt: Je dichter die PWM-Füllung ist, desto schneller drehen sich die Motoren, aber da die Batteriespannung mit der Zeit abfällt, drehen sie sich langsamer. Dann steigt die PWM-Füllung und sie drehen sich wieder schneller. Während also die PWM nicht zu 100% gefüllt ist, ist die Ausgabe immer eine logische "1". Es ist nichts zu tun. Beim aufladen!

    C-Programm für einen Mikrocontroller AVRmega328P
    /*
     * TWO_WEELS_ROBOT_NEW.c
     *
     * Created: 22.09.2017 23:48:49
     * Author : User
     */ 
    #define F_CPU 16000000
    #include <avr/io.h>
    #include <stdint.h>// стандартные целые числа
    #include <avr/interrupt.h>
    #include <math.h>	// математика
    #include <stdio.h> //стандартный ввод-вывод
    #include <setjmp.h>
    #include <stdlib.h> //стандартные возможности
    volatile uint8_t Speed_of_ADC_conversion=0;
    volatile uint8_t U_BATTERY; //среднее напряжение  подаваемое на моторы деленное на три
    volatile uint8_t avr_speed=30;// граница скорости, к которой сводится обратная связь с напряжения
    // при 8 вольтах батареи макс скорость равна где-то 110
    // средняя , берите 53. На 10 еле ползет
    volatile uint8_t komanda_s_kompa = 0;
    volatile uint8_t transmition_ready = 0;
    volatile uint8_t wheel_counter=0;
    #define Left_Speed  OCR0A	// скорость левых моторов
    #define Right_Speed  OCR0B  // скорость правых моторов
    	void time_delay(long dell)// передается время в миллисекундах
    							//   функция для временных задержек
    	{ long i;
    		cli();
    		sei();
    		dell=dell*1500;
    		for(i=0;i<dell;i++){;;};
    	}
    ISR(USART_RX_vect)  //получаем команды управления через UART
    {
    	komanda_s_kompa=UDR0;
    }
    ISR(PCINT1_vect )//PC2 int 10 //вход счетчика оборотов колеса
    {
    	transmition_ready=1;
    	wheel_counter++;
    }
    ISR(TIMER0_OVF_vect)// старт цикла запускаем ацп каждые 30 мс, 
    	// на первом цикле запускается АЦП, на втором корректируется скорость раз в 90 мс
    {
    	Speed_of_ADC_conversion++;
    		if (Speed_of_ADC_conversion<2)
    		{ADCSRA |=(1<<ADSC);}// запускаем АЦП
    		if(Speed_of_ADC_conversion>2)// запускаем коррекцию скорости 
    	{
    		ADCSRA &=~(1<<ADSC);
    		Speed_of_ADC_conversion=0;
    		U_BATTERY = ADCH;////регистр данных с ацп
    						// в него заносится напряжение с моторов, через делитель 1/3 и
    						// и интегрирующий конденсатор поскольку напряжение с ШИМ импульсное 
    						//т.е макс U = 8 вольт (2 литиев батарейки - LN298 1 вольт)   = 7 вольт / 2
    						// равно 3,5 т.к. вокруг нуля и еще делитель ,то на вход АЦП попадет  около 1 вольт 
    			if(U_BATTERY<=avr_speed)// коррекция скорости
    				{Right_Speed++;// если притормозили из-за расхода батарей, то увеличиваем скорость
    				Left_Speed++;}
    				else
    				{Right_Speed--;// если разогнались, то притормаживаем
    				Left_Speed--;}
    	}
    }
    void stop()
    {
    	PORTD|=(1<<PORTD3);
    	PORTD|=(1<<PORTD2);
    	PORTD|=(1<<PORTD4);
    	PORTD|=(1<<PORTD7);
    }
    void go_left()
    {
    	PORTD|=(1<<PORTD3);// правый вперед
    	PORTD&=~(1<<PORTD2);
    	PORTD|=(1<<PORTD4);// левый  назад
    	PORTD&=~(1<<PORTD7);
    }
    void go_right()
    {	
    	PORTD|=(1<<PORTD2);// правый назад
    	PORTD&=~(1<<PORTD3);
    	PORTD|=(1<<PORTD7);//левый вперед
    	PORTD&=~(1<<PORTD4);
    }
    void go_ahead()// движение вперед  
    {
    	PORTD|=(1<<PORTD3);// вперед
    	PORTD&=~(1<<PORTD2);
    	PORTD|=(1<<PORTD7);//вперед
    	PORTD&=~(1<<PORTD4);
    }
    void go_back()// движение назад
    {
    	PORTD|=(1<<PORTD2);// правый назад
    	PORTD&=~(1<<PORTD3);
    	PORTD|=(1<<PORTD4);// левый  назад
    	PORTD&=~(1<<PORTD7);
    }
    int main(void)
    { cli();
    	//инициализация UART на 9600
    	UCSR0A=0;
    	UCSR0B=0b10011000;
    	UCSR0C=0b00000110;
    	UBRR0L=103;
    	UBRR0H=0;
    	//инициаализация внешнего прерывания INT0 на порту С2 номер прерывания 10
    	PCICR|=(1<<PCIE1);// разрешение группы прерываниС14-8
    	PCMSK1|=(1<<PCINT10);// разрешение конкретного прерывания INT10
    	DDRC&=~(1<<PORTC2); // порт на вход для прерывания от  геркона
    	PORTC|=(1<<PORTC2);
    	// инициализация АЦП напряжение подаем на ADC1, 
    	ADMUX= 0b01100001;  // V ref питание 5 в, сдвигаем результат ADC1  преобразования влево в старший регистр, канал 2
    	ADCSRA=0b10010110;// прерывания от ацп запрещены опрашиваем программно
    	ADCSRB=0;
    	DDRC&=~(1<<PORTC1);//порт ацп/
    	// инициализация счетчика Т0 для ШИМ модуляции регистр А левые моторы, регистр B правые
    	TCCR0A |=(1<<COM0A1)|(1<<COM0B1);//внешние выводы включены
    	TCCR0A &=~(1<<COM0A0)&~(1<<COM0B0);
    	TCCR0A |=(1<<WGM00);
    	TCCR0B &=~(1<<WGM02)&~(1<<WGM01);// режим ШИМ c точной фазой
    	TCCR0B|=0b00000101; // частота переполнения 30 гц
    	// CS02 CS01 CS00 - 000 - отключен; 001  без делителя; 010 c делителем 8; 
    	// 011 -64; 100 -256; 101 -1024
    	TIMSK0|=(1<<TOIE0);// разрешаем прерывание от Т0 по переполнению
    	DDRB|=(1<<5);// зеленый светодиодный выход
    	DDRD=0b11111110; // порты для моторов и ТХ на выход, RX на вход
    	PORTD&=~(1<<PORTD5)&~(1<<PORTD6); // останов моторов после сброса
    	Left_Speed=10;// начальная скорость моторов маленькая для плавного разгона
    	Right_Speed=10;//максимальная скорость моторов определяется напряжением батареи ( 8-12 в)
    	sei();
    	PORTB |=(1<<5);//помигаем после сброса
    	time_delay(500);
    	PORTB &=~(1<<5);
    	time_delay(500);
    	PORTB |=(1<<5);
    	time_delay(500);
    	PORTB &=~(1<<5);
    	time_delay(500);
    	PORTB |=(1<<5);
    	while (1)
    				{	
    				if( (UDRE0)){
    				if(transmition_ready==1)// отправляем данные если путь увеличился
    					{
    					UDR0=wheel_counter;	
    					transmition_ready=0;
    					}
    				}
    				switch (komanda_s_kompa)
    				{
    				case 2:
    				go_right();
    				break;
    				case 1:
    				go_left();
    				break;
    				case 3:
    				go_ahead();
    				break;
    				case 4:
    				go_back();
    				break;
    				case 5:
    				avr_speed++;
    				if (avr_speed>100)
    				{
    					avr_speed=100;
    				}
    				time_delay(200); // газуем
    				break;
    				case 6:
    				avr_speed--;
    				if (avr_speed<0)
    				{
    					avr_speed=0;
    				}
    				time_delay(200);// тормозим
    				break;
    				case 0:
    				stop();
    				break;
    				}
    				}
    }	


    Der zurückgelegte Weg wird als Reed-Schalter betrachtet, der einen externen Interrupt INT10 ausgibt. Sobald der Pfad inkrementiert wird, werden die Daten sofort in den UART übernommen. Dementsprechend kommen die Steuersignale (vorwärts, rückwärts, links, rechts, Gas, Bremse, Stopp) in entgegengesetzter Richtung vom UART.

    Bitte beachten Sie, dass die chinesischen Motoren mit schrecklicher Kraft arbeiten, so dass keine Leistungskondensatoren helfen. In der Reed-Schalter-Kette wird eine solche Störung verursacht, die den Anschein hat, dass Ihr Trolley an der Formel 1 gemäß der Geschwindigkeit der Route teilnimmt. Rescues verschluckt nur ein 22-nF-Kondensator am Eingang eines externen Interrupts diese Interferenzen.

    Das Programm zum Rollen des Wagens ist dem vorherigen Artikel entnommen, in dem der mechanische Arm zuvor gesteuert wurde. Es wurden nur kleine Ergänzungen vorgenommen: Zwei Textfelder, in denen Sie die empfangenen und gesendeten Daten in Echtzeit sehen können (1,2,3,4,5,6,0 - vorwärts, rechts, links, zurück, Gas, Bremse, Stopp). sowie die Möglichkeit, die IP-Adresse des ESP-Moduls über die GUI und die Schaltfläche "Verbinden" zu bearbeiten und zu speichern. Wir steuern den Wagen mit den Pfeilen entweder über die Tastatur oder mit der Maus im Fenster. Richtig, da alle Tasten in einem Zyklus die gleichzeitige Änderung der Geschwindigkeit und der Richtung nicht funktionieren, wird dies nur abwechselnd funktionieren. Aber das liegt natürlich nur daran, dass das Programm Demonstration ist.



    Ausführbare Datei für 64-Bit-Fenster . Daraus können Sie Java-Code herausreißen. Oder nimm Github an .

    Jetzt, da der Programmierer und der Datenaustausch getestet wurden (im Allgemeinen habe ich wahrscheinlich mindestens einmal in hundertfach AVR auf WI-FI geflasht), können wir auf die Frage zurückkommen, warum ich diesen Pfad für mich selbst gewählt habe und nicht für esp-link.

    Beginnen wir also mit der Installation.

    Die Firmware des ESP-Moduls ist etwas komplizierter als die eines Mitbewerbers. Zuerst nähen wir eine NodeMCU, dann laden wir den Bootloader in LUA hoch. In esp-link nähen wir nur eine Firmware. Die Zeitkosten sind jedoch einmalig. In Zukunft berühren wir das ESP-Modul nicht. Andererseits können wir in unserem Fall mein Eichenprogramm auf LUA abschließen, wie wir es wünschen, eigene Module hinzufügen usw. usw. Mit esp-link ist das komplizierter. Das Wissen über die Grundlagen von LUA und API NodeMCU wird nicht weitergegeben.

    Auf der Computerseite liegen die Vorteile vollständig in BABUINO. Führen Sie einfach die ausführbare Datei aus und arbeiten Sie. Sogar die JAVA-Umgebung ist nicht erforderlich, wenn Sie eine 64-Bit-Version von Windows haben (aber dann eine 200 MB-Festplatte benötigen). Wenn Sie über Linux oder MacOS verfügen, können Sie im Allgemeinen den Slogan des Oracle-Unternehmens zu Java überprüfen: „An einem Ort geschrieben, funktioniert überall“, da die Java Virtual Machine den gleichen Bytecode enthält. Aber ehrlich gesagt nicht überprüft, ich weiß es nicht.

    Mit esp-link warten laut der Installation des Tibbo-Managers (ich weiß aus Erfahrung) bemerkenswerte Tänze mit Tamburinen auf Sie. Dies ist ein solches Programm zur Unterstützung des virtuellen COM-Ports. Erfordert Einstellparameter und ständige Anwesenheit im System. Sofort kaum arbeiten, befestigen. Dann müssen Sie über den Browser das ESP-Modul selbst konfigurieren. Es ist überall wichtig, auch in Tibbo, die korrekten Datenaustauschraten und alle Stopp- und Paritätsbits einzustellen.

    Danach, bereits durch den Standard-Arduino-Uploader (von dem ich schlafe ... ich habe das Design genommen) oder über die Arduino-IDE (erneutes Einrichten von COM), beginnen wir, das Programm in den AVR zu laden, sehr gut-o-o-olgo. Nein, wirklich, es ist wirklich für immer geladen. Auch wenn klein. In dieser Zeit können Sie Tee kochen. Das Minus fällt periodisch ab, so dass Sie völlig verwirrt sind, warum der Download nicht stattgefunden hat. Und dann gibt es nur einen Ausweg - Reset, Neustart, Reset, Neustart ...

    Und BABUINO wirkt wie ein normaler SPI-Programmierer viel schneller (und Dateien, die in ein Paket passen, sind im Allgemeinen 1024 Byte groß). Richtig, es wird nicht geprüft. Es ist jedoch fixierbar und wird ohnehin nicht viel Zeit in Anspruch nehmen, da es gleichzeitig mit der Firmware ausgeführt wird (eine gute Funktion des SPI-Protokolls). Außerdem stehen uns alle SPI-Programmierbefehle zur Verfügung: Sicherungs- und Sperrbits, EEPROM-Firmware usw. Wenn der Eintrag fehlschlägt, werden alle Gründe im Textfeld angezeigt. Hinweis Befehle sind verfügbar, es gibt jedoch noch keine Implementierung. Ups

    Dies betrifft die drahtlose Programmierung. Wir wenden uns jetzt der Datenübertragung zu. In dieser Hinsicht habe ich esp-link nicht verwendet, so dass meine Argumentation rein theoretisch sein wird.

    So benutzt esp-link, soweit ich weiß, das MQTT-Protokoll. Im Wesentlichen ist dies nur die nächste Abstraktionsebene über TCP.



    Ohne auf Details einzugehen, wollen wir sehen, warum es überhaupt gebraucht wird.

    Nun, zum Beispiel, wenn in einem Smart Home viele Geräte vorhanden sind, die mit diesem Protokoll arbeiten. Wenn Sie etwas haben, geht es in die Wolke und zurück. Wenn Sie sich in ein Netzwerk integrieren, das auf MQTT läuft. Wenn Sie ein gemeinsames Projekt haben, nicht etwas Eigenes zu erfinden, sondern etwas vorgefertigte und bekannte Kollegen einzusetzen.

    Und wenn Sie nur einen Byte-Stream ohne Drähte hin und her schicken müssen, wozu sind Sie so schwierig? Warum sollten Sie ein weiteres Protokoll anhäufen?

    Obwohl ich natürlich die Nützlichkeit der MQTT-Protokolle im Allgemeinen nicht leugne, versuche ich sogar, die Unterstützung in meinen Downloader in den folgenden Abschnitten und Artikeln zu integrieren. Aber obwohl ich ihn nicht brauche, werden wir weiter sehen. Und wenn Sie es brauchen, entscheiden Sie selbst.

    In der Zwischenzeit dreht mein Wagen die Räder gehorsam in die richtige Richtung und sendet die Telemetrie der zurückgelegten Entfernung an den Computer (beachten Sie, dass die Computerfirewall möglicherweise keine Pakete mit ESP zulässt). Das nächste Mal werden wir versuchen, es von einem Mobiltelefon aus zu steuern. Ich habe versucht, es auf der Tastatur auf zwei Rädern zu balancieren, aber die Erfahrung war nicht erfolgreich. Es gibt einen Gedanken, Smartphone-Beschleunigungsmesser zu verwenden (ich habe versucht, eine separate Platine mit einem Gyroskop und einem Beschleunigungsmesser zu verwenden, aber sie hat nicht abgenommen).

    Wir kehren nun zur zweiten Frage zurück, die während der Diskussion des Artikels in den Kommentaren wiederholt aufgeworfen wurde. „Warum nicht alles auf ESP machen? Sie kann! Und sei AVR wie ein Port-Extender und genüge davon. “

    Natürlich kann es! Obwohl alle gleich, wie wir sehen, ohne den AVR das nicht machen kann.

    Ja, das ist möglich, wenn:

    1. Sie ein erblicher, objektorientierter Programmierer sind, der es liebt, sich in alle möglichen Umhüllungen zu packen, Callbacks durchzuführen und nicht ohne Metatabellen das Leben zu denken.

    2. Sie kennen die Details der Arbeit verschiedener Betriebssysteme gut. Und Sie spuckten nur, um das neue Betriebssystem RT (Echtzeit) zu erlernen, dessen Systemaufrufe und Bibliotheken von den Chinesen für eine Schüssel Reis geschrieben wurden.

    3. An der Universität waren Ihre Kenntnisse mit Mikrocontrollern auf ein oder zwei Laborarbeiten beschränkt, und Sie wissen nicht einmal, welche Art von Bits und Peripheriegeräten es gibt. Im Allgemeinen ist es beispielsweise für PWM einfacher, eine Softwarebibliothek zu verwenden, als sie in Hardware zu verwenden.

    4. Sie benötigen keine Geräteantwort in Mikrosekunden. Nein, RTOS kann natürlich versuchen, es für Sie bereitzustellen, da es sich um ein Echtzeitbetriebssystem handelt. Aber nicht die Tatsache, dass es bieten wird.

    5. Sie haben nicht Hunderte von Kilobytes an bereits geschriebenem Code, und am wichtigsten ist, dass Sie bereits ohne Störungen auf dem AVR arbeiten, und Sie müssen ihn nicht entsprechend portieren und debuggen. Es ist jedoch einfacher, das native SDK (das Sie auch aus englischen Quellen spucken müssen) zu schreiben.

    Dann ja. Lesen Sie diesen Artikel nicht. Und vor allem,schreibe keine Kommentare

    Aber wenn:

    1. Sie haben seit vielen Jahren mit Mikrocontrollern gearbeitet und kennen ihre Architektur auswendig.

    2. Sie benötigen keine unverständlichen chinesischen Fehler.

    3. Sie haben in Ihrem langen Leben als Entwickler bereits Megabytes Code geschrieben und debuggt, und Sie möchten nicht unbedingt alles neu schreiben und debuggen.

    4. Sie haben weder die Zeit noch den Wunsch, das native SDK und das Echtzeitbetriebssystem eines nicht sehr bekannten Unternehmens in der Welt (dies ist nicht Microsoft) in der Sprache des wahrscheinlichen Gegners zu studieren, und warten auf Ihre Patches und Updates. 5. Beim Programmieren kletterten Sie nirgendwo hin, insbesondere für „Beginnen, dann tun, während der Schalter endet“, aber betrachten Sie die Wörter Lambda-Funktion und Korutin als missbräuchliches Latein.



    6. Sie sind tatsächlich zu Ihrem bereits einwandfrei funktionierenden Gerät, aber im Einklang mit den Trends der neuen Zeit benötigen Sie lediglich eine drahtlose Brücke zur Identifikation, Programmierung und zum Datenaustausch.

    Nun, verwenden Sie für diesen ESP8266. Wie eine drahtlose Brücke. Sie verwenden den AVR als Port Extender für ESP. Und wir werden das Gegenteil tun!



    Bitte nehmen Sie meine letzten Aussagen nicht zu ernst. In der Tat ist das nur ein Scherz. Jeder ausreichend erfahrene Entwickler trifft seine Auswahl auf der Grundlage vieler Faktoren wie Geschwindigkeits- und Stromverbrauchsparameter, Lebensdauer der Geräte, Kontinuität mit den bisherigen Entwicklungen, den Kosten des Produkts selbst und den Kosten für die Umstellung auf eine neue Plattform, Zuverlässigkeit, Zeitaufwand für das Erlernen neuer Architekturen, SDK, Betriebssysteme, die Anwesenheit von Mitarbeitern mit einer solchen Erfahrung in einem gemeinsamen Projekt und so weiter.

    Deshalb ist es besser, wenn:



    Ich würde mich freuen, wenn Ihnen der Artikel gefallen würde. Ich zitiere kein Literaturverzeichnis, es ist dasselbe wie im vorigen Artikel.

    PS

    Und schließlich zu den Signalen aus dem Weltraum. Das ganze Geheimnis ist, dass das ESP-Modul mit der NodeMCU-Firmware gerne alle Informationen an die Konsole sendet. Zum Beispiel nach einem Notfall-Neustart (und manchmal passiert ESP, glauben Sie mir, die Glukose ist immer noch gleich). Oder wenn Sie beispielsweise vergessen haben, print ("etwas dort") nach dem Debugging aus dem Lua-Programm selbst zu entfernen. Oder wenn Sie die veraltete (veraltete) API erhalten (Sie haben die Firmware geändert und müssen nun die neue Schreibweise verwenden, z. B. beim Starten des UDP-Servers), und ESP wird Sie jetzt immer daran erinnern. Schreiben Sie den Code noch nicht neu.

    Und das Problem ist, dass dies alles ordentlich und methodisch an die Konsole gesendet wird, dh an den UART-Port. Nun, was ist, wenn Ihr UART-Port zu diesem Zeitpunkt auf einen Befehl oder Daten wartet, um Ihrem Einkaufswagen mitzuteilen, dass er fortfahren soll?Dann kann Ihr Einkaufswagen vom Tisch fallen.
    Daher ist dieser Moment auch eine Überlegung wert.

    Jetzt auch beliebt: