Дорогие друзья, поздравяем вас с выполнением лабораторных работ! Перед вами стоит  очень интересная задача - вам нужно построить карусель.

Не будем больше ждать, поехали!

источник:https://www.tripadvisor.ru/LocationPhotoDirectLink-g298499-d6502619-i216890820-Poteshny_Dvor_Amusement_Park-Arkhangelsk_Arkhangelsk_Oblast_Northwestern.html

 

Оборудование

  1. Плата NodeMCU
  2. Шаговый двигатель 28byj-48
  3. Драйвер ULN2003
  4. Провода
  5. Основание
  6. Блок питания 5В

источник: https://www.yourduino.ru/product/shagovyy-dvigatel-28byj-48-i-modul-upravleniya-uln2003

 

Схема подключения


источник:https://blld.ru/3554-shagovye-dvigateli-i-motory-arduino-28byj-48-s-drajverom-uln2003.html


Распиновку можете увидеть в скетче. Шаговый двигатель использует питание от 5В, так как мы пользуемся платой NodeMCU, нам нужно запитать наш двигатель от внешнего источника. Между прочим, нам также нужно запитать плату NodeMCU, это можно сделать следующим образом: контакт 3В на плате подключаете к 5В внешнего источника, а контакт G подключаете к земле внешнего источника.

 

Скетч для управления двигателем "тупая карусель"


Прежде чем начать работу с платформой NodeMCU рекомендуем вам посмотреть ещё раз лабораторные работы, а именно: 
 



Внизу находится скетч.
 

#include <Stepper.h>

 const int stepsPerRevolution = 2048; 

Stepper myStepper(stepsPerRevolution, D0, D1, D2, D3);

 

void setup() {

  myStepper.setSpeed(10);

}

 

void loop() {

  myStepper.step(8);

  delay(7);

}

Описание команд:
 

Команда Описание

void setup() {}

Функция, которая выполняется только один раз, предназначена для объявления пинов 

#include <Stepper.h>

Подключение библиотеки для работы с шаговым двигателем

void loop() {}

Функция, которая выполняется много раз; цикл

 const int stepsPerRevolution = число шагов для одного оборота

Указание числа шагов для одного оборота. 

delay(время в милисекундах);

Задержка

Stepper myStepper(stepsPerRevolution, пин, пин, пин, пин);

Объявление контактов к которым подключается шаговый двигатель.  

myStepper.setSpeed(скорость);

Задаём скорость

myStepper.step(число шагов);

Задаём число шагов на которое должен повернуть шаговый двигатель нашу карусель.

 

Примечание: Все команды заканчиваются точкой с запятой, в функциях команды находятся между {}.

 

Скетч для управления с помощью приложения Alterzoom, "умная карусель"


Прежде чем начать работу предлагаю вам ознакомиться с  материалами в iframe-ах, расположенных ниже:
Также вам нужно скачать приложение Alterozoom, его вы можете скачать с официального сайта, а потом необходимо установить лицензию.
Для получения лицензии свяжитесь с нами по почте: branislava.jankovic.1998@ gmail.com


 





Скетч:
 

#include <Stepper.h>

const int stepsPerRevolution = 2048;  

Stepper myStepper(stepsPerRevolution, D0, D1, D2, D3);

#include <ARpcArduStrHlp.h>

#include <ARpcDevice.h>

#include <ARpcDeviceState.h>

#include <ARpcIDevEventsCallback.h>

#include <ARpcIMessageCallback.h>

#include <ARpcIWriteCallback.h>

#include <ARpcRealDeviceMessageDispatch.h>

#include <ARpcSrvReady.h>

#include <ARpcStarNetDevice.h>

#include <ARpcStarNetEndPoint.h>

#include <ARpcStarNetEndPointDevice.h>

#include <ARpcStarNetStreamWriter.h>

#include <ARpcStreamParser.h>

#include <ARpcStreamWriter.h>

#include <ARpcUuid.h>

#include <BearSSLHelpers.h>

#include <CertStoreBearSSL.h>

#include <ESP8266WiFi.h>

#include <ESP8266WiFiAP.h>

#include <ESP8266WiFiGeneric.h>

#include <ESP8266WiFiMulti.h>

#include <ESP8266WiFiScan.h>

#include <ESP8266WiFiSTA.h>

#include <ESP8266WiFiType.h>

#include <WiFiClient.h>

#include <WiFiClientSecure.h>

#include <WiFiClientSecureAxTLS.h>

#include <WiFiClientSecureBearSSL.h>

#include <WiFiServer.h>

#include <WiFiServerSecure.h>

#include <WiFiServerSecureAxTLS.h>

#include <WiFiServerSecureBearSSL.h>

#include <WiFiUdp.h>

#include <ESP8266HTTPClient.h>

uint16_t port=4081;

WiFiServer server(port);

WiFiClient client;

IPAddress bCastSenderIp;

WiFiUDP bCastCli;

 

bool     connecting=false;

const char* ssid="WL3";

const char* password="11111111";

unsigned long lastSyncMillis=0;

const char *deviceName="carrousel";  // naziv uredjaja

const ARpcUuid deviceId("{afa94e6e-d049-4142-83df-2dbd73ba7949}");

const char *interfaceStr="<controls>"

"<group title=\"CARROUSEL_SETTINGS\">"

  "<control title=\"CARROUSEL ON\" command=\"carrouselon\"/>"

  "<control title=\"CARROUSEL Off\" command=\"carrouseloff\"/>"

"</group>"

"</controls>";
 

class NetWriteCb

    :public ARpcIWriteCallback

{

public:

    void writeData(const char *d,unsigned long sz)override

    {

        client.write(d,sz);

    }

    void writeStr(const char *str)override

    {

        client.print(str);

    }

        void writeStr(const __FlashStringHelper *str)override

    {

        client.print(str);

    }

}netCb;

class SerialWriteCb

    :public ARpcIWriteCallback

{

public:

    void writeData(const char *d,unsigned long sz)override

    {

        Serial.write(d,sz);

    }

    void writeStr(const char *str)override

    {

        Serial.print(str);

    }

    void writeStr(const __FlashStringHelper *str)override

    {

        Serial.print(str);

    }

}serialCb;

ARpcDevice wifiDev(300,&netCb,&deviceId,deviceName);

ARpcDevice serialDev(300,&serialCb,&deviceId,deviceName);

//callback-класс для обработки команд, вызывается библиотекой ARpc

class EventsCb

    :public ARpcIDevEventsCallback

{

public:

    explicit EventsCb(ARpcDevice *d)

    {

        dev=d;

    }

   

    virtual void processCommand(const char *cmd,const char *args[],unsigned char argsCount)

    {

        byte cmdOK = 1;

        if     (strcmp(cmd,"carrouselon")   ==0) {

          for(int j=0;j<1000;++j){

              myStepper.step(8);

              delay(6);}

            wifiDev.disp().writeOk();

          }

        else if(strcmp(cmd,"carrouseloff") ==0) {

              myStepper.step(0);

            wifiDev.disp().writeOk();

          }

        else {

            wifiDev.disp().writeErr("Unknown cmd"); 

            cmdOK = 0;

          }

    }

    virtual void onSyncMsg()

    {

        lastSyncMillis=millis();

    }

  private:

    ARpcDevice *dev;

}serialEcb(&serialDev),wifiEcb(&wifiDev);

class SrcReadyCb

    :public ARpcISrvReadyCallback

{

public:

    void processSrvReadyMsg(const ARpcUuid &srvId,const char *srvName)

    {

        serialDev.disp().writeInfo("Server detected: ",bCastSenderIp.toString().c_str(),srvName);

        if(client.connected()||connecting)return;

        serialDev.disp().writeInfo("Connecting to server...");

        connecting=true;

        client.connect(bCastSenderIp,port);

        for(int i=0;i<20;++i)

        {

            if(client.connected())

                break;

            delay(100);

        }

        serialDev.disp().writeInfo("Connected to server");

        connecting=false;

        wifiDev.resetParser();

        lastSyncMillis=millis();

    }

}srvReadyCb;

 

АRpcSrvReady srvReadyParser(200,&srvReadyCb);

 

void connectWifi()

{

    WiFi.begin(ssid,password);

    while(WiFi.status()!=WL_CONNECTED)

    {

        delay(500);

        serialDev.disp().writeInfo("Wifi connecting");

    }

    serialDev.disp().writeInfo("WiFi connected");

}

void setup() {

  // pin definition

    myStepper.setSpeed(10);

  // other stuff

    delay(2000);

   

    Serial.begin(9600);

    wifiDev.disp().installDevEventsHandler(&wifiEcb);

    wifiDev.disp().setControls(interfaceStr);

    serialDev.disp().installDevEventsHandler(&serialEcb);

    serialDev.disp().setControls(interfaceStr);
 

   connectWifi();

    bCastCli.begin(port);

   

    // Start the server

    server.begin();

    serialDev.disp().writeInfo("Server started");

   

    // Print the IP address

    serialDev.disp().writeInfo(WiFi.localIP().toString().c_str());

    serialDev.resetStream();

}

void checkBCastCli()

{

    static int sz=0;

    sz=bCastCli.parsePacket();

    if(sz>0)

    {

        bCastSenderIp=bCastCli.remoteIP();

        for(int i=0;i<sz;++i)

            srvReadyParser.putByte(bCastCli.read());

    }

}

void checkWifiClient()

{

    if(client)

    {

        if(!client.connected())

        {

            serialDev.disp().writeInfo("Client connection lost");

            client=server.available();

            if(client)

            {

                serialDev.disp().writeInfo("Take next pending incoming connection");

                lastSyncMillis=millis();

                wifiDev.resetStream();

                wifiDev.resetParser();

            }

            delay(100);

        }

        else

        {

            while(client.available())

                wifiDev.putByte(client.read());

        }

    }

    else

    {

        client=server.available();

        if(client)

        {

            serialDev.disp().writeInfo("Take next pending incoming connection");

            lastSyncMillis=millis();

            wifiDev.resetStream();

            wifiDev.resetParser();

        }

        delay(100);

    }

}

void loop() {

    while(Serial.available())

        serialDev.putByte(Serial.read());

    if(WiFi.status()!=WL_CONNECTED)

        connectWifi();

    checkBCastCli();

    checkWifiClient();

    if(((millis()-lastSyncMillis)>12000)&&client.connected())

    {

        client.stop();

        checkWifiClient();

    }

    delay(50);

}

 

Замечание: Красными буквами написана основная часть программы, зелёными написано то, что можно менять. 

 

Команда Описание

#include <название библиотеки>

Команда с помощью которой подключаем библотеку
const char* ssid="название сети к которой подключён локальный сервер"; Определяем сеть к которой будет подключатся наше IoT устройство
const char* password="пароль сети"; Указиваем пароль сети
const char *deviceName="название IoT устройства";  Указиваем название нашего устройства
const ARpcUuid deviceId("{Id  нашего устройства}"); Указиваем ID нашего устройства

const char *interfaceStr="<controls>"

"<group title=\"название настроек\">"

  "<control title=\"название команды, которое будет видно из проложения Alterozoom после нажатия на кнопку Control device \" command=\"команда\"/>"

"</group>"

"</controls>";

Определение названия команд 

if(strcmp(cmd,"команда") ==0) {

        чась программы, которая выполняется после нажатия кнопки с названием нашей команды из приложения

            wifiDev.disp().writeOk();

          }

Определяем, что должно произойти после нажатия кнопки, если команда существует и она перечислена в разделе controls, мы получим сообщение от парсера, что всё хорошо и что он команду узнал. 

wifiDev.disp().writeErr("Unknown cmd"); 

Сообщение, которое получим когда укажем команду, которая не указана в разделе controls

 

Замечание: Остальные команды либо перечислены сверху, либо соответствуют подключению к серверу и WiFi или передаче информации парсеру.  

 

/messages/6018