[modbus] Test arduino modbus slave.

Hola a todos,

Estoy aqui porque no sé que pasa he comprobado la conexión, los parámetros de la comunicación serie y todo parece estar correcto, ayer si ves que pasa.

Les pongo en situación:

Estoy implementando un modbus clave en arduino mediante la librería SimpleModbusSlave.h
-> link : EWC2013-Greenhouse-demo/Arduino/libraries/SimpleModbusSlave at master · thibs0/EWC2013-Greenhouse-demo · GitHub

he configurado el serial de mi mega para que utilize el 1 y así dejar Serial0 para debug donde tengo los mensajes de depuración.
Código

#include <SimpleModbusSlave.h>

/* 
   SimpleModbusSlaveV10 supports function 3, 6 & 16.
   
   This example code will receive the adc ch0 value from the arduino master. 
   It will then use this value to adjust the brightness of the led on pin 9.
   The value received from the master will be stored in address 1 in its own
   address space namely holdingRegs[].
   
   In addition to this the slaves own adc ch0 value will be stored in 
   address 0 in its own address space holdingRegs[] for the master to
   be read. The master will use this value to alter the brightness of its
   own led connected to pin 9.
   
   The modbus_update() method updates the holdingRegs register array and checks
   communication.

   Note:  
   The Arduino serial ring buffer is 64 bytes or 32 registers.
   Most of the time you will connect the arduino to a master via serial
   using a MAX485 or similar.
 
   In a function 3 request the master will attempt to read from your
   slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
   and two BYTES CRC the master can only request 58 bytes or 29 registers.
 
   In a function 16 request the master will attempt to write to your 
   slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS, 
   NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
   54 bytes or 27 registers.
 
   Using a USB to Serial converter the maximum bytes you can send is 
   limited to its internal buffer which differs between manufactures. 
*/

#define  LED_PIN 2  
#define  POTENCIOMETRO_PIN A0

// Using the enum instruction allows for an easy method for adding and 
// removing registers. Doing it this way saves you #defining the size 
// of your slaves register array each time you want to add more registers
// and at a glimpse informs you of your slaves register layout.

//////////////// registers of your slave ///////////////////
enum 
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  ADC_VAL = 1000,     
  PWM_VAL,        
  HOLDING_REGS_SIZE  = ADC_VAL + 4// leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
const unsigned char SLAVE_ID = 10;
////////////////////////////////////////////////////////////
int value;
void setup()
{
  /* parameters(HardwareSerial* SerialPort,
                long baudrate, 
		unsigned char byteFormat,
                unsigned char ID, 
                unsigned char transmit enable pin, 
                unsigned int holding registers size,
                unsigned int* holding register array)
  */
  
  /* Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
     
     You can obviously use SERIAL_8N1 but this does not adhere to the
     Modbus specifications. That said, I have tested the SERIAL_8N1 option 
     on various commercial masters and slaves that were suppose to adhere
     to this specification and was always able to communicate... Go figure.
     
     These byte formats are already defined in the Arduino global name space. 
  */
	
  modbus_configure(&Serial1, 9600, SERIAL_8N2, SLAVE_ID, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, SERIAL_8N2, SLAVE_ID);

  pinMode(POTENCIOMETRO_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
  
  modbus_update();
  
  holdingRegs[ADC_VAL] = analogRead(POTENCIOMETRO_PIN); // update data to be read by the master to adjust the PWM
  Serial.print("##> holdingRegs[ADC_VAL]: ");
  Serial.println(holdingRegs[ADC_VAL]);
  
  value   = map(holdingRegs[ADC_VAL], 0, 1023, 0, 254); 
  
  //delay(800);
  
  //Serial.print("&&> Valor Led: ");
  //Serial.println(value);
  
  analogWrite(LED_PIN, value);
  //delay(800);

  //Serial.print("##> holdingRegs[PWM_VAL]: ");
  //Serial.println(holdingRegs[PWM_VAL]>>2);

  //delay(800);
  
  //Serial.print("PWM_VAL = ");
  //Serial.println(PWM_VAL);
  
  Serial.print("ADC_VAL = ");
  Serial.println(ADC_VAL);

  delay(800);
  //analogWrite(LED, holdingRegs[PWM_VAL]>>2); // constrain adc value from the arduino master to 255
  
  /* Note:
     The use of the enum instruction is not needed. You could set a maximum allowable
     size for holdinRegs[] by defining HOLDING_REGS_SIZE using a constant and then access 
     holdingRegs[] by "Index" addressing. 
     I.e.
     holdingRegs[0] = analogRead(A0);
     analogWrite(LED, holdingRegs[1]/4);
  */
  
}

He conectado el TX1 a RX del usb y RX1 al TX usb del ordenar.Y mediante el programa modpoll master para testear la conexión con el arduino.

modpoll -> Free Modbus Master Simulator and Test Tool

modpoll -m rtu -a 10 -r 1000 -c 1 -t 3:hex -b 9600 -d 8 -s 2 -p none COM3

y lo único que consigo es lo siguiente:

Copyright (c) 2002-2013 proconX Pty Ltd

Visit http://www.modbusdriver.com for Modbus libraries and tools.

Protocol configuration: Modbus RTU

Slave configuration...: address = 10, start reference = 100, count = 1

Communication.........: COM3, 9600, 8, 2, none, t/o 1.00 s, poll rate 1000 ms

Data type.............: 16-bit register (hex), input register table

-- Polling slave... (Ctrl-C to stop)

Reply time-out!

-- Polling slave... (Ctrl-C to stop)

Reply time-out!

-- Polling slave... (Ctrl-C to stop)

Reply time-out!

-- Polling slave... (Ctrl-C to stop)

Mi pregunta es la configuración serial del arduino y la del comando modpoll es correcta?
modpoll -> 9600, 8, 2stop, none

Alomejor estoy accediendo incorrectamente al stock de modbus?

Y que puedes contarnos de las interfaces 485. COmo estan hechas o las compraste?

la interfaz usb-serial es la MK20 USB Board -> link

a esa conecto el Tx con el RX1 arduino y viceversa.

El único fallo que veo en el código es el siguiente:

#define  LED_PIN 2

Y lo usas también en:

modbus_configure(&Serial1, 9600, SERIAL_8N2, SLAVE_ID, 2, HOLDING_REGS_SIZE, holdingRegs);

Usas el pin dos para dos cosas diferentes en el mismo sketch. No sé hasta que punto puede llegar a fallar con ese conflicto. La pregunta es: ¿te funciona el monitor serial?

¿Esa placita los niveles que saca son compatibles TTL con los de arduino? En teoria no hace falta usar el bus rs485 para enviar/recibir datos, simplemente que los niveles lógicos entre unos y otros sean compatibles.

Te recomiendo que uses el programa MTESTER para ver trabajar con el protocolo.

Y de paso descargate una versión mas moderna de la libreria (esa es del 2013, y la ultima del 2014), te paso el link oficial del autor: enlace

Y como consejo, empieza mandando algun caracter que otro, olvida el modbus. Si consigues mandar y recibir caracteres, entonces piensa en el modbus.

muchas Gracias por contestar, la verdad, llevas toda la razón Victorjam que los pines estoy utilizando son iguales para el led y para lo que entiendo como señalización de transmitir del modbus.

Yo pensaba que con con conectar los RXs y TXs cruzados ya tendría una comunicación seríal pero veo que no.

EL pin de señalización del modbus, llamado TxEnablePin donde lo tengo que conectar al CTS del otro puerto serie??

Estas uando esto no?

Description

BLE Nano is the smallest Bluetooth 4.1 Low Energy (BLE) development board in the market. The core is Nordic nRF51822 (an ARM Cortex-M0 SoC plus BLE capability) running at 16MHz with ultra low power consumption.
Developing a Bluetooth Smart enabled 'appcessory' (accessory device + companion application) is easier than ever. You can quickly produce protypes and demos target for Internet of Things (IoT) and other interesting projects. BLE Nano could operate under 1.8V to 3.3V, therefore it works with a lot of electronic components.

Si es asi esa librería creo que no te funcionará porque no tienes ningún pin TXEnablePin para comandar.
Sigue este consejo de PeterKanTropus que hizo un tutorial paa comunicar Modbus Slave por USB
Es mas, te responde a ti, no lo probaste en su momento?

Coincido, la libreria que estas usando no esta muy documentada, pero tiene todo el aspecto de haber sido diseñada para utilizar RS485 con control de flujo por un pin extra. No creo que se pueda utilizar sobre serial TTL sin modificarla.

Saludos.

Hola a todos y gracias por las respuestas.

os comento que he conseguido que funcione, efectivamente estoy usando eso de manera muy sencilla.

Os hago un breve resumen.
con el código dejado n post arriba sirve lo único que hay que cambiar el pin 2 de la función init para asignarlo a atro pin.

En concreto el código de arriba funcionando en el mega, y con un monitor para el debug Serial y Serial1 para el modbus.
Conectando el Serial1 tx del mega al rx del MK20 USB Board y el Rx del mega al TX del MK20 USB Board tenemos una comunicación serie en toda regla.

Yo la probe haciendo un sketch en Arduino para transmitir una A al ordenador, ya que el MK20 USB Board me hace de Uart con el pc.

Una vez que tenia comprobada la conexión como me aconsejo Victorjam. Ejecuté el modpoll por consola y empezé a recibir excepciones del modbus.

una vez supe atajarlas, unas eran porque no leia el corrector valor de la pila de registros otras porque no leia el tipo de registro que tenia el exclavo, todo funciono correctamente.

Es decir ahora se que un mega funcionando como esclavo funciona correctamente ahora tengo que implementar el modbus maestro en el BLE nano y conectarlo ambos.

PD: poco a poco va saliendo, sobre todo con vuestra ayuda :slight_smile: saludos.