Hallo,
ich habe das ganze über TCP/IP mit dem Leonardo gemacht. Vieleicht hilft dir das ja weiter.
Code: Select all
#include <Wire.h>
#include <SPI.h>
#include <Ethernet2.h>
#include "MgsModbus.h"
#include "TimerOne.h"
#include <avr/wdt.h>
MgsModbus Mb;
// Ethernet settings (depending on MAC and Local network)
byte mac[] = { macadress eintragen };
IPAddress ip( deine IP Adresse vom Arduino );
void setup()
{
Serial.begin(9600);
Wire.begin(); // enable I2C port.
Ethernet.begin(mac, ip); // start etehrnet interface
Timer1.initialize(10 * 1000); // zeit in microsekunden (1 / 1 000 000) s
Timer1.attachInterrupt(mb);
wdt_enable(WDTO_8S); // Watchdog timer alle 8 s ohne timerreset wird das gerät neu gestartet
// Mb.SetBit(0,false);
Mb.MbData[0] = 0;
Mb.MbData[1] = 0;
Mb.MbData[2] = 0;
Mb.MbData[3] = 0;
Mb.MbData[4] = 0;
}
void mb() {
Mb.MbsRun();
Mb.MbData[0] = ***;
Mb.MbData[1] = ***;
Mb.MbData[2] = *** ;
Mb.MbData[3] = ***;
Mb.MbData[4] = ***;
}
void writeCommand(int addr ,char *cmd) {
ist nur ein auszug aus meinem Code
dazu noch die MgsModbus.ccp
Code: Select all
#include "MgsModbus.h"
// For Arduino 1.0
EthernetServer MbServer(MB_PORT);
EthernetClient MbmClient;
// #define DEBUG
MgsModbus::MgsModbus()
{
}
//****************** Send data for ModBusMaster ****************
void MgsModbus::Req(MB_FC FC, word Ref, word Count, word Pos)
{
MbmFC = FC;
byte ServerIp[] = {192,168,178,10};
MbmByteArray[0] = 0; // ID high byte
MbmByteArray[1] = 1; // ID low byte
MbmByteArray[2] = 0; // protocol high byte
MbmByteArray[3] = 0; // protocol low byte
MbmByteArray[5] = 6; // Lenght low byte;
MbmByteArray[4] = 0; // Lenght high byte
MbmByteArray[6] = 1; // unit ID
MbmByteArray[7] = FC; // function code
MbmByteArray[8] = highByte(Ref);
MbmByteArray[9] = lowByte(Ref);
//****************** Read Coils (1) & Read Input discretes (2) **********************
if(FC == MB_FC_READ_COILS || FC == MB_FC_READ_DISCRETE_INPUT) {
if (Count < 1) {Count = 1;}
if (Count > 125) {Count = 1000;}
MbmByteArray[10] = highByte(Count);
MbmByteArray[11] = lowByte(Count);
}
//****************** Read Registers (3) & Read Input registers (4) ******************
if(FC == MB_FC_READ_REGISTERS || FC == MB_FC_READ_INPUT_REGISTER) {
if (Count < 1) {Count = 1;}
if (Count > 125) {Count = 125;}
MbmByteArray[10] = highByte(Count);
MbmByteArray[11] = lowByte(Count);
}
//****************** Write Coil (5) **********************
if(MbmFC == MB_FC_WRITE_COIL) {
if (GetBit(Pos)) {MbmByteArray[10] = 0xFF;} else {MbmByteArray[10] = 0;} // 0xFF coil on 0x00 coil off
MbmByteArray[11] = 0; // always zero
}
//****************** Write Register (6) ******************
if(MbmFC == MB_FC_WRITE_REGISTER) {
MbmByteArray[10] = highByte(MbData[Pos]);
MbmByteArray[11] = lowByte(MbData[Pos]);
}
//****************** Write Multiple Coils (15) **********************
// not fuly tested
if(MbmFC == MB_FC_WRITE_MULTIPLE_COILS) {
if (Count < 1) {Count = 1;}
if (Count > 800) {Count = 800;}
MbmByteArray[10] = highByte(Count);
MbmByteArray[11] = lowByte(Count);
MbmByteArray[12] = (Count + 7) /8;
MbmByteArray[4] = highByte(MbmByteArray[12] + 7); // Lenght high byte
MbmByteArray[5] = lowByte(MbmByteArray[12] + 7); // Lenght low byte;
for (int i=0; i<Count; i++) {
bitWrite(MbmByteArray[13+(i/8)],i-((i/8)*8),GetBit(Pos+i));
}
}
//****************** Write Multiple Registers (16) ******************
if(MbmFC == MB_FC_WRITE_MULTIPLE_REGISTERS) {
if (Count < 1) {Count = 1;}
if (Count > 100) {Count = 100;}
MbmByteArray[10] = highByte(Count);
MbmByteArray[11] = lowByte(Count);
MbmByteArray[12] = (Count*2);
MbmByteArray[4] = highByte(MbmByteArray[12] + 7); // Lenght high byte
MbmByteArray[5] = lowByte(MbmByteArray[12] + 7); // Lenght low byte;
for (int i=0; i<Count;i++) {
MbmByteArray[(i*2)+13] = highByte (MbData[Pos + i]);
MbmByteArray[(i*2)+14] = lowByte (MbData[Pos + i]);
}
}
//****************** ?? ******************
if (MbmClient.connect(ServerIp,502)) {
#ifdef DEBUG
Serial.println("connected with modbus slave");
Serial.print("Master request: ");
for(int i=0;i<MbmByteArray[5]+6;i++) {
if(MbmByteArray[i] < 16){Serial.print("0");}
Serial.print(MbmByteArray[i],HEX);
if (i != MbmByteArray[5]+5) {Serial.print(".");} else {Serial.println();}
}
#endif
for(int i=0;i<MbmByteArray[5]+6;i++) {
MbmClient.write(MbmByteArray[i]);
}
MbmCounter = 0;
MbmByteArray[7] = 0;
MbmPos = Pos;
MbmBitCount = Count;
} else {
#ifdef DEBUG
Serial.println("connection with modbus master failed");
#endif
MbmClient.stop();
}
}
//****************** Recieve data for ModBusMaster ****************
void MgsModbus::MbmRun()
{
//****************** Read from socket ****************
while (MbmClient.available()) {
MbmByteArray[MbmCounter] = MbmClient.read();
if (MbmCounter > 4) {
if (MbmCounter == MbmByteArray[5] + 5) { // the full answer is recieved
MbmClient.stop();
MbmProcess();
#ifdef DEBUG
Serial.println("recieve klaar");
#endif
}
}
MbmCounter++;
}
}
void MgsModbus::MbmProcess()
{
MbmFC = SetFC(int (MbmByteArray[7]));
#ifdef DEBUG
for (int i=0;i<MbmByteArray[5]+6;i++) {
if(MbmByteArray[i] < 16) {Serial.print("0");}
Serial.print(MbmByteArray[i],HEX);
if (i != MbmByteArray[5]+5) {Serial.print(".");
} else {Serial.println();}
}
#endif
//****************** Read Coils (1) & Read Input discretes (2) **********************
if(MbmFC == MB_FC_READ_COILS || MbmFC == MB_FC_READ_DISCRETE_INPUT) {
word Count = MbmByteArray[8] * 8;
if (MbmBitCount < Count) {
Count = MbmBitCount;
}
for (int i=0;i<Count;i++) {
if (i + MbmPos < MbDataLen * 16) {
SetBit(i + MbmPos,bitRead(MbmByteArray[(i/8)+9],i-((i/8)*8)));
}
}
}
//****************** Read Registers (3) & Read Input registers (4) ******************
if(MbmFC == MB_FC_READ_REGISTERS || MbmFC == MB_FC_READ_INPUT_REGISTER) {
word Pos = MbmPos;
for (int i=0;i<MbmByteArray[8];i=i+2) {
if (Pos < MbDataLen) {
MbData[Pos] = (MbmByteArray[i+9] * 0x100) + MbmByteArray[i+1+9];
Pos++;
}
}
}
//****************** Write Coil (5) **********************
if(MbmFC == MB_FC_WRITE_COIL){
}
//****************** Write Register (6) ******************
if(MbmFC == MB_FC_WRITE_REGISTER){
}
//****************** Write Multiple Coils (15) **********************
if(MbmFC == MB_FC_WRITE_MULTIPLE_COILS){
}
//****************** Write Multiple Registers (16) ******************
if(MbmFC == MB_FC_WRITE_MULTIPLE_REGISTERS){
}
}
//****************** Recieve data for ModBusSlave ****************
void MgsModbus::MbsRun()
{
//****************** Read from socket ****************
EthernetClient client = MbServer.available();
if(client.available())
{
delay(10);
int i = 0;
while(client.available())
{
MbsByteArray[i] = client.read();
i++;
}
MbsFC = SetFC(MbsByteArray[7]); //Byte 7 of request is FC
}
int Start, WordDataLength, ByteDataLength, CoilDataLength, MessageLength;
//****************** Read Coils (1 & 2) **********************
if(MbsFC == MB_FC_READ_COILS || MbsFC == MB_FC_READ_DISCRETE_INPUT) {
Start = word(MbsByteArray[8],MbsByteArray[9]);
CoilDataLength = word(MbsByteArray[10],MbsByteArray[11]);
ByteDataLength = CoilDataLength / 8;
if(ByteDataLength * 8 < CoilDataLength) ByteDataLength++;
CoilDataLength = ByteDataLength * 8;
MbsByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
MbsByteArray[8] = ByteDataLength; //Number of bytes after this one (or number of bytes of data).
for(int i = 0; i < ByteDataLength ; i++)
{
MbsByteArray[9 + i] = 0; // To get all remaining not written bits zero
for(int j = 0; j < 8; j++)
{
bitWrite(MbsByteArray[9 + i], j, GetBit(Start + i * 8 + j));
}
}
MessageLength = ByteDataLength + 9;
client.write(MbsByteArray, MessageLength);
MbsFC = MB_FC_NONE;
}
//****************** Read Registers (3 & 4) ******************
if(MbsFC == MB_FC_READ_REGISTERS || MbsFC == MB_FC_READ_INPUT_REGISTER) {
Start = word(MbsByteArray[8],MbsByteArray[9]);
WordDataLength = word(MbsByteArray[10],MbsByteArray[11]);
ByteDataLength = WordDataLength * 2;
MbsByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
MbsByteArray[8] = ByteDataLength; //Number of bytes after this one (or number of bytes of data).
for(int i = 0; i < WordDataLength; i++)
{
MbsByteArray[ 9 + i * 2] = highByte(MbData[Start + i]);
MbsByteArray[10 + i * 2] = lowByte(MbData[Start + i]);
}
MessageLength = ByteDataLength + 9;
client.write(MbsByteArray, MessageLength);
MbsFC = MB_FC_NONE;
}
//****************** Write Coil (5) **********************
if(MbsFC == MB_FC_WRITE_COIL) {
Start = word(MbsByteArray[8],MbsByteArray[9]);
if (word(MbsByteArray[10],MbsByteArray[11]) == 0xFF00){SetBit(Start,true);}
if (word(MbsByteArray[10],MbsByteArray[11]) == 0x0000){SetBit(Start,false);}
MbsByteArray[5] = 2; //Number of bytes after this one.
MessageLength = 8;
client.write(MbsByteArray, MessageLength);
MbsFC = MB_FC_NONE;
}
//****************** Write Register (6) ******************
if(MbsFC == MB_FC_WRITE_REGISTER) {
Start = word(MbsByteArray[8],MbsByteArray[9]);
MbData[Start] = word(MbsByteArray[10],MbsByteArray[11]);
MbsByteArray[5] = 6; //Number of bytes after this one.
MessageLength = 12;
client.write(MbsByteArray, MessageLength);
MbsFC = MB_FC_NONE;
}
//****************** Write Multiple Coils (15) **********************
if(MbsFC == MB_FC_WRITE_MULTIPLE_COILS) {
Start = word(MbsByteArray[8],MbsByteArray[9]);
CoilDataLength = word(MbsByteArray[10],MbsByteArray[11]);
MbsByteArray[5] = 6;
for(int i = 0; i < CoilDataLength; i++)
{
SetBit(Start + i,bitRead(MbsByteArray[13 + (i/8)],i-((i/8)*8)));
}
MessageLength = 12;
client.write(MbsByteArray, MessageLength);
MbsFC = MB_FC_NONE;
}
//****************** Write Multiple Registers (16) ******************
if(MbsFC == MB_FC_WRITE_MULTIPLE_REGISTERS) {
Start = word(MbsByteArray[8],MbsByteArray[9]);
WordDataLength = word(MbsByteArray[10],MbsByteArray[11]);
ByteDataLength = WordDataLength * 2;
MbsByteArray[5] = 6;
for(int i = 0; i < WordDataLength; i++)
{
MbData[Start + i] = word(MbsByteArray[ 13 + i * 2],MbsByteArray[14 + i * 2]);
}
MessageLength = 12;
client.write(MbsByteArray, MessageLength);
MbsFC = MB_FC_NONE;
}
}
//****************** ?? ******************
MB_FC MgsModbus::SetFC(int fc)
{
MB_FC FC;
FC = MB_FC_NONE;
if(fc == 1) FC = MB_FC_READ_COILS;
if(fc == 2) FC = MB_FC_READ_DISCRETE_INPUT;
if(fc == 3) FC = MB_FC_READ_REGISTERS;
if(fc == 4) FC = MB_FC_READ_INPUT_REGISTER;
if(fc == 5) FC = MB_FC_WRITE_COIL;
if(fc == 6) FC = MB_FC_WRITE_REGISTER;
if(fc == 15) FC = MB_FC_WRITE_MULTIPLE_COILS;
if(fc == 16) FC = MB_FC_WRITE_MULTIPLE_REGISTERS;
return FC;
}
word MgsModbus::GetDataLen()
{
return MbDataLen;
}
boolean MgsModbus::GetBit(word Number)
{
int ArrayPos = Number / 16;
int BitPos = Number - ArrayPos * 16;
boolean Tmp = bitRead(MbData[ArrayPos],BitPos);
return Tmp;
}
boolean MgsModbus::SetBit(word Number,boolean Data)
{
int ArrayPos = Number / 16;
int BitPos = Number - ArrayPos * 16;
boolean Overrun = ArrayPos > MbDataLen * 16; // check for data overrun
if (!Overrun){
bitWrite(MbData[ArrayPos],BitPos,Data);
}
return Overrun;
}
und MgsModbus.h
Code: Select all
/*
MgsModbus.h - an Arduino library for a Modbus TCP master and slave.
V-0.1.1 Copyright (C) 2013 Marco Gerritse
written and tested with Arduino 1.0
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
For this library the following library is used as start point:
[1] Mudbus.h - an Arduino library for a Modbus TCP slave.
Copyright (C) 2011 Dee Wykoff
[2] Function codes 15 & 16 by Martin Pettersson
The following references are used to write this library:
[3] Open Modbus/Tcp specification, Release 1.0, 29 March 1999
By Andy Swales, Schneider Electric
[4] Modbus application protocol specification V1.1b3, 26 april 202
From http:/www.modbus.org
External software used for testing:
[5] modpoll - www.modbusdriver.com/modpoll.html
[6] ananas - www.tuomio.fi/ananas
[7] mod_rssim - www.plcsimulator.org
[8] modbus master - www.cableone.net/mblansett/
This library use a single block of memory for all modbus data (mbData[] array). The
same data can be reached via several modbus functions, either via a 16 bit access
or via an access bit. The length of MbData must at least 1.
For the master the following modbus functions are implemented: 1, 2, 3, 4, 5, 6, 15, 16
For the slave the following modbus functions are implemented: 1, 2, 3, 4, 5, 6, 15, 16
The internal and external addresses are 0 (zero) based
V-0.1.1 2013-06-02
bugfix
V-0.1.0 2013-03-02
initinal version
*/
#include "Arduino.h"
#include <SPI.h>
#include <Ethernet2.h>
#ifndef MgsModbus_h
#define MgsModbus_h
#define MbDataLen 30 // length of the MdData array
#define MB_PORT 502
enum MB_FC {
MB_FC_NONE = 0,
MB_FC_READ_COILS = 1,
MB_FC_READ_DISCRETE_INPUT = 2,
MB_FC_READ_REGISTERS = 3,
MB_FC_READ_INPUT_REGISTER = 4,
MB_FC_WRITE_COIL = 5,
MB_FC_WRITE_REGISTER = 6,
MB_FC_WRITE_MULTIPLE_COILS = 15,
MB_FC_WRITE_MULTIPLE_REGISTERS = 16
};
class MgsModbus
{
public:
// general
MgsModbus();
word MbData[MbDataLen]; // memory block that holds all the modbus user data
boolean GetBit(word Number);
boolean SetBit(word Number,boolean Data); // returns true when the number is in the MbData range
// modbus master
void Req(MB_FC FC, word Ref, word Count, word Pos);
void MbmRun();
IPAddress remSlaveIP;
// modbus slave
void MbsRun();
word GetDataLen();
private:
// general
MB_FC SetFC(int fc);
// modbus master
uint8_t MbmByteArray[260]; // send and recieve buffer
MB_FC MbmFC;
int MbmCounter;
void MbmProcess();
word MbmPos;
word MbmBitCount;
//modbus slave
uint8_t MbsByteArray[260]; // send and recieve buffer
MB_FC MbsFC;
};
#endif