Энкодер на Arduino

Тема в разделе "Arduino & Shields", создана пользователем SnJon, 8 янв 2017.

  1. SnJon

    SnJon Нерд

    Всем доброго времени суток! Обращаюсь за помощью к знатокам, ибо собственных знаний и сил уже не хватает :)

    В общем, задача стоит следующая: необходимо имитировать замок-крутилку (типа, как на сейфе) для решения задачи открытия саркофага. Накрутили верную комбинацию - саркофаг открылся.
    Данный замок должен передавать этапы прохождения комбинации по локальной сети (три направо, два налево, один направо и т.д. Первый этап - это, например, три круга направо).
    Устроено сие чудо следующим образом: Arduino Mega 2560 + Ethernet Shield w5100 + механический энкодер (самый простой, китайский) + 2 цифровых датчика холла SS411A.
    Механический энкодер служит лишь для обновления метки времени, пока никто не крутит крутилку, этап прохождения комбинации сбрасывается.
    А два датчика холла как раз уже и решают задачу крутилки, определяют направление вращения и количество оборотов.
    Изначально был сделан прототип на жестком диске (практически такой же, как в статье, за исключением того, что стоит еще механический энкодер). Алгоритм был доработан, для исключения фальш кругов. Т.е. на прототипе все отлично работает и никаких нареканий к устройству нет.
    Теперь сама проблема: как только ставим данную систему энкодера в купе с Ethernet Shield, то стабильность работы устройства теряется. НО! (самое интересно), при подключении к Arduino по монитору порта - начинает стабильно работать.
    Подключение показано на картинке во вложении, только в реале датчики холла питаются через понижающий DC DС преобразователь 12v (c комп. БП) -> 5v.
    Arduino Mega питается через тот же компьютерный блок на вход 5v (блок выдает 5.36v).

    Код:
    Код (C++):
    #include <String.h>
    #include <SPI.h>
    #include <Ethernet.h>
    #include <Encoder.h>
    #define ENCODER_OPTIMIZE_INTERRUPTS

    uint8_t prev_state = 0;
    const uint8_t FORWARD_SEQ = 0b10000111, BACKWARD_SEQ = 0b10110100;
    uint8_t current_seq = 0;

    long          lastPosition,
                  encPosition,
                  oldencPosition;
                 
    unsigned int  llCount = 0,                          // переменные кругов влево и вправо
                  lrCount = 0;
                 
    unsigned long time_current=millis(),              // метки времени
                  enc_time = time_current;
                 
    int stage = 0;                                      // этап прохождения комбинации (всего 5 этапов)
                 
    #define ENC_PIN1      (18)
    #define ENC_PIN2      (19)


    Encoder myEnc(20, 21);

    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEA };
    IPAddress ip(192,168,0,3);
    EthernetServer server(80);


    void setup(){
      Serial.begin(9600);
      pinMode(ENC_PIN1, INPUT);
      pinMode(ENC_PIN2, INPUT);
      Ethernet.begin(mac, ip);
      server.begin();
    }


    void loop() {
      String req;
      char c;
      EthernetClient client = server.available();
      if (client) {
        boolean currentLineIsBlank = true;
        while (client.connected()) {
          if (client.available()) {                                        // начало работы клиента
            char c = client.read();
            req+=c;
            if (c == '\n' && currentLineIsBlank) {
    //          if (req.indexOf("?")>-1) Serial.println(req.substring(6,req.indexOf(" HTTP")));
                                                                           // поиск команд
           
    // -----------------------------------------------------------------------------------------
    //          Serial.println(req);                       // DEBUG: Dump HTTP data
              client.println("HTTP/1.1 200 OK");                     // заголовок
              client.println("Content-Type: application/json");
              client.println("Access-Control-Allow-Origin: *");
              client.println("Connection: close");
              client.println();
                                                           //  вывод состояния
              if(req.indexOf("showstate")>-1){
                client.print("{");
                client.print("\",\"enc\":\"");                   // крутилка на саркофаге
                client.print(stage);
                client.print("\"");
                client.println("}"); // end JSON
              }

              req="";
              break;
            }
            if (c == '\n') currentLineIsBlank = true;
             else if (c != '\r') currentLineIsBlank = false;
          }
        }
        delay(1);
        client.stop();
      }

      time_current=millis();                              // обновление метки времени

      encoder();
      service_encoder();
     
    }



    void readEncoder(uint8_t pin1, uint8_t pin2)   // сервисная функция датчиков холла
    {
      uint8_t gray_code = digitalRead(pin1) | (digitalRead(pin2) << 1);

      if (gray_code != prev_state) {
        current_seq <<= 2;
        current_seq |= gray_code;
        prev_state = gray_code;
      }
    }


    void sendError () {
         llCount = 0;
         lrCount = 0;
         stage = 0;
         Serial.println("Error!");
    }

    void nextStage () {
         llCount = 0;
         lrCount = 0;
         stage++;
         Serial.print("Next stage: ");
        Serial.println(stage);
    }

    void encoder()          //функция логической части энкодера
    {
         if (stage == 0) {
            if (lrCount == 3 && llCount == 0) {
                nextStage();
            } else if (llCount > 0) {
              sendError();
            }
         }
       
          if (stage == 1) {
            if (lrCount == 0 && llCount == 2) {
                nextStage();
            } else if (lrCount > 0) {
              sendError();
            }
         }
       
         if (stage == 2) {
            if (lrCount == 1 && llCount == 0) {
                nextStage();
            } else if (llCount > 0) {
              sendError();
            }
         }
       
         if (stage == 3) {
            if (lrCount == 0 && llCount == 2) {
                nextStage();
            } else if (lrCount > 0) {
              sendError();
            }
         }
       
         if (stage == 4) {
            if (lrCount == 2 && llCount == 0) {
                nextStage();
            } else if (llCount > 0) {
              sendError();
            }
         }
    }

    void service_encoder()
    {
         readEncoder(ENC_PIN1, ENC_PIN2);

      switch (current_seq) {
        case FORWARD_SEQ:
          Serial.print(">> ");
          Serial.println(llCount++);
          current_seq = 0;
          break;
        case BACKWARD_SEQ:
          Serial.print("<< ");
          Serial.println(lrCount++);
          current_seq = 0;
          break;
      }
       
       
       
         //для обновления времени
         encPosition  = myEnc.read();
       
         if (encPosition != oldencPosition)
         {
         enc_time = time_current;
        oldencPosition = encPosition;
         }
       

      if (stage == 0 && (time_current - enc_time > 1300)) //сброс по времени при бездействии
        {
        enc_time = time_current;
        sendError();
        }
       
      if (stage != 0 && stage != 5 && (time_current - enc_time > 30000)) // сброс через 30сек после начала прохождения комбинации при бездействии
      {
        enc_time = time_current;
        sendError();
      }
     
      if (stage == 5 && (time_current - enc_time > 3000))  // сброс после прохождения комбинации
      {
        enc_time = time_current;
        sendError();
      }
    }
     
    В чем может быть проблема?
     

    Вложения:

    • shematic.jpg
      shematic.jpg
      Размер файла:
      423,4 КБ
      Просмотров:
      782
  2. SnJon

    SnJon Нерд

    Разобрался с проблемой. Оказалось энкодеру мешает цикл общения Ethernet Shield с сетью. Из-за этого появляется задержка и алгоритм нестабильно работает. На счет Serial - ошибка в коде - Serial.println(lrCount++)
    Люди добрые, помогите дописать чтения кода Грея с прерываниями, буду очень благодарен!