Arduino Modbus 讀取與寫入範例

Arduino Modbus 讀取與寫入範例

讀取多個並寫入多個

#include <ModbusRtu.h>


/// oled debuging

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);


///  

uint16_t au16data[32]; //!< data array for modbus network sharing  Array
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query

/**
 *  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
 */
Modbus master(0,0,7); // this is master and RS-232 or USB-FTDI  ///  7 = PIN ENEABLE rs485

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

unsigned long u32wait;



void setup() {

  // initialize with the I2C addr 0x3C / mit I2C-Adresse 0x3c initialisieren
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  delay(2000);
  display.clearDisplay();
  display.setTextSize(0.5);
  display.setTextColor(INVERSE); 

  //////////////////////////////
    
  // telegram 0: read registers
  telegram[0].u8id = 1;                 // slave address
  telegram[0].u8fct = 3;                // function code (registers read multiple  3) 
  telegram[0].u16RegAdd = 0;            // start address in slave -  direccion de Inicio 0
  telegram[0].u16CoilsNo = 10;          // number of elements (coils or registers) to read  0 - 16 
  telegram[0].au16reg = au16data;       // pointer to a memory array in the Arduino - Almacenamiento en Array de memoria de arduino

  // telegram 1: write a multiple  register = function 16
  telegram[1].u8id = 1;                 // slave address
  telegram[1].u8fct = 16;               // function code (write multiple registers 16 )
  telegram[1].u16RegAdd = 10;           // start address in slave  -  direccion de Inicio 10
  telegram[1].u16CoilsNo = 10;          // number of elements (coils or registers) to read
  telegram[1].au16reg = au16data+10;    // pointer to a memory array in the Arduino - Almacenamiento en Array de memoria de arduino 10 posiciones despues

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

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1: 
    master.query( telegram[u8query] ); // send query (only once)
    u8state++;
 u8query++;
 if (u8query > 2) u8query = 0;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 1000; 
    }
    break;
  }
  
   display.clearDisplay();

  //Read Multiple Holding Register  - Lectura de multiples registros 
   
   display.setCursor(0,0); 
   display.print(au16data[0]);    // Read Holding Register [0]
   display.print(",");    
   display.print(au16data[1]);    // Read Holding Register [1]
   display.print(",");    
   display.print(au16data[2]);    // Read Holding Register [2]
   display.print(","); 
   display.print(au16data[3]);    // Read Holding Register [3]
   display.print(",");     
   display.print(au16data[4]);    // Read Holding Register [4]
   display.print(" Hold 0-4");
   
   display.setCursor(0,8);  
   display.print(au16data[5]);   // Read Holding Register [5]
   display.print(",");     
   display.print(au16data[6]);   // Read Holding Register [6]
   display.print(",");   
   display.print(au16data[7]);   // Read Holding Register [7]
   display.print(",");   
   display.print(au16data[8]);   // Read Holding Register [8]
   display.print(",");    
   display.print(au16data[9]);   // Read Holding Register [9]
   display.print(" Hold 5-9");



     
  //Write Multiple Holding Register  - Escritura de multiples registros 

   au16data[10] = analogRead( 0 ); // Write Holding Register [10]
   
   au16data[11] = analogRead( 0 ); // Write Holding Register [11]
   
   au16data[12] = analogRead( 0 ); // Write Holding Register [12]
   
   au16data[13] = analogRead( 0 ); // Write Holding Register [13]
   
   au16data[14] = analogRead( 0 ); // Write Holding Register [14]
   
   au16data[15] = analogRead( 0 ); // Write Holding Register [15]
   
   au16data[16] = analogRead( 0 ); // Write Holding Register [16]
   
   au16data[17] = analogRead( 0 ); // Write Holding Register [17]
   
   au16data[18] = analogRead( 0 ); // Write Holding Register [18]
      
   au16data[19] = analogRead( 0 ); // Write Holding Register [19]
   

// Print Oled Write Holding Register 
   
   display.setCursor(0,16); 
   display.print(au16data[10]);    
   display.print(",");    
   display.print(au16data[11]);
   display.print(",");    
   display.print(au16data[12]);    
   display.print(","); 
   display.print(au16data[13]);    
   display.print(",");     
   display.print(au16data[14]);
   display.print(",");    
   display.print(au16data[15]);    
   display.print(",");    
   display.print(au16data[16]);
   display.print(",");    
   display.print(au16data[17]);    
   display.print(","); 
   display.print(au16data[18]);    
   display.print(",");     
   display.print(au16data[19]);
   display.print(" Hold 10-19");
   
   
   display.display();  
              
 


  
}

 

讀取單個並寫入單個

/**
 *  Modbus master example 2:
 *  The purpose of this example is to query an array of data
 *  from an external Modbus slave device.
 *  This example is similar to "simple_master", but this example
 *  allows you to use software serial instead of hardware serial
 *  in case that you want to use D1 & D2 for other purposes.
 *  The link media can be USB or RS232.
 
  The circuit:
 * software serial rx(D3) connect to tx pin of another device
 * software serial tx(D4) connect to rx pin of another device
 
 * In this example, we will use two important methods so that we can use
 * software serial.
 *
 * 1. Modbus::Modbus(uint8_t u8id)
 * This is a constructor for a Master/Slave through USB/RS232C via software serial
 * This constructor only specifies u8id (node address) and should be only
 * used if you want to use software serial instead of hardware serial.
 * This method is called if you create a ModBus object with only on parameter "u8id"
 * u8id is the node address of the arduino that will be programmed on,
 * 0 for master and 1..247 for slave
 * for example: Modbus master(0); 
 * If you use this constructor you have to begin ModBus object by
 * using "void Modbus::begin(SoftwareSerial *softPort, long u32speed)".
 * 
 * 2. void Modbus::begin(SoftwareSerial *sPort, long u32speed)
 * Initialize class object.
 * This is the method you have to use if you construct the ModBus object by using 
 * Modbus::Modbus(uint8_t u8id) in order to use software serial and to avoid problems.
 * You have to create a SoftwareSerial object on your own, as shown in the example.
 * sPort is a pointer to your SoftwareSerial object, u32speed is the baud rate, in 
 * standard increments (300..115200)

 created long time ago
 by smarmengol
 modified 29 July 2016
 by Helium6072

 This example code is in the public domain.
 */

#include <ModbusRtu.h>
#include <SoftwareSerial.h>

uint16_t au16data[16]; //!< data array for modbus network sharing
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query

/**
 *  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
 */
Modbus master(0); // this is master and RS-232 or USB-FTDI via software serial

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

unsigned long u32wait;

SoftwareSerial mySerial(12, 13);//Create a SoftwareSerial object so that we can use software serial. Search "software serial" on Arduino.cc to find out more details.

void setup() {
  Serial.begin(9600);//use the hardware serial if you want to connect to your computer via usb cable, etc.
  master.begin( &mySerial, 38400 ); // begin the ModBus object. The first parameter is the address of your SoftwareSerial address. Do not forget the "&". 9600 means baud-rate at 9600
 // telegram 0: read registers
  telegram[0].u8id = 1; // slave address
  telegram[0].u8fct = 3; // function code (this one is registers read)
  telegram[0].u16RegAdd = 1; // start address in slave
  telegram[0].u16CoilsNo = 3; // number of elements (coils or registers) to read
  telegram[0].au16reg = au16data; // pointer to a memory array in the Arduino

  // telegram 1: write a single register
  telegram[1].u8id = 1; // slave address
  telegram[1].u8fct = 6; // function code (this one is write a single register)
  telegram[1].u16RegAdd = 6; // start address in slave
  telegram[1].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[1].au16reg = au16data+4; // pointer to a memory array in the Arduino
  
  master.setTimeOut( 2000 ); // if there is no answer in 5000 ms, roll over
  u32wait = millis() + 1000;
  u8state = u8query = 0; 
}

void loop() {
 switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1: 
    master.query( telegram[u8query] ); // send query (only once)
    u8state++;
  u8query++;
  if (u8query > 2) u8query = 0;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 300; 
      Serial.println(au16data[0]);
      Serial.println(au16data[1]);
      Serial.println(au16data[2]);
    }
    
    break;
  }

  au16data[4] = random(1000);
}