Урок 61. Аппаратная реализация интерфейса RS-485. Объединение плат Ардуино в локальную сеть RS-485.

Связь Ардуино через RS485

В уроке расскажу об аппаратной реализации интерфейса RS-485. Разработаем распределенную систему аналогичную системе из  предыдущего урока, только с использованием сети RS-485.

Предыдущий урок     Список уроков     Следующий урок

Для подключения к линии связи RS-485 применяются дифференциальные передатчики и приемники.

 

Передатчик должен формировать два противофазных сигнала.

Сигналы RS485

При этом стандарт RS-485 предъявляет к нему довольно жесткие требования:

  • высокое быстродействие;
  • работа на низкоомную и емкостную нагрузку;
  • защита от коротких замыканий;
  • отключение от линии (перевод в 3 состояние).

Дифференциальные приемники должны выделять разность между сигналами линий. И это при значительном уровне синфазных помех (-7 … +12 В) и высоком быстродействии.

Реализовать такие функции на дискретных элементах крайне сложно. Проще использовать интегральные приемопередатчики.

 

Приемопередатчики (драйверы) интерфейса RS-485.

Существует большое количество различных типов приемопередатчиков (драйверов) RS-485. Я предпочитаю использовать микросхемы ADM485, SP485, MAX485. Это однотипные микросхемы разных производителей. Функциональные возможности, параметры, назначение выводов у них совершенно одинаковые.

Драйвер RS-484 Производитель Ссылка на документация
MAX485 Maxim Integrated Products MAX481-MAX1487.pdf
ADM485 Analog Devices ADM485.pdf
SP485 Sipex SP485.pdf

Микросхемы выполнены в 8 выводном корпусе и имеют низкую цену.

По моей партнерской ссылке на момент написания статьи:

  • микросхема MAX485ESA стоит всего 8 руб;
  • микросхема MAX485SPA стоит 15 руб;
  • модуль конвертера TTL в RS-485 можно купить за 45 руб.

Купить драйверы RS485

В 8 выводном корпусе драйвера реализованы приемник и передатчик с параметрами, полностью соответствующими стандарту RS-485. Выходы передатчика и входы приемника объединены в микросхеме.

Драйверы RS485

Для преобразования интерфейса UART в RS-485 достаточно одной такой микросхемы.

Схема преобразования интерфейса UART в RS485

Если необходима гальваническая развязка, приходится использовать оптроны. Например, по этой схеме.

Схема преобразования интерфейса UART в RS485 с гальванической развязкой

Питание драйвера (+5 V INT) в этом случае должно быть гальванически развязано.

 

Объединение нескольких плат Ардуино в локальную сеть RS-485.

В качестве примера практической реализации сети RS-485 переработаем распределенную систему из урока 59 на сеть RS-485.

Новая схема локального контроллера будет выглядеть так.

Схема

Пояснять особенно нечего. Я добавил драйвер RS-485 по стандартной схеме включения.

Внешний вид

Такие же преобразования произошли со схемой центрального контроллера.

Схема

Все контроллеры подключены параллельно двухпроводной линии связи. Локальные контроллеры получают питание 5 В от центрального контроллера.

Линия у меня не длинная, скорость передачи низкая (9600 бит/сек). Поэтому в терминаторах нет необходимости. Для устранения неопределенности состояния линии при отключенных всех передатчиках к схеме центрального контроллера добавлены 3 резистора.

Схема смещения

Вся система теперь выглядит так.

Общий вид системы

 

Программное обеспечение.

Резидентное программное обеспечение центрального и локального контроллера осталось прежним:

  • sketch_59_2.ino - центральный контроллер:

 Зарегистрируйтесь и оплатите. Всего 25 руб. в месяц за доступ ко всем ресурсам сайта! 

  • sketch_59_1.ino  - локальный контроллер:

 Зарегистрируйтесь и оплатите. Всего 25 руб. в месяц за доступ ко всем ресурсам сайта! 

Загрузить программы в платы Ардуино необходимо до запайки драйверов RS-485. Иначе они будут блокировать сигналы RxD и мешать загрузке из Arduino IDE.

Обмен данными по сети происходит под управлением библиотек Tiny_ModBusRTU_Master и Tiny_ModBusRTU_Slave.

В программах, которые мы использовали в уроке 59, для организации сети через интерфейсы UART объекты ModBus создаются следующим конструктором:

Tiny_ModBusRTU_Slave slave(1, 8, regTable, 6, 13); // создаем объект ModBus

Последний параметр задает номер вывода для управления передатчиком RS-485 (сигнал DE). Для интерфейса UART этот вывод не нужен. Можно было параметр не задавать и сэкономить один вывод микроконтроллера. Но я его задал с номером 13 – светодиод общего назначения. Светодиод светился, когда в контроллере происходила передача данных.

Теперь мы подключили сигнал разрешения работы передатчика (DE) к 13 выводу. Поэтому программное обеспечение осталось прежним. В реальных разработках лучше использовать другой вывод.

 

Проверка работы системы.

Проверка ничем не отличается от тестирования системы-прообраза. Подал питание. Покрутил переменные резисторы, погрел термодатчики, понажимал кнопки. Все работает, данные отображаются на дисплее центрального котроллера. Ошибок обмена нет.

Дисплей системы

Имитировал ошибки обмена – нажал кнопку сброса локального контроллера.

Сообщение об ошибках

Посыпались ошибки на дисплее для данных обоих контроллеров.

В системе-прообразе на интерфейсе UART при нажатии сброса были ошибки только одного локального контроллера. Второй работал нормально. Происходит это, потому что при состоянии сброса микроконтроллер переводит все свои выводы в плавающее состояние (бросает в воздухе). Сигнал разрешения работы передатчика RS-485 за счет светодиод с резистором (вывод 13) переходит в состояние лог. 1. Для передатчика это разрешающий уровень. В результате выход драйвера блокирует линию связи.

Если необходимо, чтобы при отключении микроконтроллера сигналом сброса линия связи не блокировалась необходимо использовать для сигнала DE другой вывод. Также надо подключить его к земле через резистор сопротивлением 5…10 кОм.

Помехоустойчивость сети.

Все, что было написано по поводу сети RS-485 в предыдущем уроке в полной мере справедливо по отношению к нашей системе.

Длина линии связи теперь может достигать 1200 м. Скорость обмена можно увеличить. По сравнению с сетью через интерфейс UART схема незначительно усложнилась, но помехоустойчивость и все остальные параметры повысились. Получилась сеть совершенно другого качественного уровня.

 

В следующем уроке продолжу тему обмена данными между платами Ардуино.

Предыдущий урок     Список уроков     Следующий урок

0

Автор публикации

не в сети 4 дня

Эдуард

56
Комментарии: 1302Публикации: 147Регистрация: 13-12-2015

60 комментариев на «Урок 61. Аппаратная реализация интерфейса RS-485. Объединение плат Ардуино в локальную сеть RS-485.»

  1. Здравствуйте! Спасибо за статью! Скажите пожалуйста, нужно-ли защищать приемопередатчик MAX495 от наводок в линии супрессором?

    0
    • Здравствуйте!
      Да конечно. Если линия длинная и есть опасность высоковольтных импульсных помех то надо защищать. Поставить 3 пробивных стабилитрона (супрессора) между линиями A B, A C, B C.

      0
  2. Добрый день! Спасибо за ваши уроки. У меня не получается передать с одной ардуины на другую показания трех датчиков температуры. Вместо вольтметра в вашем коде показания второго датчика работает, а третий никак не могу настроить. С уважением Виталий.

    0
    • Здравствуйте!
      Передайте сначала просто последовательность байтов. Убедитесь, что они принимаются правильно. Затем упаковывайте в байты значения температуры. Можете открыть тему на форуме сайта.

      0
      • Здравствуйте! У меня все получилось. Сперва не мог понять что делает 2 в (regTable+2), и что надо было ставить для третьего датчика температуры( поставил +4). Но пока не увеличил регистры хранения с 6 до 8 ничего не получалось. Тему открою чуть попозже. Сперва определюсь сколько данных мне надо передавать в проекте. Большое спасибо за уроки.

        0
  3. Эдуард, спасибо за уроки.
    Библиотеки
    Tiny_ModBusRTU_Slave и
    Tiny_ModBusRTU_Master
    не работают с программным UART..??

    0
      • Спасибо за ответ, думал что я что-то не то делаю, хотел использовать уно для опроса нескольких разных веток.
        Придется использовать отдельный контроллер на каждую ветку, или «Мегу».

        0
  4. Здравствуйте Эдуард !
    Спасибо за уроки. Очень хорошие статьи.
    Вопрос: Будет ли работать сеть RS-485 с тремя ведомыми платами Ардуино, если к ней подключить через стандартный преобразователь RS-485 USB компьютер в качестве ведущего с программой для обмена данными, используя на Ардуино Вашу библиотеку Tiny_ModBusRTU_Slave ?

    С уважением Геннадий.

    0
  5. Здравствуйте Эдуард !
    1. Правильно ли я понял, что с помощью переключателей SW1, SW2 и SW3 устанавливается адрес платы с Ардуино ?
    2. Будет ли работать покупной модуль RS-485 TTL, использующий микросхему МАХ 485, с Вашей библиотекой Tiny_ModBusRTU_Slave ?
    С уважением Геннадий.

    0
    • Здравствуйте!
      1. Кнопки SW1 — SW3 используются для демонстрации передачи информации на локальные контроллеры. При нажатии кнопки должен загораться светодиод на соответствующем локальном контроллере.
      2. Да, конечно. Библиотека будет работать с модулем на микросхеме MAX485. У меня в уроке схема ничем не отличается от схемы этого модуля.

      0
  6. Здравствуйте, Эдуард! Огромное спасибо за великолепные уроки! Повсюду в интернете лежат лишь монструозные скетчи, собранные из стандартных примеров, напичканные delay’ями. В крайнем случае встречаются псевдопланировщики на базе функции millis, но все библиотеки опроса датчиков типа DHT22 или того же 18B20 все равно используют все те же delay’и, так что о параллельном выполнении задач вообще речи нет. Ваш же сайт, похоже, единственный в рунете, где показана нормальная реализация многозадачности для всего сразу. Правда придется переделывать все стандартные библиотеки, но это даже хорошо — опыт прокачивается. 🙂
    З.Ы, Присоединяюсь к ждущим с нетерпением следующих уроков. Панели Nextion HMI очень удобны (правда, дороги), с удовольствием почитаю про Ваш опыт общения с ними.

    0
  7. Здравствуйте Эдуард !
    1. У меня Ардуино Мега 2650 и имеется три канала: RX0-TX0, RX1-TX1 и RX2-TX2. Я подключил конвертер RS-485 TTL к каналу RX1-TX1. Скажите, у Вас в библиотеке Tiny_ModBusRTU_Slave для Ардуино определяется по какому каналу вести прием-передачу? Если нет, то подскажите, что надо сделать?
    2. Из каких условий выбран интервал прерываний в 500 мксек ? Можно ли его изменить ?
    С уважением Геннадий.

    0
    • Здравствуйте!
      Библиотека работает только на аппаратном порту 0. Она была создана для урока, хотя по моим тестам и отзывам других работает безупречно. Я проверял ее только на Arduino UNO, Arduino Nano и Arduino PRO Mini. Мне писали, что были проблемы с функционированием на Mega 2560 на Serial, но нашлась причина. Давайте лучше я сейчас на форуме сайта (http://mypractic-forum.ru) опубликую переписку по этому поводу в разделе «Уроки Ардуино». Там же можете задавать вопросы на эту тему.

      0
  8. Здравствуйте Эдуард !
    1. Ардуино Мега 2650 имеет 4 порта: RX0-TX0, RX1-TX1, RX2-TX2, RX3-TX3. У меня подключено к порту RX1-TX1. Есть ли в Вашей библиотеке Tiny_ModBusRTU_Slave возможность указывать по какому порту работать ? Если нет, то как запрограммировать Ардуино, чтобы он работал через этот порт ?
    2. Как выбирался интервал прерывания в 500 мксек и можно ли его изменять ?
    С уважением Геннадий.

    0
  9. Здравствуйте Эдуард !
    Arduino UNO по ModBus_RTU пытаюсь прочитать регистр (ватметр dds238-2 zn) адрес 40015 функции 3. (реверсная энергия)
    Не работает! Чем может отличаться режим раба ардуино от ватметр dds238??
    Вот сам Ваттметр https://ru.aliexpress.com/item/5-65-A-230V-50HZ-voltage-current-DDS238-2-ZN-S-single-phase-Din-rail/32812065998.html?spm=2114.13010708.0.0.8Z8w4V

    0
    • Здравствуйте!
      Может у вас устройство медленно отвечает. Попробуйте увеличить время тайм-аута. На форуме сайта пишут, что даже потребовалось изменить тип переменной для тайм-аута.
      http://mypractic-forum.ru/viewtopic.php?t=87

      0
  10. Здравствуйте!
    А какой допуск на длину импульса при приеме в библиотеках?
    Например,если использовать RS485 для DMX512 — не все устройства передают импульсы-паузы длиной строго 4мс.

    0
    • Здравствуйте!
      Драйверы RS-485 осуществляют только преобразование уровней сигнала. Формированием сигналов занимается контроллер. Длительность импульсов 4 мкс драйверы RS-485 передадут без проблем.

      0
  11. Эдуард, здравствуйте!

    Одна надежда на Вас осталась! 3 недели бьюсь с настройкой передачи данных через китайские модули на MAX485. Приходит -1, а должны придти данные от 0 до 1023 (от потенциометра). Буду очень признателен, если подскажите что не так я сделал. Вот ссылки на мои скетчи, он отличаются от Ваших, но вполне простые.

    https://drive.google.com/file/d/1cXvEr3OWzMjULIxX35F1GlH_MONWMe2w/view?usp=sharing

    https://drive.google.com/file/d/1MpAj73tsTZZhRGMR_XG4dn2zv00eFrfC/view?usp=sharing

    0
    • Здравствуйте!
      Прежде всего, если у вас чисто практическая задача, то возьмите библиотеку для ModBus из последующих уроков и реализуйте задачу через нее. Будет проще, надежнее.
      Теперь про ваше творение.
      Я правильно понял, что для обмена по RS-485 используется аппаратный порт Serial?
      Что вы передаете. Команда Serial.println(pot); передает несколько байтов: символы, соответствующие числу pot в десятичном виде, управляющие символы возврат каретки (код 13) и перевод строки (код 10).
      Это от 3 до 6 байтов. Например, если у вас значение pot= 356, то будет передан код символа 3, символа 5, символа 6 и управляющие коды. И вы добавляете паузу между пакетами 150 мс.
      Что вы принимаете.
      Командой Serial.read(); вы считываете первый попавшийся байт и загружаете его в переменную pot, с которой дальше работаете, полагая, что это число, полученное от передатчика.
      В pot у вас будет, что попало. Если вы попадете на момент, когда буфер Serial пуст, вы получите -1. Еще из буфера вы можете получить код одного символа числа в текстовом виде.
      Посмотрите урок 12 о последовательном порте. Обратите внимание на передачу данных в двоичном и символьном виде. И еще просмотрите урок 31 о текстовых протоколах.
      Если вы хотите принять, то что вы сейчас передаете, т.е. число в текстовом виде, то вы должны:
      1. Ожидать паузу в передаче. Проверять функцией available, что в течении какого-то времени, например 10 мс, не пришло ни одно данное.
      2. Ожидать прихода первого данного.
      3. Записать в текстовый массив все пришедшие коды символов, без управляющих символов.
      4. Преобразовать полученное число из текстового вида в двоичное число и записать его в переменную pot.
      Только так.
      Более простой вариант передавать переменную pot в двоичном виде. Надо передать 2 байта функцией write.
      Тогда всегда будут передаваться только 2 байта и нет необходимости преобразовывать их в двоичный формат. Все остальное, вычислять паузу между передачами и т.п., делать надо.
      И еще я не понял, зачем вы принятое число передаете назад.
      Serial.println(pot);

      0
      • Эдуард, добрый день! Благодарю за внимание и совет! ModBus еще сложно для меня, не разобрался.Serial.println(pot); использовал, чтобы увидеть что передаю. Иначе не получилось. Решил передавать через write, но ничего не получается.В мониторах передатчика и приемника пусто. Паузу ставил, не помогает. Вот отредактированный код:

        #include

        SoftwareSerial RS485 (7,6); // Инициализируем порты RX и TX
        #define DIR 13 // Задаем константу для порта управления
        //int pot;

        void setup () {

        Serial.begin(9600); // Инициализируем последовательное соединение
        RS485.begin(4800); // Инициализируем программный сериал

        pinMode(DIR,OUTPUT); // Устанавливаем режим работы для цифрового вывода как Выход
        digitalWrite(DIR, HIGH); // включаем режим передачи
        }

        void loop () {
        if( Serial.available() > 0 ) {
        int pot = analogRead(0);
        Serial.write(pot);
        }
        }

        Что я упустил, подскажите, пожалуйста.

        0
        • Здравствуйте!
          Так вы какой порт используете для обмена по RS-485?
          Если программный, то почему вы передаете данные через аппаратный.
          В любом случае вы проверяете наличие данных в приемном буфере и, если он пуст, то передаете. Зачем?
          Но давайте с портом определимся.

          0
  12. Вот тут провал в понимании и терминалогии. Насмотрелся полупохожих примеров и запутался. Я пытаюсь получить данные с потенциометра и отправить их через програмный сериал с пинов 6 и 7. Я пробовал задавать RS485.write(pot) вместо Serial.write(pot), но толку не было. Почему я передаю при пустом буфере?

    0
    • Начните с того, что передавайте в цикле один байт.
      RS485.write(50);
      delay(200);
      Если нет осциллографа, то подключите светодиод через резистор к выводу 6 и убедитесь, что он мигает примерно 5 раз в секунду.
      Потом подключите приемную плату, подключите светодиод на выход MAX485 приемной платы и убедитесь, что данные приходят.

      0
  13. Поправил:

    void loop () {
    int pot = analogRead(0);
    RS485.write(pot);
    delay(500);
    }

    На МАХ485 передатчика диод работает как надо. На выходе МАХ 485 приемника тоже работает.

    Но приемник команды не выполняет…

    0
    • Верните передатчик к передаче одного фиксированного байта и проверьте приемник.
      if( RS485. available() != 0 ) {
      RS485.read();
      digitalWrite(13, ! digitalRead(13));
      }
      Программа должна инвертировать состояние светодиода на приход каждого байта.
      Только задайте 13 вывод на выход.

      0
    • Значит прием идет.
      Теперь надо передавать переменную pot. Она типа int, поэтому надо передавать 2 байта. Сначала младший, потом старший.
      int pot = analogRead(0);
      RS485.write((byte)pot);
      RS485.write((byte)(pot>>8));
      delay(500);

      Светодиод перестанет мигать, потому что прием одного байта будет инвертировать вывод 13, и тут же прием следующего байта инвертировать еще раз.
      Дальше надо выделять паузу. между принятыми данными.
      И принимать данные.
      while( RS485.available == 0 ) {}
      pot= (unsigned int)RS485.read();
      while( RS485.available == 0 ) {}
      pot |= ((unsigned int)RS485.read()) < < 8 ; Надо отрабатывать тайм-аут, вдруг обмен зависнет и т.п. Посмотрите в моих программах.

      0
  14. Эдуард, добрый день!

    Проблемы с строчкой «pot |= ((unsigned int)RS485.read()) < < 8" Пишет "expected primary-expression before 'unsigned'"
    Не нашел решения. Что же делать?

    0
  15. Ура, это исправил! Теперь в мониторе порта приемника приходит «1». Но как же мне теперь получить данные от 0 до 1023?

    0
    • Сейчас данные должны приниматься. Только не выделяется первый байт, поэтому может быть путаница. Может приниматься сначала второй, а потом первый байт. Но в принципе данные с АЦП должны изменяться.

      0
      • На потенциометр не реагирует и постоянно 1 мониторе.

        Вот такой код получается:

        void loop () {

        while( RS485.available() == 0 ) {}
        pot= (unsigned int)RS485.read();
        delay(10);
        while( RS485.available() == 0 ) {}
        pot |= ((unsigned int)RS485.read()) << 8;
        delay(10);
        Serial.println(RS485);

        Тогда как же избавиться от путаницы?

        0
          • Эдуард, разве в данной программе не выводится два байта?

            #include

            SoftwareSerial RS485 (7,6); // Инициализируем порты RX и TX
            #define DIR 13 // Задаем константу для порта управления
            int pot;
            int a;
            int s;
            void setup () {

            Serial.begin(9600); // Инициализируем последовательное соединение
            RS485.begin(4800); // Инициализируем программный сериал

            pinMode(DIR,OUTPUT); // Устанавливаем режим работы для цифрового вывода как Выход
            digitalWrite(DIR, HIGH); // включаем режим передачи
            }

            void loop () {
            int pot = analogRead(0);
            RS485.write((byte)pot);
            RS485.write((byte)(pot>>8));
            delay(500);

            }

            0
          • Еще вопрос analogRead(0);. Надо analogRead(A0);

            Добейтесь, чтобы у вас с одним байтом работало. На передающей стороне сделайте в цикле:
            RS485.write((byte)analogRead(A0));
            delay(500);

            На приемной стороне:
            if( RS485.available() != 0 ) Serial.println(RS485.read());

            0
          • Так как я вывожу в сериал с приемника, поэтому Serial.println(pot);

            Вот скетч. Мне нужно передать показания потенциометра, конвертировать их в ШИМ для управления моторами.

            #include

            SoftwareSerial RS485 (8,7); // Инициализируем порты RX и TX
            //#define DIR 12 // Задаем константу для порта управления
            #define LED 13 // Задаем константу для порта управления

            //Motor Pins
            int EN_A = 11; //Enable pin for first motor. было 11
            int IN1 = 9; //control pin for first motor было 9
            int IN2 = 6; //control pin for first motor было 8
            int IN3 = 5; //control pin for second motor было 7
            int IN4 = 3; //control pin for second motor было 6
            int EN_B = 10; //Enable pin for second motor было 10
            //Initializing variables to store data
            int X;
            int pot;
            int a;

            void setup ( ) {
            Serial.begin (9600); //Starting the serial communication at 9600 baud rate
            RS485.begin(4800); // Инициализируем программный сериал
            pinMode(DIR,OUTPUT); // Устанавливаем режим работы для цифрового вывода как Выход
            digitalWrite(DIR, LOW); // Задаем логически 0, что переводит модуль в режим приемника
            pinMode(LED,OUTPUT);

            pinMode(EN_A, OUTPUT);
            pinMode(IN1, OUTPUT);
            pinMode(IN2, OUTPUT);
            pinMode(IN3, OUTPUT);
            pinMode(IN4, OUTPUT);
            pinMode(EN_B, OUTPUT);

            }

            void loop () {

            while( RS485.available() == 0 ) {}
            pot= (unsigned int)RS485.read();
            delay(10);
            while( RS485.available() == 0 ) {}
            pot |= ((unsigned int)RS485.read()) << 8;
            delay(100);
            Serial.println(RS485);

            int X = map(pot, 0, 1023, 0, 255); //Mapping the values to 0-255 to move the motor

            digitalWrite(IN1, LOW);
            digitalWrite(IN2, HIGH);
            analogWrite(EN_A, X);

            digitalWrite(IN3, LOW);
            digitalWrite(IN4, HIGH);
            analogWrite(EN_B, X);
            }

            0
  16. С одним байтом приходят разные числа. Добавляю второй байт:

    void loop () {

    //if( RS485.available() != 0 ) Serial.println(RS485.read());
    while( RS485.available() == 0 ) {}
    pot= (unsigned int)RS485.read();
    delay(10);
    while( RS485.available() == 0 ) {}
    pot |= ((unsigned int)RS485.read()) << 8;
    delay(100);
    Serial.println(RS485);

    В результате — опять приходит только "1". Эдуард, а правильно ли введено "pot |" ? Символ в виде палки не помеха?

    0
    • А правильные?
      Когда вы повышает напряжение от 0 до максимума должны приходить 0…255, затем опять 0…255, и еще 2 раза так.

      0
      • Если все правильно с одним байтом, то надо включить 2 байта только на передатчике. И вручную пересчитать код.
        код = мл. байт + ( ст.байт * 256 )
        Если все правильно, только тогда делать приемник на 2 байта.

        0
        • С одним приходит через единицу, в виде:

          1
          35
          1
          35
          1
          35
          1
          35
          1
          Да, максимальное число 255. Единица это и есть младший байт?

          0
          • Кстати, может лучше на передатчике показания потенциометра конвертировать в диапазон 0-255 и передать, а полученные сигнал использовать для ШИМ ?

            0
          • Конечно, 1 байт передавать проще. Передавать так:
            RS485.write((byte)(analogRead(A0) >> 2));
            delay(500);

            0
          • Старший байт не может быть боле 3. Сейчас код 291, т.е. напряжение 1,42 В. Так?

            0
  17. Не могу сказать на счет кода и напряжения, но добился передачи от 0 до 255.

    Передатчик

    void loop () {
    pot=analogRead(A0);
    int X = map(pot, 0, 1023, 0, 255); //Mapping the values to 0-255 to move the motor
    RS485.write(X);

    Приемник

    oid loop () {

    if( RS485.available() != 0 ) Serial.println(RS485.read());
    while( RS485.available() == 0 ) {}
    pot= (unsigned int)RS485.read();
    delay(500);
    Serial.println(RS485);

    В результате при крайнем положении потенциометра:

    1
    255
    1
    255
    1
    255
    1
    255
    1

    ЧТо же делать с единицей?

    0
  18. Добрый день. Можете посоветовать, как прикрутить библиотеку Tiny_ModBusRTU_Master к ESP8266

    0
      • Спасибо за оперативные ответы. Вот разбираюсь с алгоритмом библиотеки Tiny_ModBusRTU_Master и такие вот вопросы:
        1. Почему выбор режима _mode реализовали через if/else, а не switch/case?
        2. Команда if( (UCSR0A & 64) != 0 ) очень уж специфичная для AVR. Можно ли заменить на if(!Serial.available())? Если я правильно понимаю UCSR0A с маской по пятому биту проверяет флаг опустошения регистра данных UDR0 последовательного интерфейса USART0.
        Дело в том, что я пока плохо знаю тонкости Си, потому и такие вопросы.

        0
        • Здравствуйте!
          1. Какая разница?
          2. Нет, нельзя. Функция available() проверяет наличие принятых данных в буфере Serial. Цель конструкции if( (UCSR0A & 64) != 0 ) — проверить, что закончилась передача данных из сдвигового регистра. Есть буферный регистр передатчика. Если он пуст, то это значит, что новые данные можно загружать, но это не означает, что передача данных на выходе TX закончилась. А нам надо убедиться, что передача данных закончилась и можно разворачивать шину на прием. Посмотрите последний урок по STM32. Там этот момент обсуждается.

          0
          • Спасибо огромное. Ну про if/else я просто уточнил. Было предположение, что конструкция switch/case больше памяти съедает.
            Касаемо UCSR0A & 64 пока думаю как организовать проверку окончания передачи данных в ESP8266. С этим зверем я только начинаю дружить.
            Еще раз огромное спасибо!!!

            0

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *