Raspberry PI 3 + OpenCV + Arduino UNO + ......(поледнее решение и вопрос в последнем сообщении)

Тема в разделе "Флудилка", создана пользователем Igor68, 21 ноя 2016.

  1. Igor68

    Igor68 Гуру

    Я имел ввиду ASSEBLER.
     
  2. Alex19

    Alex19 Гуру

    Да, не разобрался, в начале подумал речь о Си:).
     
  3. Igor68

    Igor68 Гуру

    Может посоветуете малогабаритный дальномер... сонар или инфракрасный с получением параметра по I2C. Смотрел... в основном все с дискретным импульсом разной длительности или с заполнением пакета импульсов. Да и не такие маленькие. Надо поставить рядом с камерой на поворотно-наклонном устройстве.
    Да и платформа с моторами, но без энкодеров. Проблема ориентации.
    Спасибо!

    Вот эта игрушка может кому пригодиться для рассмотрения (тестовая программа):
    qtarpi.zip
     

    Вложения:

    • qtarpi.zip
      Размер файла:
      65,6 КБ
      Просмотров:
      421
    Последнее редактирование: 9 дек 2016
    Alex19 нравится это.
  4. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Про датчик (дальномер) от Amperka:
    Повышенная точность ни к чему... но вот дистанция требуется около 2 м. Минимальное около 0.1...0.2 м. Интерфейс I2C.
    Помогите с выбором!
    Заранее Спасибо!
     
  5. Igor68

    Igor68 Гуру

    Доврого времени суток!!!

    Вот первые опыты с выделением фрагмента картинки с веб-камеры кликом мышки на рабочем окне (изображении, принимаемом от camserver). После клика сместил камеру и фиксация не меняется. Красный это "слой" с камеры, а остальное "слой" индикации:
    snapshot13.png

    При клике на другом фрагменте - будет выделен другой:
    snapshot14.png
    Пока что OpenCV применяется только в camserver на малине для преобразования картинки с камеры в черно-белое изображение. Основные операции на ПК в программе теста. Собственно в ней сейчас и все эксперименты:
    qtarpi.zip

    Текущая задача - поворачивать и наклонять камеру по выделенному фрагменту, таким образом, что-бы этот фрагмент был в центре изображения... точнее в неком "регионе"... или центральной зоне экрана. В случае достижения "ограничения" камеры по горизонтали производить разворот платформы.......

    Так же беспокоит ранее поднятый вопрос про датчик-дальномер. В перспективе метод построения "карты" неизвестного пространства.
    Заранее спасибо!
    С глубоким уважением!
     

    Вложения:

    • qtarpi.zip
      Размер файла:
      110 КБ
      Просмотров:
      425
    Последнее редактирование: 12 дек 2016
    Alex19 нравится это.
  6. Igor68

    Igor68 Гуру

    Приветствую! Доброго времени суток!
    Пока ничего не меняю со стороны управления. Вопрос по дальномеру.
    Будь Arduino конечным устройством наверное можно больше... но от неё ещё I2C устройства.
    Может требуемого датчика и в природе нет... может схему от какого-нибудь большого... разведу и закажу плату. Масса очень важна... да и размер тоже. Надо разместить тут:
    20161212_213229.jpg
    При подъёме около 30 градусов дёргается... понимаю надо машину мощнее, да и в цепи ОС серво-машины должно быть изменено (увеличено) время интегрирования. Но что имею... то имею.

    Спасибо!
     
  7. Alex19

    Alex19 Гуру

    День добрый.
    Сегодня была минутка поковыряться со своим кодом, нашел в ModbusRtuSlave.cpp мелкий недочет, там к unt8_t конвертируется в int8_t, поэтому при больших объемах получаем ошибку, он возвращает отрицательные значения. На работу не влияет, но просто некрасиво, особенно когда в коде стоит такая проверка.
    Код (C++):
    // Проверяем, поступил ли запрос и если поступил даем ответ.
      int16_t modbusError = modbusSlave.poll(modbusData, MODBUS_DATA_COUNT);
      if (modbusError < 7
        && modbusError != 0)
      {
        DEBUG_PRINTLN(modbusError);
      }  
    Есть и на I2C, но с такими не работал.
    К примеру, подходящий Вам SRF02 (по габаритом, нужно смотреть), есть компания http://www.maxbotix.com/index.htm, она выпускает с 10-ток различных моделей, но и цены кусаются. Посмотрите, может что-то подойдет.
     

    Вложения:

    Igor68 нравится это.
  8. Alex19

    Alex19 Гуру

    Тут бы не плохо смотрелся IMU, но все ни как не могу найти время с ним разобраться.

    Если важна масса и размер, присмотритесь к I2CXL-MaxSonar-EZ4 или MB1242 их ставят на самолеты, квадрокоптеры в проекте Ardupilot. Наверно это самые доступные, с учетом характеристик.

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

    UPD. Хотя по поводу IMU погорячился, есть энкодеры, специально для машинок. К примеру такие
    [​IMG]
     
    Последнее редактирование: 12 дек 2016
    Igor68 нравится это.
  9. Igor68

    Igor68 Гуру

    Вот выбрал типы
    MB1202, MB1212, MB1222, MB1232, MB1242
    из указанных буду искать... удаление от железки рядом с камерой до 10 мм - хорошо, что закупил пластиковые стойки... да и первая малина (тип B) есть, из которой сделал... ну на вроде программатора. Ведь надо указать адрес! Там по умолчанию:
    224 dec (default) 11100000 bin 0xE0 hex... то есть адресация 8 бит! Надо покурить даташит!
    Спасибо!
    С аналоговым выходом тоже интересно... но если выход постоянный, а измерения непрерывны... правда в конструкции 4 шима (не считая Multisrtdo)... а монтаж?

    Спасибо!!!
     
  10. Alex19

    Alex19 Гуру

    Там стандартная адресация - http://www.maxbotix.com/documents/I2CXL-MaxSonar-EZ_Datasheet.pdf, на 2 странице 7 битный адрес + 1 бит R\W. Но интересно, что адрес I2C можно менять.

    Тут не понял Вас.
    А так есть и с аналоговыми, видел и на UART.
     
    Igor68 нравится это.
  11. Igor68

    Igor68 Гуру

    Некачественный шим... Multiservo(Amperka)... по ходу "рычаг длинный" (хоть и брал для камеры... меньше размером камеру не нашел). Дёргается только вверх, но если плавно менять задание, то всё нормально! Вибрация приводит к дёрганью - мощности конечно мало, но S3003 в комплекте для сборки. И ещё время ОС по "внутреннему" измерительному резистору. Резистора коррекции нуля нет! Вполне возможно, что скачки по питанию - едины для ComMotion и Multiservo. Цепи питания контроллеров пока по нормальному не развязал - питаются от USB-SERIAL от Raspberry, который питается от зарядки "SAMSUNG Galaxy TAB10.1" - на HDD-USB хватает. В принципе пока что-нибудь не "перережу" для гарантированного раздела питания будет какой-нибудь бардак! Да и Multiservo могли бы полигоном "залить" цепи подачи напряжения и GND... Жалко что ли? А то сервы целых 12 на одной линии.
     
    Alex19 нравится это.
  12. Igor68

    Igor68 Гуру

    Скачал уже! Курю! Про адресацию видел! Только в таблице 224 по умолчанию!
    Имел ввиду, если преобразование не запускать а он постоянно выдаёт последнее измерение!
     
  13. Alex19

    Alex19 Гуру

    А да, забыл:), у Вас Multiservo. Там сделано все хорошо.

    Адрес 112, но данный адрес можно изменить. R\W это уже команда, запись, чтение, поэтому и получается 224 и 225. Там по I2C всего 3 команды, все хорошо расписано.

    Если будете использовать стандартную библиотеку, то можете взять уже готовую библиотеку - https://github.com/simondlevy/MB1242_Arduino/tree/master/MB1242.
     
    Igor68 нравится это.
  14. Igor68

    Igor68 Гуру

    Спасибо большое!... я это уже прочитал. Там всё понятно! Осталось только приобрести. Конфигурировать практически есть чем!
    Спасибо! И по этому вопросу то же! Большое спасибо!
     
  15. Alex19

    Alex19 Гуру

    Не за что, удачи в проекте!
     
  16. Igor68

    Igor68 Гуру

    Доброго времени суток!!!
    Решил применять гистограммы по горизонтали и вертикали. Сплошная гистограмма - реального времени с выбранными координатами центра квадрата 320х240, размер которого 150х150. Размер получаемой картинки 640х480, т.е. наш маркер для динамики в центре экрана. Штриховая гистограмма - соответствует тоже такому же квадрату но с центром выбранным кликом мышки. Разворачивая камеру по горизонтали и вертикали с помощью "ползунков" очень... ну очень не быстро :mad: почти совместил гистограммы в ручную. Точность перемещения... да..:(!
    По ходу в механике... идёт... идёт.. потом скачок и перелетели далеко. ну что же опыты они и есть опыты. Верхние гистограмма определение по горизонтали в этом квадрате, а нижняя соответственно по вертикали. Числовые значения - максимальные значения на гистограмме (масштабируются).
    snapshot15.png

    Соответственно при клике на картинке реального времени фиксируется новая гистограмма для новых координат
    snapshot16.png
    Похоже придется делать "автопоиск" на этой картинке... чтобы обойти механические дефекты.
    Та же но только изменённая программа теста в QtCreator... и снова пока без применения OpenCV... пока без применения. Гистограммы не "взвешены"... и не настоящие - потому то их две!
    qtarpi.zip
    Работает с теми же серверами, запущенными на Raspberry Pi 3.
    camserver в частности:
    camserver.zip
    и скрипт запуска:
    Код (Bash):
    #!/bin/bash

    ./camserver -p 8998
    сервер управления пока без изменений:
    arbot.zip
    ну и скрипт запуска для него:

    Код (Bash):
    #!/bin/bash

    echo "...starting Arduino & Raspberry conrol"
    ./arbot -p 8971 -sp /dev/ttyUSB0
     

    Вложения:

    • qtarpi.zip
      Размер файла:
      115 КБ
      Просмотров:
      394
    • camserver.zip
      Размер файла:
      65,9 КБ
      Просмотров:
      404
    • arbot.zip
      Размер файла:
      31,9 КБ
      Просмотров:
      444
    Последнее редактирование: 18 дек 2016
    Alex19 нравится это.
  17. Igor68

    Igor68 Гуру

    Что-то не очень движется...
    Ранее строил так сказать "неправильные" две по X и Y. Поиск проводил от центра в направлении клика мыши на картинке. Сейчас Строю по "инструкции"... сразу стала нужна только одна.
    Построение (количество ячеек соответствует количеству градаций)
    Код (C++):
    //заполнение гистограммы
    void Hist(HIST * h)
    {
        U16 shx, cntx;
        U16 shy, cnty;
        //проверка и выставление границ
        if(((int)(h->startx) - _hist_size_x/2) < 0)
            h->startx += _hist_size_x/2;
        if(((int)(h->startx) + _hist_size_x/2) >= 640)
            h->startx -= _hist_size_x/2;
        if(((int)(h->starty) - _hist_size_y/2) < 0)
            h->starty += _hist_size_y/2;
        if(((int)(h->starty) + _hist_size_y/2) >= 480)
            h->starty -= _hist_size_x/2;
        shx = h->startx -_hist_size_x/2;
        shy = h->starty -_hist_size_y/2;
        //
        cntx = 0;
        while(cntx < _hist_size)
        {
            h->hist[cntx] = 0;
            cntx++;
        }
        //построение гистограммы
        cntx = 0;
        while(cntx < _hist_size_x) //значения координаты пикселя по X
        {
            cnty = 0;
            while(cnty < _hist_size_y) //значения координаты пикселя по Y
            {
                //увеличение значения ячейки для яркости пикселя wvbuf[shx + cntx][shy + cnty]
                h->hist[wvbuf[shx + cntx][shy + cnty]] += 1;
                cnty++;
            }
            cntx++;
        }
        //завершили построение
        h->work = false;
    }
     
    Одним словом как у всех... но визуально прошлый метод был нагляднее. Но этот несколько быстрее. Сравниваю по методике CV_COMP_CHISQR – хи-квадрат:
    snapshot17.png
    ну и соответственно:
    Код (C++):
    //сравнение гистограмм
    int wCompareHist(HIST * h1, HIST * h2, HISTSEARCH * hs)
    {
        int     cnt;
        float   val1, val2;
        float   err;
        //сравнение
        cnt     = 0;
        err     = 0.0f;
        while(cnt < _hist_size)
        {
            val1 = h1->hist[cnt];
            val2 = h2->hist[cnt];
            if((val1 + val2) > 0) //бывают и нулевые значения
                err += (float)(pow((double)(val1 - val2), 2) / (float)(val1 + val2));
            cnt++;
        }
        //ошибка
        hs->err = err;
        //
        return 0;
    }
     
    Тестирую на ПК без OpenCV... Собственно фиксация искомого места по клику мыши не только определяет саму гистограмму, но и регистрирует координаты клика. Соответственно от центра экрана "ползём" к этим координатам сравнивая всё на своём пути и регистрируем место совпадения, укладывающееся в параметр ошибки (по ValErr = 500 по умолчанию). Если совпадение дальше чем:
    Код (C++):
    #define _region_radius  75      //максимальное удаление от центра
     
    то изменяем положение камеры по горизонтали и вертикали... эта часть кода не доработана.
    snapshot18.png
    Ранее "сканировал" весь экран, но это долго... хоть и достаточно надёжно. Сейчас пытаюсь искать по какому-нибудь короткому пути. Собственно сложность в том, что камера повернулась и фрагмент сместился и для повторного поиска надо определять новый путь. Калибровать соответствие угла поворота местом на экране смысла нет. Нужен именно поиск. Какой метод выбрать пока не могу понять. Серым кругом на картинке показано "найденное" место, а при таком удалении от центра будет поворот камеры.
    Собственно условие нахождения:
    Код (C++):
    if(histsearch.err < histsearch.seterr)
        {
            //проверка региона
            deltax = abs(_centre_xregion - histsearch.startx);
            deltay = abs(_centre_yregion - histsearch.starty);
            radius = (float)(sqrt(pow((double)(deltax),2) + pow((double)(deltay),2)));
            if(radius < (float)_region_radius)
                histsearch.region = true;
            else
                histsearch.region = false;
            //поиск окончен
            histsearch.serch_end = true;
            //фиксация новой гистограммы послк поиска
            //hist.startx = histsearch.startx;
            //hist.starty = histsearch.starty;
            //Hist(&hist);
            return 0;
        }
     
    Может есть какие идеи?!
    Спасибо!
    С глубоким уважением!
     
    Последнее редактирование: 18 дек 2016
  18. Igor68

    Igor68 Гуру

    Решение проблемы управления... В моём случае в сервере управления приводами возникла необходимость в "плавности" управления приводами. Для сервомашин постепенное "приближение" к заданной позиции, а для моторов плавное изменение скорости до заданного значения. Причём следует отметить, что некоторые команды такие как стоп должны выполняться максимально быстро. Необходимость в плавности например текущая стопроцентная скорость вперёд резко сменяется реверсом. В моём случае (пока с плохим источником) резкие скачки напряжения по питанию... и... соответственно сбой. Конечно оптимальнее это всё сделать внутри MomMotion и Multiservo(Amperka). Лучше дополнительной командой задания по I2C... ну сделать ещё команду. Сейчас реализовал внутри сервера управления на малине:
    Код (C++):
    switch(regs[_mode_contrl])
        {
            //приращение на единицу
            case _mode_ctrl1:
                //моторы
                cnt = 0;
                while(cnt < 4)
                {
                    if((motors[cnt] < regs[_num_vol_m1 + cnt]) &&
                    (motors[cnt] < 255))
                        motors[cnt]++;
                    else if((motors[cnt] > regs[_num_vol_m1 + cnt]) &&
                    (motors[cnt] > -255))
                        motors[cnt]--;
                    cnt++;
                }
                //сервомашины
                cnt = 0;
                while(cnt < 18)
                {
                    if((servos[cnt] < regs[_num_pos_s1 + cnt]) &&
                    (servos[cnt] < 180))
                        servos[cnt]++;
                    else if((servos[cnt] > regs[_num_pos_s1 + cnt]) &&
                    (servos[cnt] > -180))
                        servos[cnt]--;
                    cnt++;
                }
                break;
            //обычная установка
            default:
                //копирование данных для реализации
                memcpy(&motors[0], &regs[_num_vol_m1], 8);    //моторы
                memcpy(&servos[0], &regs[_num_pos_s1], 36);    //сервомашины
                break;
        }
    Лучше конечно задать ещё и изменяемый шаг приращения значения. Ну это позже.
    arbot.zip
    со значением _mode_ctrl1 управление "плавное". Реализовано дополнением регистра режима:
    Код (C++):
    //режим управления
    #define _mode_contrl    0x20    //регистр режима управления
    #define _mode_ctrl1     1       //управление приближением
    Спасибо!
     

    Вложения:

    • arbot.zip
      Размер файла:
      32,5 КБ
      Просмотров:
      481
  19. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Стал добавлять команду Modbus RTU :3 (чтение значений регистров).... и столкнулся с этим в отчёте сервера управления на малине:
    Код (Bash):
    igor@debian-i:/home/ext_projects/arbot$ ./start
    ...starting Arduino & Raspberry conrol
    ---- opening tcp/ip  8971 ----
    receive ansver CMD16 error! ...dev: 1  addr: 48
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 48 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 64 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 64 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 48 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 48 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 64 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 64 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 48 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 48 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 64 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 64 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 48 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 48 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 64 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 64 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 48 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 48 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 64 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 64 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 48 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 48 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 64 sendCMD: 10 recvCMD: 03
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 64 sendCMD: 03 recvCMD: 10
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 48 sendCMD: 10 recvCMD: 03
     
    то есть мы получаем ответ от предыдущей команды. Опрос производится по циклу в потоке main на малине:
    Код (C++):
    ........
    switch(num_work)
        {
            case 0:    //задание для 4-х моторов
                res = MRTU_CMD_16(1, _num_vol_m1, (U16*)(&wmotors[0]), 4);
                num_work++;
                break;
            case 1:    //чтение значения 4-х моторов
                res = MRTU_CMD_3(1, _num_vol_m1, (U16*)(&rmotors[0]), 4);
                num_work++;
                break;
            case 2:    //управление положением камеры - два сервопривода
                res = MRTU_CMD_16(1, _num_pos_s1, (U16*)(&wservos[0]), 2);
                num_work++;
                break;
            case 3:    //чтение положения камеры - два сервопривода
                res = MRTU_CMD_3(1, _num_pos_s1, (U16*)(&rservos[0]), 2);
                num_work = 0;
                break;
            default:
                num_work = 0;
                break;
        }
    ...............
    Одним словом сначала передаём параметры для моторов по команде 16(10hex), после чего читаем значения для моторов по команде 3 и так далее для всех приводов. Следует заметить, что управление происходит нормально... т.е. то что малина передаёт ардуине и далее приводам по I2C всё соответствует. Ранее не применял чтение.
    Причём испытывал разные параметры, указанные в скрипте test (вот последние тесты):
    Код (Bash):
    #!/bin/bash

    echo "...starting Arduino & Raspberry conrol"
    ./arbot -p 8971 -sp /dev/ttyUSB0 19200 4 -wd 250
    для пояснения запуска сервера контроля:
    Код (Bash):
    igor@debian-i:/home/ext_projects/arbot$ ./arbot

    Parametrs not defined!
    "--help" for information
    igor@debian-i:/home/ext_projects/arbot$ ./arbot --help


    ======== Arduino Raspberry Bot control devices server =======
    arbot <parameters> :

        --help                      - current info

        -p <port>                   - tcp port for listen
                                      <port> number tcp port
        -sp <port> <speed> <stout>  - name and speed of serial port
                                      <port> serial port(use recommended /dev/ttyUSB0)
                                      <speed> speed for serial port (use recommended baudrate 9600)
                                      <stout> wait of byrs for sendded and reseived
        -wd <waint>                 - wait for device mS (wait loop serial)

    igor@debian-i:/home/ext_projects/arbot$
     
    и разное ожидание байтов и разная периодичность цикла.
    Собственно для ардуины:
    r1_uno_plus.zip

    Проверка соответствия команд по буферу передачи в ардуино и приёма из неё малиной. Тут мы игнорируем результат самой команды, а только соответствия ей (на примере 3):
    Код (C++):
    if(txbuf[1] != (rxbuf[1] & 0x7F))
        {
            #if(_mdbg == 1)
                    printf("receive ansver CMD3 no main CMD! ...dev: %i  addr: %i sendCMD: %02X recvCMD: %02X\n",
                    Dev, Addr, txbuf[1], (rxbuf[1] & 0x7F));
            #endif
            return _rx_cmd_err;
        }
    Сервер для малины:
    r1_uno_plus.zip

    Радикально и много что изменил. Понимаю что туплю! Но где? И интервал менял и ожидание...
    Заранее Спасибо!
     

    Вложения:

    • r1_uno_plus.zip
      Размер файла:
      21,6 КБ
      Просмотров:
      411
    • arbot.zip
      Размер файла:
      38,2 КБ
      Просмотров:
      246
    Последнее редактирование: 21 дек 2016
  20. Igor68

    Igor68 Гуру

    Сразу вопрос: может я получаю эхо-пакет... по причине того, что использую тот же порт (USB-SERIAL), по которому собственно и программирую?

    Вот влепил для проверки(arbot):
    Код (C++):
    /проверяем совпадение команд исключая ошибки их выполнения
        if(txbuf[1] != (rxbuf[1] & 0x7F))
        {
            #if(_mdbg == 1)
                    printf("receive ansver CMD3 no main CMD! ...dev: %i  addr: %i sendCMD: %02X recvCMD: %02X\n",
                    Dev, Addr, txbuf[1], (rxbuf[1] & 0x7F));
                MRTU_TestRxTx(&txbuf[0], 8, &rxbuf[0], rcount);
            #endif
            return _rx_cmd_err;
        }
     
    Аналогично поступил и с командой 16. Собственно добавленная функция для вывода содержимого переданного и принятого пакетов(arbot):
    Код (C++):
    void MRTU_TestRxTx(U8 * sd, int sl, U8 * rd, int rl)
    {
        int    cnt;
        cnt    = 0;
        printf("send bytes: ");
        while(cnt < sl)
        {
            printf("%02X ", *(sd + cnt));
            cnt++;
        }
        cnt    = 0;
        printf("\nrecv bytes: ");
        while(cnt < rl)
        {
            printf("%02X ", *(rd + cnt));
            cnt++;
        }
        printf("\n");
    }
     
    Ну и вот:
    Посылаем значения для колёс по команде 16, получаем значения серврмашин (консольный отчёт arbot):
    Код (Bash):
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 48 sendCMD: 10 recvCMD: 03
    send bytes: 01 10 00 30 00 04 08 00 00 00 00 00 00 00 00 3A F6
    recv bytes: 01 03 04 00 00 00 00 33 FA
    Посылаем команду 3 для чтения значений колёс, получаем ответ на исполнение значений колёс(консольный отчёт arbot):
    Код (Bash):
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 48 sendCMD: 03 recvCMD: 10
    send bytes: 01 03 00 30 00 04 06 44
    recv bytes: 01 10 00 30 00 04 C5 C1
    Посылаем значения для серврмашин по команде 16, получаем прочитанные значения колёс(консольный отчёт arbot):
    Код (Bash):
    receive ansver CMD16 no main CMD! ...dev: 1  addr: 64 sendCMD: 10 recvCMD: 03
    send bytes: 01 10 00 40 00 02 04 00 00 00 00 9F F7
    recv bytes: 01 03 08 00 00 00 00 00 00 00 00 D7 95
    Посылаем команду 3 для чтения значений сервомашин, получаем ответ на исполнение значений серврмашин(консольный отчёт arbot):
    Код (C++):
    receive ansver CMD3 no main CMD! ...dev: 1  addr: 64 sendCMD: 03 recvCMD: 10
    send bytes: 01 03 00 40 00 02 DF C5
    recv bytes: 01 10 00 40 00 02 1C 40
    И так по кругу.
    В принципе можно и фильтровать ответы но команда 3 не отсылает в ответе ни стартовый адрес регистра ни их количества, а только количество байт данных и сами данные.

    С управлением в ступоре! Где косяк? Вот пока обхожу этот косяк по тупому... но всё равно это не то(arbot)!
    Код (C++):
    switch(num_work)
        {
            case 0:    //задание для 4-х моторов
                res = MRTU_CMD_16(1, _num_vol_m1, (U16*)(&wmotors[0]), 4);
                if(res == _rx_cmd_err) //не наша команда
                    break;
                num_work++;
                break;
            case 1:    //чтение значения 4-х моторов
                res = MRTU_CMD_3(1, _num_vol_m1, (U16*)(&rmotors[0]), 4);
                if(res == _rx_cmd_err) //не наша команда
                    break;
                num_work++;
                break;
            case 2:    //управление положением камеры - два сервопривода
                res = MRTU_CMD_16(1, _num_pos_s1, (U16*)(&wservos[0]), 2);
                if(res == _rx_cmd_err) //не наша команда
                    break;
                num_work++;
                break;
            case 3:    //чтение положения камеры - два сервопривода
                res = MRTU_CMD_3(1, _num_pos_s1, (U16*)(&rservos[0]), 2);
                if(res == _rx_cmd_err) //не наша команда
                    break;
                num_work = 0;
                break;
            default:
                num_work = 0;
                break;
        }
    Для связи применял порт Arduino UNO plus USB-SERIAL. В общем смысл состоит в том, что в другое время можно сразу применить для заливки Arduino IDE. Обработка запроса в шилде (при опытах уже намусорил) (r1_uno_plus/ModbusRTU.cpp):
    Код (C++):
    /*
    ****************************
    приём команды и обработка
    ****************************
    */

    int8_t  MRTU_rWORK(void)
    {
        int8_t rcvsz = Serial.available();    //принятый размер
        //нет пакета для обработки
        if(rcvsz < 8)
        {
            Serial.flush();
            return 0;
        }
        memset((&dmrtu.rxbuf[0]), 0, _szbuf);
        wcnt = Serial.readBytes((char*)(&dmrtu.rxbuf[0]), _szbuf);
        //не наш адрес
          if(dmrtu.rxbuf[_ADDR_MADDR] != _MRTU_Addr)
            return 0;
        //определение команд
        switch(dmrtu.rxbuf[_ADDR_MCMD])
        {
            case 3:
                MRTU_CMD3();
                break;
            case 6:
                MRTU_CMD6();
                break;
            case 16:
                MRTU_CMD16();
                break;
            default:
                MRTU_CMDunknown();
                break;
        }
        Serial.flush();
        Serial.flush();
        Serial.flush();
        return 0;
    }

    С глубоким уважением!
     
    Последнее редактирование: 21 дек 2016