Modbus.poll() from ModbusRtu doesn't work properly

Hi,

I want to read some data from a pyranometer using Modbus, an arduino mega and a max485 converter (to create a rs485 grid, the complete proyect includes several pyranometer connected to the same port of the arduino).

I am using Modbusrtu.h library, but it doesn't seem to work correctly. I am able to transmits data, and the pyranometer responds as it should, but the function modbus.poll() doesn't receive anything. I know i am receiving things because i made a proof conecting the rx to a diferent serial port, and I read the response using Serial.read(). So, the error must be in the receiving part.
As I said, i can read the data from the pyranometer using serial.read(), but this solution is not valid to as i need in a further step to connect more than one pyranometer to the rs485, and i don't know how to manage the responses or controling the data without a library.

I've read this old Forum about the same subject, but it is closed and i don't fully understand the solution given there. What's the problem with the millis()? and how should i modify the library to solve the problem?

I put my code here (it is quite similar to the example code):

#include <ModbusRtu.h>


/**
    Modbus object declaration
    u8id : node id = 0 for master, = 1..247 for slave
    u8serno : serial port (use 0 for Serial)
    u8txenpin : 0 for RS-232 and USB-FTDI
                 or any pin number > 1 for RS-485
   u8txenpin pin for txen RS-485 (=0 means USB/RS232C mode)
   u8rxenpin pin for rxen RS-485 (=0 means USB/RS232C mode) NO EN ESTA LIBRERIA
*/
//  Modbus(u8id, u8serno, u8txenpin, u8rxenpin);
Modbus master(0, 3, 22); //ID: 0 (master)
                         //Serial port: 3
                         //Enable pint : any (not use)

/**
   This is an structe which contains a query to an slave device
*/
modbus_t telegram;

//-=-=-=-Variables ModBus-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
uint16_t au16data[16];
uint8_t u8state;       //!< machine state
uint8_t u8query;       //!< pointer to message query
unsigned long u32wait;


//Variables globales
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
float radiometro = 0;


//Variables de la respuesta
unsigned int respuesta[16];       //sin signo porque es como se recibe
unsigned int irradiancia_serie[4];
unsigned long int irradiancia;  //32 bits sin signo
int n_mensaje;


void setup() {

  Serial.begin(19200);
  Serial1.begin(19200);
  Serial2.begin(19200);
  Serial3.begin(19200);

  master.begin( 19200, SERIAL_8E1 ); // baud-rate at 19200
  master.setTimeOut( 5000 ); // if there is no answer in 5000 ms, roll over
  u32wait = millis() + 1000;
  u8state = u8query = 0;

  //ENVÍO DE TELEGRAMAS POR FIWARE
  // telegram 0: read registers
  telegram.u8id = 4; // slave address
  telegram.u8fct = 3; // function code (this one is registers read)
  telegram.u16RegAdd = 2; // start address in slave
  telegram.u16CoilsNo = 2; // number of elements (coils or registers) to read
  telegram.au16reg = au16data[0]; // pointer to a memory array in the Arduino





  Serial.println("Estoy en el setup");
  int ID;
  ID = master.getID();
  Serial.println( "ID del maestro (arduino): " + String(ID));

}



void loop() {
  // put your main code here, to run repeatedly:
  radiometro = leeRadiometro();

  Serial.println("Radiometro " + String(radiometro));
  delay(5);
}



float leeRadiometro() {
  master.query( telegram ); // Envía la petición ModBus
  u8state = 1;
  n_mensaje=1;
  do {
    master.poll(); // Chequea la entrada de mensajes
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 1000; 
      Serial.println("mensaje leido completo ");
    }
  } while (u8state != 0);
  for(int i=0; i<16; i++){
    Serial.print("au16data" + String(i) + ": ");
    Serial.println(au16data[i]);
  }
  
  smartdelay(100);

  
  Serial.print("irradiancia (real): ");
  Serial.println(radiometro);
  Serial.println(String(radiometro));
  Serial.println("**********************************");
  return  (radiometro);
}



static void smartdelay(unsigned long ms)
{
  // Ubicamos el cursor en la primera posición(columna:0) de la segunda línea(fila:1)
  unsigned long start = millis();
  do
  {
    // Intentar recibir secuencia durante milisagundos ms
  } while (millis() - start < ms);
}

And i am using this converter:


those are different to the usuals, this don't include a DE pin, but they admit half-duplex communication

I will appreciate any advice here,
Victoria

The comment is correct, the implementation is wrong. Your au16reg field is not pointing to an array! (Hint: remove the [0]!)

And don't use the String class on AVR Arduinos!

BTW: What exactly do you think is smart in smartdelay()? It's definitely more stupid than calling delay().

okey, i've just correct the [0] thing but the code sill not working.

And don't use the String class on AVR Arduinos!

I don't know what you mean with that. Are you talking about the

Serial.println( "ID del maestro (arduino): " + String(ID));

line? or there is another issue i'm not seing? Anyway i just delete that line and all the others similar as they are not needed.

And, about the smartdelay() funtion, is a thing i have used in other proyect, to avoid the arduino to shut down all the parallel process while the delay() is working. Probably i don't need it here, but i don't have a clue where the error is, so i decided to use it anyway

I still thinking the problem migth be on the library i use, as the anwer seems to not be charge in au16data as it should. I put the link here.

How do you know? What exact device are you talking to?

You don't check for errors (master.getLastError()) but you should. If you get an error, what error is it?

I doubt that. I use the same library (slightly modified) in my projects and it works without a problem.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.