Machsupport Forum
Mach Discussion => Mach4 General Discussion => Topic started by: tgirard on December 13, 2015, 11:58:13 AM
-
I have a need to be able to do certain tasks with arduino and Modbus and have tried to put together a system. I can make a connection but I continually get a Illegal Data Address error when trying to poll for data in the holding registers.
Setup:
Arduino Unu R3
Arduino Ethernet2 board
Mach4
Ethernet2 library from arduino.org
Andre Sarmentos ModbuisIP Library https://github.com/andresarmento/modbus-arduino
Pic1 shows Mach4 with two Modbus setups, modbus0 is connected to the MODBUS Simulator
modbus1 is connected to the arduino through TCP 192.168.1.120
Note, modbus1 has no functions assigned, it's just connecting
Stay with me here...
Here is the arduino code that is simply checking 5 A-D floating inputs and sending that data across the Modbus in registers 40011 through 40015:
read the comments in the code:
/*
Modbus-Arduino Example - TempSensor (Modbus IP)
Copyright by André Sarmento Barbosa
http://github.com/andresarmento/modbus-arduino
*/
#include <SPI.h>
#include <Ethernet2.h>
#include <Modbus.h>
#include <ModbusIP.h>
//Modbus Registers Offsets (0-9999)
const int reg1 = 40011; //Setup the holding register numbers to use
const int reg2 = 40012;
const int reg3 = 40013;
const int reg4 = 40014;
const int reg5 = 40015;
//Used Pins
const int sensorPin1 = A0; //setup the A-d
const int sensorPin2 = A1;
const int sensorPin3 = A2;
const int sensorPin4 = A3;
const int sensorPin5 = A4;
//Instanciate the ModbusIP object
ModbusIP mb;
long ts;
void setup() {
Serial.begin(9600);
// The media access control (ethernet hardware) address for the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// The IP address for the shield
byte ip[] = { 192, 168, 1, 120 };
//Config Modbus IP
mb.config(mac, ip);
mb.addHreg(reg1);//Create the registers based on the values above
mb.addHreg(reg2);
mb.addHreg(reg3);
mb.addHreg(reg4);
mb.addHreg(reg5);
ts = millis();
}
void loop() {
//Call once inside loop() - all magic here
mb.task();
//Read each two seconds
if (millis() > ts + 1000) {
ts = millis();
//Setting raw value (0-1024)
mb.Hreg(reg1, analogRead(sensorPin1));//Send the A-D values through Modbus
mb.Hreg(reg2, analogRead(sensorPin2));
mb.Hreg(reg3, analogRead(sensorPin3));
mb.Hreg(reg4, analogRead(sensorPin4));
mb.Hreg(reg5, analogRead(sensorPin5));
Serial.println(mb.Hreg(reg1));
}
}//END
This code seems to work fine and when I run it and connect to it with a Modbus Master other than Mach4 I see the data
(I couldn't upload more than 4 pics but it ran fine)
I then create the function for modbus1 in Mach4 (pic3)
It is exactly the same as the other read function in modbus0(pic4) except I start at 40011 and only use 5 registers
The result (pic5) is modbus1 throws a Illegal Data Address error. This means that The data address received in the query is not an allowable address for the slave. More specifically, the combination of reference number and transfer length is invalid.
http://www.simplymodbus.ca/exceptions.htm
I've tried changing the starting number in Mach to 0 and to 2 with no luck. Any ideas?
I think this would be a really good thing to be able to do and would allow for easy and fast connectivity to the arduino.
I really don't want to use serial but I will if I have to.
Let me know if you have any ideas or if you have any questions
Thanks
-Tim
-
It wouldn't let me post the pics the first time :)
-
I got it figured out for anyone whos interested.
When Setting up the registers on the arduino, You only specifiy the register position number like this:
//Modbus Registers Offsets (0-9999)
const int reg1 = 0;
const int reg2 = 1;
const int reg3 = 2;
const int reg4 = 3;
const int reg5 = 4;
That's because Andre adds 40001 in the Modbus Arduino library to this number to give your final number. The software is Base0 where Mach is Base1. So in Mach you use 1 through 5. I'm watching the arduino update some DROs on my screens without any problems. This is really cool as it allows me to do all kinds of really cool things and push the values to Mach. Feel free to ask if I didn't explain this well or if you want to see more :)
-
I made a video if anyone is interested
https://www.youtube.com/watch?v=B0w1lwUv5_o
-
Tim,
I watched your video and have read in detail on how to set this all up. I am trying to duplicate what you have done as a starting point for a project I am working on. I have the same hardware and same settings but when I view the Modbus Diagnostics I am getting an "Illegal State error" Any chance you know why this would be happening. And did you have to config your Ethernet port on the PC at all?
Also did you have to modify the ModbusIP.h file to include Ethernet2.h instead of Ethernet.h
-
Hey Sorry for the delay in responding.
Yes, I did have to modify the Modbus.h to use ethernet2 instead of Ethernet.
Dang it, I can't remember what the Illegal state error is but I bet you dollars to donuts it's the setup count is incorrect between Mach and modbus (Base 1 for Mach and Base 0 for Modbus)
-
I have been playing with this. Did you have to uncomment the #define TCP_KEEP_ALIVE in ModbusIP.h folder to keep it running?
Polling it did not work for me.
Thank you
R. Clark
-
Hi Sparkey3
Yes, I did have to uncomment the #define TCP_KEEP_ALIVE in ModbusIP.h
Thanks for posting that :)
-
Hi
Nice work. I want to use your example for my own project. Can this code work with W5100 ethernet shield and libraty Ethernet(one) and mach3?
Thank you!
-
Hi,
How do you know that the register "X_Axis_DRO" is really the position of the X axis?
Is there a Mach's registers manual?
Tnks
-
Cool concept. Seems like something is either wrong with the arduino library or I don't know what I'm doing or something else. I'm not able to use 0, 8 or 16 as a reg value. I didn't go any further to check 24 but maybe...They just don't work. The Modbus plugin doesn't recognize the 8th "coil" input either. Neither does wireshark.
#include <ModbusIP_ENC28J60.h>
ModbusIP mb;
long ts;
int i = 0;
int regs[] = {1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17}; // values 0, 8 and 16 don't work for registers????
int pins[] = {2, 3, 4, 5, 6, 7, 8, 9, 14, 15, 16, 17, 18, 19};
void setup() {
for(i = 0; i < sizeof(pins)/sizeof(pins[0]); i++)
pinMode(pins[i], INPUT);
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 210 };
mb.config(mac, ip);
for(i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
mb.addCoil(regs[i]); //create reg
ts = millis();
}
void loop() {
mb.task(); // MB comms
if (millis() > ts + 200) {
ts = millis();
for(i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
mb.Coil(regs[i], digitalRead(pins[i])); //update reg val
}
}
(https://image.ibb.co/gTcgLd/Capture1.png)
(https://image.ibb.co/jLzHty/Capture2.png)
-
Hi Tim,
Thank you for sharing your progress on Arduino, Modbus, and Mach4. I am building a relatively gantry-type robot, for robotic welding. To achieve this, I need to define M codes (or any equivalent), to control multiple parameters of the welding machine from within the lines of G code. For instance, to increase arc voltage or wire feed speed, or accessing a memory slot in the welding machine, between lines of G code.
I wonder if you could help me understand how to define M codes to perform Modbus TCP communication. The relevant information from the welding machine manufacturer is here https://resources.userdoc.kemppi.com/manuals/a7-mig-welder-integration-om-en.pdf
At the moment, I understand that it is possible to configure the Modbus TCP protocol on Mach4. I just haven't figured out how to relate this to M codes.
Thank you in advance for any insights you may be able to share with me. Or publicly on the forum, that would be even better I guess.
Cheers
Sergio
-
To Everyone who has read this thread, I no longer work in the CNC field and now only Dabble a little bit with my machine at home. I haven't played with the Modbus stuff for years and so really have not kept up with how Mach4 works with Modbus. I hope that someone else who works in CNC more often can take the thread and help people or link another thread that would be more helpful.
I hope you find what you need somewhere here :)
-Tim
-
Hi Tim,
Thank you for sharing your progress on Arduino, Modbus, and Mach4. I am building a relatively gantry-type robot, for robotic welding. To achieve this, I need to define M codes (or any equivalent), to control multiple parameters of the welding machine from within the lines of G code. For instance, to increase arc voltage or wire feed speed, or accessing a memory slot in the welding machine, between lines of G code.
I wonder if you could help me understand how to define M codes to perform Modbus TCP communication. The relevant information from the welding machine manufacturer is here https://resources.userdoc.kemppi.com/manuals/a7-mig-welder-integration-om-en.pdf
At the moment, I understand that it is possible to configure the Modbus TCP protocol on Mach4. I just haven't figured out how to relate this to M codes.
Thank you in advance for any insights you may be able to share with me. Or publicly on the forum, that would be even better I guess.
Cheers
Sergio
Once you map the Modbus IO in the Mach4 inputs/outputs mapping then you can just use the LUA scripting API to monitor or set the state of the IO. The third post down by ChaoticOne here: https://www.machsupport.com/forum/index.php?topic=27158.0 shows images on how to map the IO.
You can find documentation on the Mach4 LUA scripting located in the installation directory of Mach4 (Docs Folder Mach4CoreAPI.chm).