ModBus master semplice

Buonasera,
purtroppo questo ModBus non mi da tregua.
Dovrei realizzare un semplice ModBus Master, in grado di visualizzare un valore che arriva da uno slave.
Me ne basta solo uno il 400007 del Holding_Register (address 6).
Nulla di più.

Sto provando varie soluzioni ma nulla.

Ha disposizione questo Shield: Arduino RS422 RS485 Shield - Zihatec GmbH

Grazie.

Sono ad una svolta,

con questo codice riesco a comunicare con lo slave, però vorrei far accendere un led quando scrivo 1 sul registro 4000007 dallo slave

/*

  Basic.pde - example using ModbusMaster library

  Library:: ModbusMaster

  Author:: Doc Walker <4-20ma@wvfans.net>

  Copyright:: 2009-2016 Doc Walker

  Licensed under the Apache License, Version 2.0 (the "License");

  you may not use this file except in compliance with the License.

  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software

  distributed under the License is distributed on an "AS IS" BASIS,

  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  See the License for the specific language governing permissions and

  limitations under the License.

*/

#include <ModbusMaster.h>
#define  ledPin  9 // onboard led 

// instantiate ModbusMaster object

ModbusMaster node;

void setup()

{

  // use Serial (port 0); initialize Modbus communication baud rate

  Serial.begin(38400);

  // communicate with Modbus slave ID 2 over Serial (port 0)

  node.begin(1, Serial);

 // ledPin
 pinMode(ledPin, OUTPUT);

}

void loop()

{

  static uint32_t i;

  uint8_t j, result;

  uint16_t data[6];

  i++;

  // set word 0 of TX buffer to least-significant word of counter (bits 15..0)

  node.setTransmitBuffer(0, lowWord(i));

  // set word 1 of TX buffer to most-significant word of counter (bits 31..16)

  node.setTransmitBuffer(1, highWord(i));

  // slave: write TX buffer to (2) 16-bit registers starting at register 0

  result = node.writeMultipleRegisters(0, 2);

  // slave: read (6) 16-bit registers starting at register 2 to RX buffer

  result = node.readHoldingRegisters(2, 6);

  // do something with data if read is successful

  if (result == node.ku8MBSuccess)

  {

    for (j = 0; j < 6; j++)

    {

      data[j] = node.getResponseBuffer(j);
      

    }
      //digitalWrite(ledPin, HIGH);
  }

}

Qualche idea?

io non ho capito...ma arduino sarà slave o master? hai dato un occhio al pdf che ti ho allegato nell'altro thread? hai capito perchè non possono esistere registri oltre il 65536?...e che quindi parlare di registro 400007 o 4000007 non ha senso? il device esterno con cui ti connetterai cos'è?...un PLC, un PC (programma in C# o altro linguaggio), un qualche tipo di driver...altro? hai lo scambio dati di questo dispositivo esterno? (allegalo)

cmq...se non ricordo male quella libreria ti da 2 possibilità per comunicare...o ti costruisci/interpreti tu il buffer da inviare/ricevere (ma qua vuol dire conoscere il protocollo) oppure tramite enumerazione (come nell'esempio dell'altro thread) e polling del master/slave.

Ciao ORSO2001,

grazie per le risposte. Aggiungo qualche dettaglio, così almeno chiarisco la situazione, sperando di liberarmi di questa croce il più presto possibile e non rompere più.

Ho preso in mano questa cosa perché il collega che se ne occupa se ne è andato e devo finirlo io, che non ne capisco nulla a riguardo e non ho molto tempo (e purtroppo neanche più l'eta) per leggermi tutta la documentazione. Come detto, sviluppo tutta altra roba ed è la prima volta che mi imbatto nel "ModBus". C'è stato un misunderstanding tra cliente e fornitore ed il software ( si tratta di un applicazione su pc, apre una porta COM ed inizia a inviare dati) che devo testare in realtà è uno slave. (ti lascio immaginare le parolacce nella mia testa). L'Arduino dovrà fare quindi da Master e ci sono riuscito grazie allo stesso Shield ed alla libreria ModBusSlave che ho citato prima, vedo il polling continuo sui led TX ed RX dello shield e dell'adattaore, quindi ora si parlano. Sono riuscito a patteggiare che farò accendere 1 solo led al variare del valore di un registro. Nulla più. Parlo di registro 400007 perché è presente su un software che gli ho visto usare. Ho capito che si parla di HoldingRegister, se mi riferisco a quel valore.

Tutto qui, chiedo ancora scusa per l'argomento e la rottura di scatole.

ok...quindi arduino (master) dovrà verificare se uno specifico registro ha valore x o y o z per far accendere un LED. cioè per esempio...richiedo allo slave 1 il valore del registro 7 (quello che tu definisci 400007)...questo mi ritorna valore 1...accendo il LED...se ritorna valore 0 spengo il LED ....giusto? questa lettura deve avvenire in continuo?...al verificarsi di un evento (tasto premuto...altra verifica su altre cose)...altro?

Hai centrato perfettamente il requisito.

Questo avviene di continuo, nessun tasto da premere.

Grazie ancora!

non l’ho testato…prova e fammi sapere…dovrebbe gestire il LED della scheda…il DE ed RE del MAX485 vanno collegati al PIN 2 di arduino…diversamente cambia la #define in testa:

#define MAX485_RE_DE  2 //definisce il PIN per abilitare invio e ricezione...va connesso sia a DE che RE su MAX485

#include <ModbusMaster.h>

ModbusMaster node;

void preTransmission()
{
  digitalWrite(MAX485_RE_DE, HIGH);
}

void postTransmission()
{
  digitalWrite(MAX485_RE_DE, LOW);
}

void setup()
{
  Serial.begin(19200);
  pinMode(MAX485_RE_DE, OUTPUT);
  node.begin(1, Serial);
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}


void loop()
{
  // tra una richiesta e la successiva di solito va lasciato un po' di tempo allo slave di elaborare i propri dati
  delay(100);

  // variabili locali
  uint8_t result;
  uint16_t data;

  // richiede allo slave il valore del registro 7
  result = node.readHoldingRegisters(7, 1);

  // se la risposta dallo slave arriva entro il time out ad il CRC è positivo
  if (result == node.ku8MBSuccess)
  {
    // leggo il valore dell'indice 0 (un solo registro letto) della risposta
    data = node.getResponseBuffer(0);

    // qua vien da se...
    if (data == 1) {
      digitalWrite(LED_BUILTIN, HIGH);
    }
    else {
      digitalWrite(LED_BUILTIN, LOW);
    }
  }
}

Funziona perfettamente!!!
Non so davvero come ringraziarti!!!
Sei un vero eroe.
Mi hai salvato la vita