Библиотека Serial27b для радиомоделизма и не только

Тема в разделе "Глядите, что я сделал", создана пользователем issaom, 27 авг 2019.

Метки:
  1. issaom

    issaom Гуру

    Библиотека для Arduino, позволяющая организовать связь 2-х плат Ардуино через аппаратный последовательный порт (UART).

    Функции:
    1. Автоматический обмен данными с использованием механизма прерываний.
    2. Флаг наличия/отсутствия связи (встроенный светодиод L, pin13)
    3. Обмен данными производится с добавлением контрольного числа
    4. Сборка кода библиотеки может выполняться под любой аппаратный UART на плате Ардуино
    5. Автоматическая оптимизация трафика между платами

    Приемник и передатчик содержат 2 однобайтовых массива данных transm_arr[27]; и receiv_arr[27];
    В эти массивы пользователь может вносить свои данные.

    Настройка и использование передатчика:
    После выполнения на передатчике функции transmStart (9600, 200); передатчик будет отсылать на приемник
    массив transm_arr и ждать от него в ответ массив receiv_arr[27];
    Если ответ в течении следующих 200мс не пришел – это будет считаться потерей связи –
    при этом погаснет встроенный на плате Ардуино светодиод L.

    Настройка и использование приемника:
    После выполнения на приемнике функции receivStart (9600, 400);
    приемник будет ждать от передатчика массив transm_arr[27]; в течении 400мс.
    и отправлять в ответ массив receiv_arr[27];
    Если в течении 400мс данных от передатчика не поступит новый пакет данных это будет считаться
    потерей связи – при этом погаснет встроенный на плате Ардуино светодиод L.

    Время ожидания (мс) на приемнике в функции receivStart (9600, ХХХ); должно быть выставлено
    в 2 раза больше чем в функции transmStart (9600, YYY) – иначе возможны ложные срабатывания о потере связи.

    Опрашивая состояние светодиода L на плате Arduino в основном цикле loop можно обрабатывать
    событие "потеря связи".

    Пример использования:
    Схема подключения:
    HC12.vsd.jpg
    Алгоритм работы:
    С помощью трех потенциометров на передатчике производится управление яркостью 3 светодиодов на приемнике.
    При нажатии на кнопку загорается светодиод на Передатчике.
    В случае обрыва связи красный светодиод на плате приемника гаснет.
    Код:
    Код (C++):
    // Выбор аппапатного порта UART (расскомментируйте один из этих вариантов)
    #define Serial_0
    // #define Serial_1
    // #define Serial_2
    // #define Serial_3

    byte transm_arr[27];  // Массив который отправляется на приемник
    byte receiv_arr[27];  // Массив который приходит с приемника

    // Подключаем библиотеку ПЕРЕДАТЧИКА
    // Встроеный светодиод L светится при наличие связи
    #include <Serial27bTransmitter.h>

    void setup() {
      // скорость соединения, интервал посылок приемнику(мс)
      startTransmitter(9600, 200);
      // пин к которому подключен желтый светодиод
      pinMode(2, OUTPUT);
    }

    void loop() {

      // Читаем значения с аналоговых входов к которому подключены потенциометры
      // Преобразовываем значения в диапазон 0....255 и записываем в массив передатчика
      transm_arr[0] = map(analogRead(A0), 0, 1023, 0, 255); //потенциометр красного светодиода
      transm_arr[1] = map(analogRead(A1), 0, 1023, 0, 255); //потенциометр зеленого светодиода
      transm_arr[2] = map(analogRead(A2), 0, 1023, 0, 255); //потенциометр синего светодиода

      // Читаем значение из массива приемника и если там нажали кнопку - светодиод загорается
      if (receiv_arr[0] == 1) digitalWrite(2, HIGH); else digitalWrite(2, LOW);

      if (digitalRead(13) == LOW) {
        // Здесь можно вставить код который будет что-то делать если связь пропадет
      }

    }
    Код приемника:
    Код (C++):
    // Выбор аппапатного порта UART (расскомментируйте один из этих вариантов)
    #define Serial_0
    // #define Serial_1
    // #define Serial_2
    // #define Serial_3

    byte transm_arr[27];  // Массив который приходит с передатчика
    byte receiv_arr[27];  // Массив который отправляется передатчику

    // Подключаем библиотеку ПРИЕМНИКА
    // Встроеный светодиод L светится при наличие связи
    #include <Serial27bReceiver.h>

    void setup() {
      //  скорость соединения, максимальное время ожидания данных от передатчика(мс)
      startReceiver(9600, 300);
      pinMode(5, OUTPUT);         // пин к которому подключен красный светодиод
      pinMode(10, OUTPUT);        // пин к которому подключен зеленый светодиод
      pinMode(11, OUTPUT);        // пин к которому подключен синий светодиод
      pinMode(2, INPUT_PULLUP);   // пин к которому подключена кнопка
    }

    void loop() {

      // Читаем из массива transm_arr данные которые получены с передатчика
      analogWrite(5,  transm_arr[0]); // управляем яркостью красного светодиода
      analogWrite(10, transm_arr[1]); // управляем яркостью зеленого светодиода
      analogWrite(11, transm_arr[2]); // управляем яркостью синего светодиода

      // Сообщаем передатчику что на приемнике нажали кнопку
      if (digitalRead(2) == LOW) receiv_arr[0] = 1; else receiv_arr[0] = 0;

      if (digitalRead(13) == LOW) {
        // если пропала связь - гасим красный светодиод
        transm_arr[0] = 0;
      }

    }
    Сама библиотека:
     

    Вложения:

    • Serial27b.zip
      Размер файла:
      11,9 КБ
      Просмотров:
      293
    Последнее редактирование: 30 авг 2019
    lepidot, b707, ИгорьК и ещё 1-му нравится это.
  2. b707

    b707 Гуру

    issaom - пара замечаний, с Вашего разрешения.

    Вы используете в коде библиотеки явно заданные константы для работы с пинами. для задания бодрейта и тд. Это делает библиотеку очень негибкой. На данный момент этот код, похоже, рассчитан только на Уно-Нано с МК Атмега328 с частотой 16 МГц. Например, на Меге оно уже не заработает, как описано - потому что Вы жестко забили в коде адрес светодиода как PB5, а на меге он на другом пине. Или с частотой ядра - в коде опять же, явно забита константа 16000000 - и значит при тактировании не 16 МГц все сдохнет.
    Не сочтите за занудство - но такой код надо оформлять в виде условной компиляции под разные типы МК, вместо голых чисел для частоты использовать макрос F_CPU - и в описании четко указывать, под какими контроллерами и при каких частотах это все работает. А то новички быстро потащат это на Атмегу32 или на Аттини :) - и закидают вас претензиями
     
    Daniil, parovoZZ, ДеКодер и 3 другим нравится это.
  3. parovoZZ

    parovoZZ Гуру

    на восемьсот семнадцатую.
     
  4. issaom

    issaom Гуру

    Замечания только приветствуются! Спасибо! - мне пока не понятно вообще нужна ли-эта шляпа кому-то кроме меня и тестировал пока только на платах с Атмега328P и Атмега328PB - до Меги и Леонарды еще не дошел.Это так сказать первая версия для теста самой функциональности - ну и проверка не поломается ли что при использовании других библиотек - ведь главная задача чтобы эта штука работала из под среды Arduino IDE.
    PWM например удалось сохранить на всех пинах....
     
  5. Daniil

    Daniil Гуру

    Тоже хочу немного высказаться. Не обращайте внимание, если покажется, что придираюсь)
    А почему только 27 байт в массивах прм/прд? А если мне не нужно передавать каждый раз 27 байт (сейчас 7 байт, завтра 13)? Мне кажется удобным протоколом является modbus ascii. Где есть работа по запросу.
    Вообще, нужно ли выжидать 400 мс для определения, что связь оборвалась? Есть и другие варианты ошибок.
    А когда начинается передача? В коде вы засовываете в массив данные, но явного запуска передачи нет. КС считается для каждого байта массива отдельно?
    Библиотека организует передачу данных между ардуинками, но в примере используются радио-прм/прд. Что будет если соединить напрямую и дождаться момента когда две ардуинки будут "говорить" одновременно?
    А числа с зпт тут не передаём?
     
    b707 и issaom нравится это.
  6. issaom

    issaom Гуру

    Это например какие?
    Про работу библиотеки у меня есть видео - там подробно разбирается алгоритм её работы.



    И работает она несколько сложнее.
    27 байт это максимальный объем посылки. Если вы присвоите значения только 2-м первым элементам массива то передаваться будут только они. (пакет режется автоматически до последнего элемента массива не равному нулю). Передача туда-сюда осуществляется по таймеру в процедуре прерывания - если управляете чем-то быстродвижущимся или летящим это актуально - связь и реакция на нее должны быть насколько-это возможно быстрыми причем не важно давят стой стороны на кнопки или нет.
    Говорит тут только передатчик - приемник уму только отвечает и пока он ждет ответ - молчит. Так что одновременно говорить они не будут никогда. Если вы про "соединить напрямую" имеете ввиду провода - то библиотека именно на проводах писалась и отлаживалась. ))) Про числа с зпт не понял совсем - тип float в Arduino занимает 4 байта. Переписываете эти 4 байта в массив, а на другой стороне достаете и снова собираете из них число. КС это просто сумма всех элементов массива - небольшая "защита от дурака" чтобы применик и передатчик не реагировали если кто-то громко крикнет рядом на той же частоте какую нибудь бессвязную фигню. 400mc это критическое время - если связь работает стабильно никто там ничего не ждет.
     
    Daniil нравится это.
  7. parovoZZ

    parovoZZ Гуру

    Ошибка в том, что 27 нулей - это тоже информация. Не понимаю, почему ее не надо передавать?
     
  8. parovoZZ

    parovoZZ Гуру

    Именно так. Что-то другое выдумать сложно.
     
  9. parovoZZ

    parovoZZ Гуру

    Сами трансиверы уже кладут в радиопакет поле с CRC. Поэтому если кто-то гавкнет - не пройдёт на аппаратном уровне. У si4463 (hc12) есть ещё целая преамбула, поле адреса и много чего есть, что не видно за библиотекой.
     
  10. issaom

    issaom Гуру

    Если я хочу управлять одним моторчиком - какую полезную информацию будут содержать остальные 26 нулей?
     
  11. Daniil

    Daniil Гуру

    я губу раскатал) В обычный (ардуиновский) компорт 4 байта как float не пролезут. (да, да - библиотека для связи ардуин, помню
    а если 3-мя надо задать координату сверла? x,y,z = 100, 0, 15
    ограничение нулем вводит некоторую сложность, решаемую, но неудобную.
    ну так таймер и вводит, в среднем, задержку Т/2. Если бы работа была по запросу, то было бы быстрее.
    Uart и так реализован в ардуине, если к нему чего и прикручивать, то уж с протоколом.
    Слишком узкоспециализированным получилось решение, но уж если она решает задачи автора, то круто!
     
  12. parovoZZ

    parovoZZ Гуру

    Это частный случай. Остальные нули могут указывать на что угодно - хоть остановка остальных 26 моторов, индикаторов и прочее.
    Надо смотреть шире - каким признаком заканчивается строка? Нулем? Нет.
     
  13. issaom

    issaom Гуру

    Вы плохо прочитали мое последнее сообщение ;-)
    "пакет режется автоматически до последнего элемента массива не равному нулю" в вашем случае последний элемент равен 15 - значит передано будет все три байта
    [0] = 100;
    [1] = 0;
    [2] = 15;
    Если у Вас будет x,y,z = 100, 0, 0 - то передаваемый пакет обрежется до одного байта а на на приемнике будет
    [0] = 100;
    [1] = 0;
    [2] = 0;
    (его обрежет сама библиотека)
     
    Daniil нравится это.
  14. Daniil

    Daniil Гуру

    И правда! Я неправильно понял, спасибо, что поправили
     
  15. issaom

    issaom Гуру

    Накладные расходы на протоколе "modbus ascii какие" ? (сколько дополнительных байт летит для отправки например 27 байт Ваших данных) ведь их всех придется транслировать, а радиосвязь, поверьте очень не шустрая
    У меня на 27 байт пользовательских данных, размер отправляемого пакета который будет прокачиваться через радио модули составит 32 байта - чем ответит modbus? ;)
     
  16. Daniil

    Daniil Гуру

    Столько же.
    1-й байт - символ начала посылки
    2-й - адрес (устройства/переменной)
    с 3 по 29-й - данные
    с 30 по 31 - crc
    32-й - символ конца посылки.

    Другое дело, что, допустим, вам нужно изменить 27 переменных, где все они байты, то вы передадите 32 байта и будете счастливы.
    А я буду долго передавать для каждой переменной дополнительно по 5 байт, т.е. 27*6=162 байта.
    У вас получается весь набор данных меняется за раз. Я о таком не думал. Слежка сразу за всеми переменными. Но и в модбасе rtu (не аски) такое можно реализовать.
     
  17. parovoZZ

    parovoZZ Гуру

    Малейшая ошибка при передаче и весь пакет отбраковывается.
     
  18. Daniil

    Daniil Гуру

    и, кстати, прд об этом не узнает.

    Ну и напридирались жеж)
     
  19. Daniil

    Daniil Гуру

    Признаюсь, мне очень нравится работать с регистрами. Если автор получил удовольствие от сборки мозайки, то я чутка завидую)
     
  20. issaom

    issaom Гуру

    Что для какой-нибудь р/у пукалки с 2 моторами просто трендец какой необходимый функционал....
    А потом.....
    Это было про что ?