Как подключить к Arduino эхолот Humminbird?

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем Bif+, 12 фев 2019.

  1. Bif+

    Bif+ Гик

    Да, но протокол что у NEO 6M V2 и эхолота один - nmea 0183.
     
  2. tpolimer

    tpolimer Нерд

    Бегло изучал протокол, просто прочел, что к примеру у Garmin есть свои дополнительные строки - https://ru.wikipedia.org/wiki/NMEA_0183.

    У данного эхолота есть специальный кабель, аналогичный этому - https://humminbird.johnsonoutdoors....3.1849103999.1549994535-1685064724.1549994535
     
  3. tpolimer

    tpolimer Нерд

    Вот нормального описания на данный эхолот не нашел.

    Если там используется аналогичный кабель, то и RS-422 там не к чему. Можно просто подключиться по RS-232. Главное не ошибиться с уровнями, чтобы ни чего не спалить.
     
  4. Только я вам писал про rs422-адаптер, а не про протокол.
     
  5. parovoZZ

    parovoZZ Гуру

    На операционнике адаптер делается на коленке.
     
  6. tpolimer

    tpolimer Нерд

  7. Bif+

    Bif+ Гик

    Уважаемые господа!
    Искренее всем Вам спасибо за участие в обсуждении моей проблемы!
    Буду "переваривать".
     
  8. Bif+

    Bif+ Гик

    Возвращаясь к теме: Arduino - Эхолот.

    Добрый вечер, уважаемое сообщество!
    При подключении эхолота к ноутбуку через USB-TTL выводились кракозябры.
    Собрал инвертор на кт 815. Инвертированный сигнал подал на RX USB-TTLи на экране появился сигнал NMEA:
    $INDPT,3.5,0.0*41
    $INGGA,164042,5040.8852,N,00104.2094,W,2,,1.0,330.0,M,,,,*18
    $INZDA,164042,19,07,2004,-05,00*7C
    $INDPT,3.6,0.0*42
    $INRMC,164043,A,5040.8852,N,00104.2089,W,2.6,136.0,190704,3.1,W*6B
    $INGLL,5040.8848,N,00104.2083,W,164044,A*2A
    $INMTW,18.5,C*18
    $INDPT,3.7,0.0*43
    Затем собрал на MAX232CXEи 5 конденсаторах 100пф по схеме из интернета как RS232.
    С эхолота на 8 ногу, а с выхода (9нога) – на RX USB-TTL. Сигнал по китайскому DS0138 в пределах +5в и – 0,2в. Все работает, NMEA выдает.
    Мне нужна строка: $INDPT,3.5,0.0*41
    и только первые две цифры – 3.5 – глубина в реальном времени.
    Подключил 9 ногу к ArduinoMega 2560. За основу взял скетч
    https://habr.com/ru/sandbox/47751/
    (конечный автомат или Arduino с GPS),
    пытался переделать, но видно что-то не правильно делаю. Двумя словами – танец с бубнами. На монитор ничего не выводится. Прошу помощи, уважаемое сообщество.

    Код (C++):

    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(2, 3); // RX, TX

    char st = '0';
    String dpt;
    char dpt_s;
    boolean renew = false;

    void setup()
    {
    Serial.begin(4800);
    mySerial.begin(4800);
    }

    String readVal() {
    boolean rot = true;
    String buffer;
    while(rot) {
    int b = mySerial.read();

    if ( (('0' <= (char)b) && ((char)b <= '9')) || ((char)b == '.') || (('A' <= (char)b) && ((char)b <= 'Z')) ) { // считываем
    //значения,

    //содержащие цифры, буквы и точку
    buffer += (char)b;

    }
    if ( (char)b == ',' ) rot = false; // заканчиваем читать, когда встречаем запятую

    delay(10);
    }
    return buffer;
    }

    void loop()
    {
    int b = mySerial.read();
    //Serial.write(b);
    //Serial.write(st);

    switch ( st ) { // перебираем состояния
    case '0': if('$' == b) st = '1';
    break;

    case '1': if('I' == b) st = '2'; else st = '0';
    break;
    case '2': if('N' == b) st = '3'; else st = '0';
    break;
    case '3': if('D' == b) st = '4'; else st = '0';
    break;
    case '4': if('P' == b) st = '5'; else st = '0';
    break;
    case '5': if('T' == b) st = '6'; else st = '0';
    break;
    case '6': if(',' == b) { // распознали $INDPT
    dpt = readVal();
    dpt.replace('.',',');
    dpt_s = (char)readVal()[0];
    readVal();

    renew = true;
    st = '0';
    } else st = '0';
    break;

    }

    if (renew) {
    Serial.print("Dpt:"  + dpt + " " "\r\n");
    renew = false;
    }
    delay(10);

    }
     







     
    tpolimer и parovoZZ нравится это.
  9. Bif+

    Bif+ Гик

    Почему не работает код? Загружается, но не работает.
     
  10. tpolimer

    tpolimer Нерд

    Учитывая проделанную Вами работу, приятно помочь.

    И так, исхожу из того, что все подключено правильно и NMEA выдается. Требуется просто получить глубину.
    Простой, на мой взгляд код, не претендует на академичность, но рабочий.
    Код (C++):

    #define BUFFER_SIZE 15
    char serialBuffer[BUFFER_SIZE + 1];

    void setup()
    {
      // put your setup code here, to run once:
      Serial.begin(9600);
      while (!Serial)
      {
        ; // wait for serial port to connect. Needed for native USB port only
      }
    }

    void loop()
    {
      if (Serial.available() > 0)
      {
        static byte saveInBuffer = 0;
        static byte commandCorrect = 0;
        static byte finishComand = 0;
        static float lastDeep = 0;

        char lastChar = Serial.read();
        static byte indexBuffer = 0;
        switch (lastChar)
        {
          case '$':
            memset(serialBuffer, 0, sizeof(serialBuffer));
            indexBuffer = commandCorrect = finishComand = 0;

            serialBuffer[indexBuffer] =  lastChar;

            saveInBuffer = 1;
            break;
          default:
            if (commandCorrect == 1 && lastChar == ',')
            {
              finishComand = 1;
              saveInBuffer = 0;
           
              lastDeep = atof(&serialBuffer[7]);
              Serial.println(lastDeep);
            }
       
            if (indexBuffer < BUFFER_SIZE && saveInBuffer == 1)
            {
              indexBuffer = indexBuffer + 1;
              serialBuffer[indexBuffer] =  lastChar;
            }
            break;
        }

        if (indexBuffer == 6)
        {
          if (strstr(serialBuffer, "$INDPT,") > 0)
          {
            commandCorrect = 1;
          }
          else
          {
            saveInBuffer = 0;
          }
        }
      }
    }
     
    Это код, который читает Serial (Вам нужно заменить его на mySerial). Программа проверяет команду и если она $INDPT, читает глубину, после чего преобразует в float и отправляет на печать.
     
    Bif+ нравится это.
  11. tpolimer

    tpolimer Нерд

    Загружается, это значит лишь одно, нет ошибок на этапе компиляции.

    Он валится, потому что-то у Вас строка $INDPT,3.5,0.0*41
    Код рассчитан на $INDPT,3.5,0.0*41,

    О после второго вызова readVal, ждет запятую.

    Не рекомендую использовать этот код (хабор удивил) и вот почему:
    1. Нет проверки mySerial.available(), перед чтением mySerial.read(). Поэтому потребовались костыли в виде delay, так как программа выполняется быстрее, чем приходят данные.
    1.1 А когда данные закончатся, зачем снова вызывать int b = mySerial.read()?
    2. int b = mySerial.read(), почему тип int, а не char?
    В программе он работает с ним как char, да программа съела, но зачем писать такой код.
    2.1 int b = mySerial.read(), аналогично, плюс постоянно приводим к типу char.
    3. Тройной вызов readVal(), без комментариев.
    4. В readVal() используется цикл while, который ожидает запятую, а если не придет?
    5. Нет отступов.

    Но если Вас это не тревожит и Вы просто разбираетесь в коде, который не будете использовать. Тогда замените case 6, на этот
    Код (C++):
        case '6': if (',' == b) { // распознали $INDPT
            dpt = readVal();
            dpt.replace('.', ',');
            //dpt_s = (char)readVal()[0];
            //readVal();

            renew = true;
            st = '0';
          } else st = '0';
          break;
     
    Bif+ нравится это.
  12. Bif+

    Bif+ Гик

    С убогим кодом можно разбираться, но позже, сейчас нужен рабочий код.
    С предложенным Вами С++ я, кажется, поплыл. С моими изменениями работать не желает!
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(2, 3); // RX, TX
    #define BUFFER_SIZE 15
    char serialBuffer[BUFFER_SIZE + 1];


    void setup()
    {
      // put your setup code here, to run once:
      Serial.begin(4800);
      mySerial.begin(4800);
      while (!Serial)
      {
        ; // wait for serial port to connect. Needed for native USB port only
      }
    }

    void loop()
    {
      if (mySerial.available() > 0) //добавил my
      {
        static byte saveInBuffer = 0;
        static byte commandCorrect = 0;
        static byte finishComand = 0;
        static float lastDeep = 0;

        char lastChar = mySerial.read(); //добавил my
        static byte indexBuffer = 0;
        switch (lastChar)
        {
          case '$':
            memset(serialBuffer, 0, sizeof(serialBuffer));
            indexBuffer = commandCorrect = finishComand = 0;

            serialBuffer[indexBuffer] =  lastChar;

            saveInBuffer = 1;
            break;
          default:
            if (commandCorrect == 1 && lastChar == ',')
            {
              finishComand = 1;
              saveInBuffer = 0;
           
              lastDeep = atof(&serialBuffer[7]);
              Serial.println(lastDeep);
            }
       
            if (indexBuffer < BUFFER_SIZE && saveInBuffer == 1)
            {
              indexBuffer = indexBuffer + 1;
              serialBuffer[indexBuffer] =  lastChar;
            }
            break;
        }

        if (indexBuffer == 6)
        {
          if (strstr(serialBuffer, "$INDPT,") > 0)
          {
            commandCorrect = 1;
          }
          else
          {
            saveInBuffer = 0;
          }
        }
      }
    }
    Что не правильно?
     
  13. tpolimer

    tpolimer Нерд

    По коду все правильно. Вы можете заменить mySerial на Serial, открыть монитор порта и оправить строку $INDPT,3.5,0.0*41, ответ будет 3.50
    Print.jpg
    Так что смотрите, что приходит в mySerial или смотрите подключение.

    Так же добавьте после
    Код (C++):
    char lastChar = mySerial.read(); //добавил my
    строку
    Код (C++):
    mySerial.println(lastChar);
    Сможете видеть, что приходит
     
  14. tpolimer

    tpolimer Нерд

    Ой, добавить строчку
    Код (C++):
    Serial.println(lastChar);
    Чтобы выводить в монитор порта, видимо уже устал.

    Если не разберетесь, скиньте, все что будет в мониторе порта.
     
  15. Bif+

    Bif+ Гик

    Все сделал, Ардуино не возвращает посылку. Монитор порта вообще пуст.
     
    Последнее редактирование: 13 мар 2019
  16. tpolimer

    tpolimer Нерд

    Если Serial.println(lastChar) ни чего не возвращает в монитор порта, значит ни чего не приходит.

    Еще раз гляньте в мониторе порта, просто скопировать этот код, если он ничего не вернет, значит эхолот не отправляет данные в mySerial. И тут нужно смотреть соединение, настройки эхолота.
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(2, 3); // RX, TX
    #define BUFFER_SIZE 15
    char serialBuffer[BUFFER_SIZE + 1];


    void setup()
    {
      // put your setup code here, to run once:
      Serial.begin(4800);
      mySerial.begin(4800);
      while (!Serial)
      {
        ; // wait for serial port to connect. Needed for native USB port only
      }
    }

    void loop()
    {
      if (mySerial.available() > 0) //добавил my
      {
        static byte saveInBuffer = 0;
        static byte commandCorrect = 0;
        static byte finishComand = 0;
        static float lastDeep = 0;

        char lastChar = mySerial.read(); //добавил my
        Serial.print("Char - ");
        Serial.println(lastChar);
        static byte indexBuffer = 0;
        switch (lastChar)
        {
          case '$':
            memset(serialBuffer, 0, sizeof(serialBuffer));
            indexBuffer = commandCorrect = finishComand = 0;

            serialBuffer[indexBuffer] =  lastChar;

            saveInBuffer = 1;
            break;
          default:
            if (commandCorrect == 1 && lastChar == ',')
            {
              finishComand = 1;
              saveInBuffer = 0;
       
              lastDeep = atof(&serialBuffer[7]);
              Serial.print("lastDeep - ");
              Serial.println(lastDeep);
            }

            if (indexBuffer < BUFFER_SIZE && saveInBuffer == 1)
            {
              indexBuffer = indexBuffer + 1;
              serialBuffer[indexBuffer] =  lastChar;
            }
            break;
        }

        if (indexBuffer == 6)
        {
          if (strstr(serialBuffer, "$INDPT,") > 0)
          {
            commandCorrect = 1;
          }
          else
          {
            saveInBuffer = 0;
          }
        }
      }
    }
     
  17. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Извините за любопытство. Там же две пары линий - А, B на прием и А,В на передачу. Вы какие линии выбрали, А или В ? По описанию вроде линии А соответствуют полярностью 232му - протоколу (не инвертированному).
     
  18. Bif+

    Bif+ Гик

    На макетке все собрано и можно подать и снять с любой ноги, как инвертированный, так не инверт.
    На USB-TTL подаю инвертсигнал с 9 ноги - работает, если прямо с эхолота или с7 - идут кракозябры. С инвертора на кт 815 тоже работает и выводит на экран NMEA. Выход с эхолота контролирую по DS0138 .Сигнал +4,99в max и min -0,21в. С инвертора на транзисторе те же вольты, думаю, что -0,21 -это погрешность Китайца. П-образная пила идет качественная.
     
    Последнее редактирование: 13 мар 2019
  19. Bif+

    Bif+ Гик

    Скопировал, загрузил, отправил и монитора порта $INDPT,3.5,0.0*44 - ответа нет. Менял пины, проверял работоспособность пинов кнопкой и светодиодом - работают.
     
  20. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Извините я пропустил. USB -TTL - это подключать к компу по УСБ ? С 9-й ноги или 7-й - с чего ноги ? В 422м протоколе используются 0 и +5 вольт. Для RS232-TTL этому соответствуют линии В. Подключите линии В эхолота к переходнику USB -TTL. И не забудьте земли соединить.
     

    Вложения:

    • DataByte.gif
      DataByte.gif
      Размер файла:
      4,4 КБ
      Просмотров:
      298
    Последнее редактирование: 13 мар 2019