ESP32 + RS-485(Mudbus RTU) = работает

klofelin
Offline
Зарегистрирован: 26.11.2021

nik182, спасибо за ответ.
Я убрал 485. Пины esp32 подключил напрямую к A и B контактам USB переходника. Но результат не изменился.
Слэйв (компьютер) получает запрос на чтение регистров и отправляет их содержимое. А esp32 выдает ошибку и не записывает информацию в массив.
Не пойму... Axex писал, что у него получилось.

nik182
Offline
Зарегистрирован: 04.05.2015

Подключать надо к входам имеющим те же логические протоколы и физические уровни сигналов. Для USB не знаю A B, знаю D+ D-. Соединить надо Rx TTL c Tx TTL и Тх TTL c Rх TTL последовательных портов. Это если соединять 2 платы. Если комп соединять, то просто воткнуть провод компа в USB-TTL конвертор последовательного порта и Rx Tx соединить с ногами Tx Rx последовательного порта платы, установив правильное напряжение на конверторе.  

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

ESP32 стоит подключать по вот такой схеме к железке MAX485/MAX3485(вторая лучше). Но в идеале MAX485/MAX3485 должна иметь примерно такую обвязку:

 

MOP3E
Offline
Зарегистрирован: 19.09.2021

klofelin пишет:
Меня смущает, что контакты DE, RE у MAX485 висят в воздухе.

Правильно смущает. При обмене данными на них по какому-то алгоритму должна подаваться логическая единица. Но, кажется, эта либа не управляет этими входами. Нужно делать обвязку для их включения-отключения. Или купить что-то вроде такого (там обвязка уже прикручена на плату, просто втыкаешь UART и дело в шляпе):

6 в 1, конвертер USB - TTL COM, RS232, RS485 и между собой (Silabs CP 2102) (mysku.ru)

b707
Offline
Зарегистрирован: 26.05.2017

MOP3E пишет:

по какому-то алгоритму ....

:)))))))))

klofelin
Offline
Зарегистрирован: 26.11.2021

Ура, получилось! Всем спасибо за помощь. Научили пацана)

Также я обращался к разработчику библиотеки Modbus-esp8266 - Александру Емельянову. Он любезно поделился информацией по поводу того, что делать с контактами RE/DE в случае, если связь через RS485. У него на гитхабе есть описание частых проблем, возникающих с этой ошибкой. Одна из них оказалась и у меня - одна плата RS485 не заработала. 

Код ниже для модбас-мастера который читает два регистра у слейва, сохраняет их в массив и записывает слейву обратно.

#include <ModbusRTU.h>

#define SLAVE_ID 1
#define FIRST_REG 0
#define REG_COUNT 2
#define MODBUS_RX_PIN 25     //RO in RS485 module
#define MODBUS_TX_PIN 32     //DI  in RS485 module
#define RE_DE_PIN 33

ModbusRTU mb;

bool cb(Modbus::ResultCode event, uint16_t transactionId, void* data) { // Callback to monitor errors
  if (event != Modbus::EX_SUCCESS) {
    Serial.print("Request result: 0x");
    Serial.println(event, HEX);
  }
  return true;
}

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200, SERIAL_8N1, MODBUS_RX_PIN, MODBUS_TX_PIN);
  mb.begin(&Serial1, RE_DE_PIN);                                    //if without RE_DE_PIN in RS485 module then   mb.begin(&Serial1);
  mb.master();
}

uint16_t res[REG_COUNT];

void loop() {
  if (!mb.slave()) {    // Check if no transaction in progress
    mb.readHreg(SLAVE_ID, FIRST_REG, res, REG_COUNT, cb); // Send Read Hreg from Modbus Server
    while(mb.slave()) { // Check if transaction is active
      mb.task();
      //delay(10);
    }
    //Serial.println(res[0]);
    //Serial.println(res[1]);
  }
  
  delay(1000);
  
    if (!mb.slave()) {    // Check if no transaction in progress
    mb.writeHreg(SLAVE_ID, FIRST_REG+2, res, REG_COUNT, cb); // Send Write Hreg from Modbus Server
    while(mb.slave()) { // Check if transaction is active
      mb.task();
      //delay(10);
    }
    //Serial.println(res[0]);
    //Serial.println(res[1]);
  }
  
}

 

b707
Offline
Зарегистрирован: 26.05.2017

Хм, а вот чего не понимаю... Ведь модбас- протокол высокого уровня, который может работать поверх разных транспортных интерфейсов, например самого обыкновенного Сериал. И самому модбасу в общем-то до лампочки конкретные детали обмена байтами на нижнем уровне.
В таком случае зачем нужна отдельная библиотека модбас для Есп и чем она отличается от модбас библиотеки для ардуино?
Почему вообще возникают такие темы как " модбас на есп" - разве протокол обмена между мастером и слейвами зависит от типа МК каждого из них? - конечно нет. Тогда в чем проблема запустить модбас на есп, если например под ардуину библиотека уже есть?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Потому чта... Использование MAX485 требует правильного контроля направления передачи. Переключать на чтение нужно когда все байты отправлены и аппаратный буфер тоже пуст. Это невозможно определить не опускаясь к аппаратному уровню, разве что считать время, которое зависит от скорости последовательного интерфейса и один хрен сделать это точно не получится.

b707
Offline
Зарегистрирован: 26.05.2017

Ок. это понятно, но тут как минимум половину ветки обсуждалась библиотека, которая вообще не управляет пинами разрешения приема и передачи на МАХ485, то есть не имеет этой проблемы.  А с ней в чем сложность?

nik182
Offline
Зарегистрирован: 04.05.2015

Не, управляет. Конструктор по другому надо вызывать, с указанием пина ЕN.

PabloSS
Offline
Зарегистрирован: 11.04.2022

Здравствуйте. Лично у меня Ваш код работает только на чтение. Помогите разобраться) Да и чтение с командами из этой библы, типа readIreg() тоже не работает

PabloSS
Offline
Зарегистрирован: 11.04.2022

klofelin пишет:

Ура, получилось! Всем спасибо за помощь. Научили пацана)

Также я обращался к разработчику библиотеки Modbus-esp8266 - Александру Емельянову. Он любезно поделился информацией по поводу того, что делать с контактами RE/DE в случае, если связь через RS485. У него на гитхабе есть описание частых проблем, возникающих с этой ошибкой. Одна из них оказалась и у меня - одна плата RS485 не заработала. 

Код ниже для модбас-мастера который читает два регистра у слейва, сохраняет их в массив и записывает слейву обратно.

#include <ModbusRTU.h>

#define SLAVE_ID 1
#define FIRST_REG 0
#define REG_COUNT 2
#define MODBUS_RX_PIN 25     //RO in RS485 module
#define MODBUS_TX_PIN 32     //DI  in RS485 module
#define RE_DE_PIN 33

ModbusRTU mb;

bool cb(Modbus::ResultCode event, uint16_t transactionId, void* data) { // Callback to monitor errors
  if (event != Modbus::EX_SUCCESS) {
    Serial.print("Request result: 0x");
    Serial.println(event, HEX);
  }
  return true;
}

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200, SERIAL_8N1, MODBUS_RX_PIN, MODBUS_TX_PIN);
  mb.begin(&Serial1, RE_DE_PIN);                                    //if without RE_DE_PIN in RS485 module then   mb.begin(&Serial1);
  mb.master();
}

uint16_t res[REG_COUNT];

void loop() {
  if (!mb.slave()) {    // Check if no transaction in progress
    mb.readHreg(SLAVE_ID, FIRST_REG, res, REG_COUNT, cb); // Send Read Hreg from Modbus Server
    while(mb.slave()) { // Check if transaction is active
      mb.task();
      //delay(10);
    }
    //Serial.println(res[0]);
    //Serial.println(res[1]);
  }
  
  delay(1000);
  
    if (!mb.slave()) {    // Check if no transaction in progress
    mb.writeHreg(SLAVE_ID, FIRST_REG+2, res, REG_COUNT, cb); // Send Write Hreg from Modbus Server
    while(mb.slave()) { // Check if transaction is active
      mb.task();
      //delay(10);
    }
    //Serial.println(res[0]);
    //Serial.println(res[1]);
  }
  
}

 

klofelin
Offline
Зарегистрирован: 26.11.2021

Для начала все манипуляции лучше проводить без rs485. Для отладки я использовал esp32 - TTL to USB - комп. Только когда заработает эта связка, тогда есть смысл пробовать rs 485. Но плата rs 485 имеет уровни сигналов выше чем нужно esp32, т.к. питается от 5 в. И последствия такой связки у меня дают положительный результат только в некоторых случаях. Если я повешу ещё какие-то датчики на esp32, то либо rs485 не заработает, либо датчики будут выдавать фигню.

PabloSS
Offline
Зарегистрирован: 11.04.2022

А вы уверены что по RX/TX передаются (принимаются) сигнали рабочим напряжением 5В (3,3В)?

klofelin
Offline
Зарегистрирован: 26.11.2021

У меня нет осциллографа и опыта в этом деле. Но когда я подключил rs485 к esp32, то на некоторых контактах esp32 обнаружил мультиметром напряжение около 4В. Причем это были не только те контакты, которыми соединялся rs485 с esp32, но и контакты принадлежащие тому-же АЦП.
К тому же тут писал кто-то, что 485 с ардуинкой работает, а с esp32 не захотел. Возможно, причина та же. Нужно согласовать уровни сигналов. Но для начала рекомендую добиться стабильной работы без rs485.
Библиотекой и примером продолжаю успешно пользоваться в своем проекте, но пока без rs485.

PabloSS
Offline
Зарегистрирован: 11.04.2022

Ок. Все равно не ясно - читает все регистры с частотного преобразователя прекрасно и без ошибок. Писать с помощью writeHreg() как у вас в примере не хочет никуда. Я, конечно, не спец, но если были бы какие-то несогласованности по напряжениям, то и с чтением были бы проблемы. Подскажите пожалуйста как связывались с Емельяненко, разработчиком ModbusRTU.h??

klofelin
Offline
Зарегистрирован: 26.11.2021

Отладку легче с компом производить - послушать порт и выяснить кто выделывается. А Вы точно знаете, что писать нужно в Hreg и номера регистров?
В примерах, которые в библиотеке, можно поискать емэйл разработчика и на гитхабе можно посмотреть. Вот, покапался для Вас - a.m.emelianov@gmail.com

PabloSS
Offline
Зарегистрирован: 11.04.2022

Благодарю вас за контакты. Уже регаюсь на гите. Согласно KEYWORD библиотеки там есть  только writeHreg() и writeCoil(). Мне нужно записать в  регистры которые, согласно руководству по настройке оборудования, предназначены только для записи. Я таких регистров не вижу даже в спецификации Modbus. У меня есть другое устройство которое и пишет и читает с этого же частотного преобразователя что угодно. Так что адреса регистров я знаю.

PabloSS
Offline
Зарегистрирован: 11.04.2022

Кстати, с регистров "только для чтения" я спокойно читаю с помощью readHreg(). Хотя согласно документации к Modbus такие регистры не являются Holding.

  • Discrete Inputs — дискретные входы устройства, доступны только для чтения. Диапазон адресов регистров: с 10001 по 19999. Имеют функцию «02» — чтение группы регистров
  • Coils — дискретные выходы устройства, или внутренние значения. Доступны для чтения и записи. Диапазон адресов регистров: с 20001 по 29999. Имеет функции: «01» — чтения группы регистров, «05» — запись одного регистра, «15» — запись группы регистров
  • Input Registers — 16-битные входы устройства. Доступны только для чтения. Диапазон адресов регистров: с 30001 по 39999. Имеют функцию: «04» — чтение группы регистров
  • Holding Registers — 16-битные выходы устройства, либо внутренние значения. Доступны для чтения и записи. Диапазон адресов регистров: с 40001 по 49999. Имеют
sadman41
Offline
Зарегистрирован: 19.10.2016

Как-то я ковырялся с китайским частотником... И там что-то такое было - пишешь частоту в один регистр, а читаешь вообще с другого.

PabloSS
Offline
Зарегистрирован: 11.04.2022

У нас качественные частотники и мы с ними давно работаем. Просто сейчас нужно сделать управление с ESP32. А он пока только читает.

nik182
Offline
Зарегистрирован: 04.05.2015

У modbus все регистры одинаковые. Нет физического разделения. Любой регистр можно прочитать и записать любой функцией. Это на заре модбасастроения, когда реализация была аппаратная, что бы не искать номера регистров их делили чисто логически. Сейчас, когда МК может прочитать регистр с любым номером осталось одно ограничение - тип данных регистра word. И конечно конечное устройсво может иметь начало пула регистров с любого адреса. А уж holding они или что там ещё при чтении вообще не имеет значения. Если конечное устройство может отдать информацию, оно её отдаст. Если после записи может сохранить в регистре- сохранит.

PabloSS
Offline
Зарегистрирован: 11.04.2022

В моем случае содержимое регистров "только для записи" не читается. Но мы уже ушли от моего вопроса.

PabloSS
Offline
Зарегистрирован: 11.04.2022
SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

PabloSS пишет:
Если есть желание помочь разобраться, то тему я уже создал. ModbusRTU + ESP32 + частотный преобразователь VEMPER VR100. Читаются только регистры функциональных кодов 

Поставьте ModbusPull на компьютер, подключите к сети RS485.

Сначала проверьте что и как отвечает ваш частотник мастеру на компе (ModbusPull), в ModbusPull есть возможность и писать и читать регистры.

А потом выключаете отправку данных в ModbusPull и оставляете "Communication Traffic", а мастером включаете ваш ESP32 и наблюдаете разницу в передаваемых сообщениях.

Я пока не дошел до ESP32 с мастером Modbus RTU, но планирую к лету, не до этого пока.

ESP32 буду подключать к RS485 через драйвер SP3485. Он работает с питанием 3.3В и 5В, в отличии от MAX485, который работает только от 5В.

Никаких преобразователей уровней с ним не нужно, просто подключается к ESP32, 3.3В и на линию A, B и GND.

С Мегой я использовал так же SP3485, RE/DE объедены и подключены на порт Меги.

Так вот, пока я не добавил запрет прерываний на прием (у меня драйвер RS485 подключен к Serial1) перед переключением на передачу, и разрешение прерываний по приему после переключения на прием, периодически проскакивали ошибки обмена.  С добавлением запрета/разрешения прерываний ошибок нет в принципе.

За основу брал  эту библиотеку но переписывал ее под свои нужды.

 

   

Kakmyc
Offline
Зарегистрирован: 15.01.2018

В документации на частотник должен быть полный объем информации по вашему вопросу. Вплоть до рекомендуемого алгоритма проверки crc с программным кодом на Си.