ArduinoModbus / RS485 конфликт между Serial и Serial1

Я пытаюсь реализовать ArduinoModbus на моем STM32 Poternta H7 с помощью коммутационной платы.

Хорошо документировано, что в ArduinoRS485 объект RS485 жестко подключен. Если вы используете плату PH7/Breakout, вам нужно перенастроить ее, чтобы убедиться, что RS485 установлен на Serial1/Uart1.

После перенастройки, когда я запускаю свой код, я изначально могу писать отладочные сообщения в последовательный монитор через последовательный порт (встроенный USB C). Но как только я начинаю использовать RS485 на Serial1, я больше не могу печатать в последовательный монитор через последовательный порт, и код зависает.

Что я сделал, чтобы перенастроить объект RS485. Я реализовал следующее на основе этого обходного пути от Arduino ArduinoModbus для других шилдов и с другим последовательным портом - MKR SHIELDS - Форум Arduino 1 Затем сохранил обновленный ArduinoRS485 в /lib.

В ArduinoRS485.cpp

void RS485Class::setSerial(HardwareSerial* serial) {
  _serial = serial;
}

В ArduinoRS485.h

void setSerial(HardwareSerial* serial);

В моем коде настройки я определил:

#define UART1_TX_PIN PA_9       // Заголовок J1 33 (LPUART) = SERIAL1_TX = R0
 #define UART1_RX_PIN PA_10      // Заголовок J1 35 (LPUART) = SERIAL1_RX = DI
 #define UART1_RTS_PIN PI_14     // Разъем J1 37 (LPUART) = SERIAL1_RTS = вывод REn
 #define UART1_CTS_PIN PI_15     // Заголовок J1 39 (LPUART) = SERIAL1_CTS = DE
 #define SERIAL_PORT_HARDWARE Serial1

Мой ModbusClient настроен

void modbusClientSetup() {
     
   while (!Serial);
     Serial.println("");
     Serial.println("Modbus RTU Client Test");
     
     RS485.setPins(UART1_TX_PIN, UART1_RX_PIN, UART1_RTS_PIN);
     RS485.setDelays(50,50);
     RS485.setSerial(&SERIAL_PORT_HARDWARE);
 
     if(!ModbusRTUClient.begin(9600,SERIAL_8N1 )){
     //Serial.println("Failed to start Modbus RTU Client!");
     while (1);
   }
 }

Строка Serial.println("Modbus RTU Client Test"); работает нормально.

Then i run this code to test my Modbus

 void writeCoilValues() {
   
   // устанавливаем катушки на 1, когда счетчик нечетный
   byte coilValue = ((counter % 2) == 0) ? 0x00 : 0x01;
 
   Serial.print("Writing Coil values ... ");
 
   // записать 10 значений катушки в (ведомый) идентификатор 1, адрес 0x00
   ModbusRTUClient.beginTransmission(slaveID, COILS, 0x15, 10);>   for (int i = 0; 
     i < 10; i++) {
     counter = i;
     coilValue = ((counter % 2) == 0) ? 0x00 : 0x01;
     ModbusRTUClient.write(coilValue);
     delay(100);
   
   if (!ModbusRTUClient.endTransmission()) {
     Serial.print("failed! ");
     errClient = ModbusRTUClient.lastError();
     Serial.println(errClient);
   } else {
     errClient = "All Good";
     Serial.println("success");
   }
 }

Строка Serial.print("Writing Coil values ... "); не печатается, но код не зависает.

Но как только я дохожу до Serial.print("failed! "); код просто зависает на write_op.wait(NULL); в USBCDC.cpp ниже.

bool USBCDC::send(uint8_t *buffer, uint32_t size)
 {
     lock();
 
     AsyncWrite write_op(this, buffer, size);
     _tx_list.add(&write_op);
 
     unlock();
 
     write_op.wait(NULL);
     return write_op.result;
 }

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

Ура

, 👍0


2 ответа


Лучший ответ:

1

Хорошо документировано, что в ArduinoRS485 объект RS485 подключен жестко.

Я не знаю, откуда вы черпаете эту «хорошо документированную» информацию, но и библиотека ArduinoRS485, и библиотека ArduinoModbus позволяют вам передавать последовательный порт, который вы собираетесь использовать, через конструкцию класса. Вы можете увидеть исходный код RS485 Construct и ModbusRTU Construct.

Итак, чтобы использовать Serial1, вам нужно создать экземпляр класса и передать ему последовательный порт, который вы собираетесь использовать.

#include <ArduinoRS485.h>
#include <ArduinoModbus.h>

#define UART1_TX_PIN PA_9       // Заголовок J1 33 (LPUART) = SERIAL1_TX = R0
#define UART1_RX_PIN PA_10      // Заголовок J1 35 (LPUART) = SERIAL1_RX = DI
#define UART1_RTS_PIN PI_14     // Разъем J1 37 (LPUART) = SERIAL1_RTS = вывод REn
#define UART1_CTS_PIN PI_15     // Заголовок J1 39 (LPUART) = SERIAL1_CTS = DE

RS485 rs485(Serial1, UART1_TX_PIN, UART1_RX_PIN, UART1_RTS_PIN, UART1_CTS_PIN);
ModbusRTUClient mbClient(&rs485);

void setup() {
  Serial.begin(115200);

  // запустить клиент Modbus RTU
  if (!mbClient.begin(9600)) {
    Serial.println("Failed to start Modbus RTU Client!");
    while (1);
  }
}

void loop() {
 // доступ к различным методам ModbusRTUClient с помощью объекта mbClient
}
,

2

Спасибо это сработало (почти, мне пришлось внести несколько изменений, но это помогло мне добиться цели, я добавил требуемые изменения ниже). Я уже пробовал версию этого подхода раньше, но по какой-то причине мне не удалось заставить ее работать.

#include <ArduinoRS485.h>
#include <ArduinoModbus.h>

#define UART1_TX_PIN PA_9       // Заголовок J1 33 (LPUART) = SERIAL1_TX = R0
#define UART1_RX_PIN PA_10      // Заголовок J1 35 (LPUART) = SERIAL1_RX = DI
#define UART1_RTS_PIN PI_14     // Разъем J1 37 (LPUART) = SERIAL1_RTS = вывод REn
#define UART1_CTS_PIN PI_15     // Заголовок J1 39 (LPUART) = SERIAL1_CTS = DE

// Следующие две строки отличаются.
RS485Class rs485(Serial1, UART1_TX_PIN, UART1_RX_PIN, UART1_RTS_PIN);
ModbusRTUClientClass mbClient(&rs485);

void setup() {
  Serial.begin(115200);

  // запустить клиент Modbus RTU
  if (!mbClient.begin(9600)) {
    Serial.println("Failed to start Modbus RTU Client!");
    while (1);
  }
}

void loop() {
 // доступ к различным методам ModbusRTUClient с помощью объекта mbClient
}
,

RS485Class не обязателен, RS485 должен работать, см. [исходный код](https://github.com/arduino-libraries/ArduinoRS485/blob/master/src/RS485.h#L109). То же самое для [ModbusRTUClient](https://github.com/arduino-libraries/ArduinoModbus/blob/master/src/ModbusRTUClient.h#L47)., @hcheung

Привет и спасибо еще раз. Попробовал еще раз, и мне удалось заставить код работать только тогда, когда я использую RS485Class и ModbusRTUClientClass для определения моего объекта mbClient., @Dave by 2