Modbus TCP/IP on Arduino - arduino

I am trying to implement Modbus TCP on arduino uno + ethernet shield using the following code.
I am using a modbus slave simulator on a pc to check the following code. However, the code doesn't seem to be working. I have downloaded the code & the libraries from http://myarduinoprojects.com/modbus.html. Please suggest me corrections if necessary. Also is there another working example available for modbus tcp/ip on arduino.
Thanks.
#include <SPI.h>
#include <Ethernet.h>
#include "MgsModbus.h"
MgsModbus Mb;
int inByte = 0; // incoming serial byte
// Ethernet settings (depending on MAC and Local network)
byte mac[] = {0x00, 0x1A, 0xB6, 0x02, 0xD1, 0x14 };
IPAddress ip(192, 168, 0, 35);
void setup()
{
// serial setup
Serial.begin(9600);
Serial.println("Serial interface started");
// initialize the ethernet device
Ethernet.begin(mac, ip); // start etehrnet interface
Serial.println("Ethernet interface started");
// print your local IP address:
Serial.print("My IP address: ");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(".");
}
Serial.println();
// slave address
Mb.remSlaveIP = (192,168,0,1);
// Fill MbData
// Mb.SetBit(0,false);
Mb.MbData[0] = 1;
Mb.MbData[1] = 2;
Mb.MbData[2] = 3;
Mb.MbData[3] = 4;
Mb.MbData[4] = 5;
Mb.MbData[5] = 6;
Mb.MbData[6] = 0;
Mb.MbData[7] = 0;
Mb.MbData[8] = 0;
Mb.MbData[9] = 0;
Mb.MbData[10] = 0;
Mb.MbData[11] = 0;
// print MbData
for (int i=0;i<12;i++) {
Serial.print("address: "); Serial.print(i); Serial.print("Data: "); Serial.println(Mb.MbData[i]);
}
// print menu
Serial.println("0 - print the first 12 words of the MbData space");
Serial.println("1 - FC 1 - read the first 5 coils from the slave and store them in the lower byte of MbData[1]");
Serial.println("2 - FC 2 - read the first 5 discrete inputs from the slave and store them in the higer of the MbData[1]");
Serial.println("3 - FC 3 - read the first 5 registers from the slave and store them in MbData[3..7");
Serial.println("4 - FC 4 - read the first 5 input registers from the slave and store them in MbData[8..12]");
Serial.println("5 - FC 5 - write coil 0 of the slave with the bit valeu of MbData[0.0]");
Serial.println("6 - FC 6 - write register 0 of the slave with MbData[2]");
Serial.println("7 - FC 15 - write 5 coils of the slave starting with coil 0 with GetBit(16..20");
Serial.println("8 - Fc 16 - write 5 registers of the slave starting on register 0 with MbData[0..4]");
Serial.println(Mb.remSlaveIP);
}
void loop()
{
if (Serial.available() > 0) {
// get incoming byte:
inByte = Serial.read();
if (inByte == '0') { // print MbData
for (int i=0;i<12;i++) {
Serial.print("address: "); Serial.print(i); Serial.print("Data: "); Serial.println(Mb.MbData[i]);
}
}
if (inByte == '1') {Mb.Req(MB_FC_READ_COILS, 6,6,6);} // 1 // ref, count, pos
if (inByte == '2') {Mb.Req(MB_FC_READ_DISCRETE_INPUT, 6,6,6);} // 2
if (inByte == '3') {Mb.Req(MB_FC_READ_REGISTERS, 6,6,6);} // 3
if (inByte == '4') {Mb.Req(MB_FC_READ_INPUT_REGISTER, 6,6,6);} // 4
if (inByte == '5') {Mb.Req(MB_FC_WRITE_COIL, 0,0,0);} // 5 // count can be x
if (inByte == '6') {Mb.Req(MB_FC_WRITE_REGISTER, 7,0,0);} // 6 // count can be x
if (inByte == '7') {Mb.Req(MB_FC_WRITE_MULTIPLE_COILS, 0,6,0);} // 15
if (inByte == '8') {Mb.Req(MB_FC_WRITE_MULTIPLE_REGISTERS, 0,6,0);} // 16
}
Mb.MbmRun();
// Mb.MbsRun();
}

Serial monitor works fine. Following lines are printed on first debugging the program
Serial interface started
Ethernet interface started
My IP address: 192.168.0.35.
address: 0Data: 1
address: 1Data: 2
address: 2Data: 3
address: 3Data: 4
address: 4Data: 5
address: 5Data: 6
address: 6Data: 0
address: 7Data: 0
address: 8Data: 0
address: 9Data: 0
address: 10Data: 0
address: 11Data: 0
0 - print the first 12 words of the MbData space
1 - FC 1 - read the first 5 coils from the slave and store them in the lower byte of MbData[1]
2 - FC 2 - read the first 5 discrete inputs from the slave and store them in the higer of the MbData[1]
3 - FC 3 - read the first 5 registers from the slave and store them in MbData[3..7
4 - FC 4 - read the first 5 input registers from the slave and store them in MbData[8..12]
5 - FC 5 - write coil 0 of the slave with the bit valeu of MbData[0.0]
6 - FC 6 - write register 0 of the slave with MbData[2]
7 - FC 15 - write 5 coils of the slave starting with coil 0 with GetBit(16..20
8 - Fc 16 - write 5 registers of the slave starting on register 0 with MbData[0..4]
1.0.0.0
however it seems that the TCP communication does not work since there is nothing on the serial monitor after this #graham.reeds

I am using mgsmodbus for my modbuswork at office. What I have is a Master TI board and a Slave simulator. However I am using Wifi.h instead of ethernet.h. I am able to do all the operations.
Did you check if the ethernet connection is properly established?
If so try IBH Modbus slave simulator. That works perfect. You would have to change the setting to TCP and select the port. Sometimes the port number you are trying for could be wrong. I use port 502 which is the default one.
Also, make sure that the slave IP in the .cpp code is also changed.

Related

Solved --- ESP8266 with DHT11 / DHT22 Standalon -> problem with Arduino to flash the ESP8266

before to come here, I've tried lot an lot of solutions found on the net and here.
The issue is:
After compile code (passed as good), I try to upload it into ESP8266 throu Arduino.
The result is:
« esptool.py v3.0 Serial port /dev/ttyACM0
Connecting........_____....._____....._____....._____....._____....._____.....____
Traceback (most recent call last):
File "/home/patrick/.arduino15/packages/esp8266/hardware/esp8266/3.0.2/tools/upload.py", line 66, in <module> esptool.main(cmdline)
File "/home/patrick/.arduino15/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool/esptool.py", line 3552, in main esp.connect(args.before, args.connect_attempts)
File "/home/patrick/.arduino15/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool/esptool.py", line 529, in connect raise
FatalError('Failed to connect to %s: %s' % (self.CHIP_NAME, last_error)) esptool.
FatalError: Failed to connect to ESP8266: Timed out waiting for packet header
_ le port série sélectionné _ n'existe pas ou votre Arduino n'est pas connecté »
During transfer I can see both Arduino (TX and RX) DEL blinking, and Arduino RX blinks the ESP8266 TX blinks also. From there ... I feel like having good connection.
The pinout goses like this
Arduino - ESP8266
GND - GND
3.3V - VCC
RX+0 - TX
TX+1 - RX
3.3V - CH_PD/EN
According to ESP8266pinout
I tried to
change the upload speed
change the CPU frequency
change the cristal frequency
switch TX / RX just i case I would plugged them on reverse
updated the DHT driver and adapted the code consequently
downgrade the ESP8666 driver on Arduino IDE from 3.2 to 2.5.1, to 2.5.0, to 2.4.9
modify the upload.py file, line 66 and around
My ESP8666 did connect properly to the WiFi Network previously, programming it with Raspberry PICO and micropython. From that, I'm pretty sure about the good working state of the device.
Below is my c++ code
#include <ESP8266WiFi.h>
#include <DHT.h>
const char* ssid = "BullFrog"; // Your ssid
const char* password = "Pr1on$J3sus"; // Your Password
WiFiServer server(80);
//Instantiation d'une nouvelle classe DHT
// DHT DHT (pin, type, count);
// #param pin
// pin number that sensor is connected
// #param type
// type of sensor
// #param count
// number of sensors
DHT DHT(2, 11, 1);
double Fahrenheit(double celsius) {
return ((double)(9 / 5) * celsius) + 32;
}
double Kelvin(double celsius) {
return celsius + 273.15;
}
void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
// Connect to WiFi network
WiFi.mode(WIFI_STA);
Serial.println();
Serial.println();
Serial.print("Tentative de connexion au Wifi nommé ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("Connexion WiFi établie");
// Start the server
server.begin();
Serial.println("Démarrage du serveur web");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
int err;
float temp, humi;
if (temp = DHT.readTemperature(false, false)) {
Serial.print("Température:");
Serial.print(temp);
} else {
Serial.println();
Serial.print("Erreur lors de la lecture de la température. No :");
Serial.print(err);
Serial.println();
}
if (temp = DHT.readHumidity(false)) {
Serial.print(" Humidité:");
Serial.print(humi);
Serial.println();
} else {
Serial.println();
Serial.print("Erreur lors de la lecture de l humidité relative. No :");
Serial.print(err);
Serial.println();
}
WiFiClient client = server.available();
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println("Refresh: 5");
client.println();
client.println("<!DOCTYPE html>");
client.println("<html xmlns='http://www.w3.org/1999/xhtml'>");
client.println("<head>\n<meta charset='UTF-8'>");
client.println("<title>ESP8266 Température & Humidité DHT11</title>");
client.println("</head>\n<body>");
client.println("<H2>Capteurs ESP8266 & DHT11</H2>");
client.println("<H3>Humidité / Température</H3>");
client.println("<pre>");
client.print("Humidité (%) : ");
client.println((float)humi, 2);
client.print("Température (°C) : ");
client.println((float)temp, 2);
client.print("Température (°F) : ");
client.println(Fahrenheit(temp), 2);
client.print("Température (°K) : ");
client.println(Kelvin(temp), 2);
client.println("</pre>");
client.println("<H3>Revenez nous voir!</H3>");
client.print("</body>\n</html>");
// delay(DHT11_RETRY_DELAY); //delay for reread
}
I want to use this kit in standalone
I followed this tutorial (among others)
Thanks for your attention and help.
I would first try to program your ESP-01 with a simple Blink sketch, just to confirm the ESP-01 is ok.
These are examples from the same website you reference:
https://www.elec-cafe.com/tag/esp8266-flasher/
https://www.elec-cafe.com/esp8266-esp-01-firmware-update/
Also, the ESP8266 requires a good amount for power for WiFi transmit. Sometimes it help to use separate power supply and add 470uF or 1000uF capacitor across the VCC and GND of the ESP chip.
I hope this might help you to succeed.
The problem is not in coding but in wiring.
Remember that (with ESP8266-01) :
pin 1 as GND (from left to right 1,2,3,4) on the row near to the middle of board
pins 5 as VCC (from right to left 5,6,7,8) on the row near to the ridge of board
pins 5 and 7 must be permanently connected
for loading code into ESP8266-01: pins 1 and 3 must be connected for the uploading time duration.
Once everything is uploaded, come back to the using position (uplug 1 - 3) like this:

Arduino communication with TMC2209

I'm trying to communicate with TMC2209 (stepper drive) with an Arduino nano Every.
I connected pin RX on pin D2 and TX on pin D3.
I placed a 1K resistor between TX and RX.
It seems I can write parameters (even I'm testing this deeply, I'm not so sure now..) but I'm not able
to read nothing from driver.
Picture added 15/04/2021 related to datasheet of TMC2209
In my test, I tried with only one driver with address 0, means MS1_AD0 and MS2_AD1 connected to GND.
driver1.microsteps(MICROSTEPS);
SerialPort.print("Counter1=");
SerialPort.print(driver1.IFCNT());
SerialPort.print(", Status=");
SerialPort.println(driver1.DRV_STATUS());
I tried reading IFCNT and DRV_STATUS, always ZERO.
The initialization is done in this way:
#include <Wire.h>
#include <AG_AS5600.h>
#include <TMCStepper.h>
#include <AccelStepper.h>
#define ENCODER false
#define FEEDBACK_I2C true
#define GEARBOX 139 //51
#define MICROSTEPS 16
#define MIN_SPEED 20
#define MAX_SPEED 3000
double offsetHome = 77.0;
#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
#define SerialPort SerialUSB
#define SYS_VOL 3.3
#else
#define SerialPort Serial
#define SYS_VOL 5
#endif
#define SW_RX 2 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX 3 // TMC2208/TMC2224 SoftwareSerial transmit pin
#define EN_PIN 7 // Enable
#define DIR_PIN 8 // Direction
#define STEP_PIN 9 // Step
#define SERIAL_PORT Serial1 // TMC2208/TMC2224 HardwareSerial port
#define DRIVER_ADDRESS1 0b00 // TMC2209 Driver address according to MS1 and MS2
#define R_SENSE 0.11f // Match to your driver
// SilentStepStick series use 0.11
// UltiMachine Einsy and Archim2 boards use 0.2
// Panucatt BSD2660 uses 0.1
// Watterott TMC5160 uses 0.075
AG_AMS_5600 ams5600;
TMC2209Stepper driver1(SW_RX, SW_TX, R_SENSE, DRIVER_ADDRESS1);
AccelStepper stepper = AccelStepper(stepper.DRIVER, STEP_PIN, DIR_PIN);
String cmd = {};
void setup()
{
SerialPort.begin(115200);
Wire.begin();
Wire.setTimeout(10);
SerialPort.println(">>>>>>>>>> Program started <<<<<<<<<<");
pinMode(EN_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
digitalWrite(EN_PIN, HIGH); // Enable driver in hardware
// Enable one according to your setup
SPI.begin(); // SPI drivers
driver1.beginSerial(115200); // SW UART drivers
driver1.begin(); // SPI: Init CS pins and possible SW SPI pins
// UART: Init SW UART (if selected) with default 115200 baudrate
driver1.toff(5); // Enables driver in software
driver1.rms_current(2000); // Set stepper current to 600mA. The command is the same as command TMC2130.setCurrent(600, 0.11, 0.5);
driver1.microsteps(MICROSTEPS);
driver1.pwm_autoscale(true); // Needed for stealthChop
stepper.setMaxSpeed(degToSteps(500.0)); // steps/s
stepper.setAcceleration(degToSteps(1.0)); // steps/s^2
stepper.setEnablePin(EN_PIN);
stepper.setPinsInverted(false, false, true);
stepper.disableOutputs();
}
void loop()
{
unsigned long t0 = micros();
switch (step) {
case 0:
cmd = SerialPort.readString();
if (cmd.charAt(0)=='a' && cmd.charAt(1)=='=') {
acc = degToSteps(cmd.substring(2).toDouble());
SerialPort.print("Acceleration=");
SerialPort.println(acc);
cmd = "";
}
else if (cmd.charAt(0)=='d' && cmd.charAt(1)=='=') {
dec = cmd.substring(2).toInt();
SerialPort.print("Deceleration=");
SerialPort.println(dec);
cmd = "";
}
else if (cmd.charAt(0)=='c' && cmd.charAt(1)=='?') {
driver1.microsteps(MICROSTEPS);
driver2.microsteps(MICROSTEPS);
SerialPort.print("Counter1=");
SerialPort.print(driver1.IFCNT());
SerialPort.print(", Counter2=");
SerialPort.print(driver2.IFCNT());
SerialPort.print(", Status=");
SerialPort.println(driver1.DRV_STATUS());
cmd = "";
}
}
The hardware should be ok because the jumper for UART is configured as default on pin4.
Can someone help me to understand why?
Thanks
Andrea
I found!
The issue was the handling of "software" serial port.
Unfortunately I was confused because many examples of "TMCstepper.h" library are shown using two pins as TX and RX, so I was convinced internally pins were handled to send and receive.. but it's not.
So solution I found is:
#include <SoftwareSerial.h>
SoftwareSerial SerialDriver1(SW_RX, SW_TX);
TMC2209Stepper driver1(&SerialDriver1, R_SENSE, DRIVER_ADDRESS1);
void setup()
{
SerialDriver1.begin(57600);
SerialDriver1.listen();
...
and was really important to comment:
//driver1.beginSerial(115200); // SW UART drivers
this is important I guess because the port was already opened in the setup by me.
and it's necessary to specify the software port where to listen, not done by TMC library.
Last hint, with Arduino Nano Every I found out that Software Serial seems to work with max baudrate of 57600, 115200 was not working.

Can't send and receive data from my own usart - SAM4SD16C

I'm trying to use USART 0 on the SAM4SD16C processor.
I got some help to start, from this website : SAM4S Xplained USART
Here's the code I'm using (which compiles):
#define COM_Handler USART0_Handler
#define USART_SERIAL USART0
#define USART_SERIAL_ID ID_USART0
#define USART_SERIAL_BAUDRATE 115200
#define USART_SERIAL_CHAR_LENGTH US_MR_CHRL_8_BIT
#define USART_SERIAL_PARITY US_MR_PAR_NO
#define USART_SERIAL_STOP_BIT US_MR_NBSTOP_1_BIT
#define PINS_USART0_PIO PIOA
#define PINS_USART0_ID ID_USART0
#define PINS_USART0_TYPE PIO_PERIPH_A
#define PINS_USART0_ATTR PIO_DEFAULT
#define PINS_USART0_MASK (PIO_PA5A_RXD0| PIO_PA6A_TXD0)
uint32_t received_byte;
uint32_t dw_status ;
int main(void)
{
sysclk_init();
board_init();
sysclk_enable_peripheral_clock(USART_SERIAL_ID);
pio_configure(PINS_USART0_PIO, PINS_USART0_TYPE, PINS_USART0_MASK, PINS_USART0_ATTR);
const sam_usart_opt_t usart_console_settings = {
USART_SERIAL_BAUDRATE,
USART_SERIAL_CHAR_LENGTH,
USART_SERIAL_PARITY,
USART_SERIAL_STOP_BIT,
US_MR_CHMODE_NORMAL
};
usart_init_rs485(USART_SERIAL, &usart_console_settings, sysclk_get_peripheral_hz());
usart_enable_tx(USART_SERIAL);
usart_enable_rx(USART_SERIAL);
usart_enable_interrupt(USART_SERIAL, US_IER_RXRDY);
NVIC_EnableIRQ(USART0_IRQn);
while (1)
{
while(US_CSR_TXRDY != 0 );
do
{
usart_write(USART_SERIAL, 1);
}while(US_CSR_RXRDY==0);
/*dw_status = usart_get_status(USART_SERIAL);
if(dw_status & US_CSR_RXRDY){
usart_read(USART_SERIAL, &received_byte);
}*/
}
}
When I debug the program, it stays in the while(US_CSR_TXRDY != 0) loop...
I wrote this line because I've seen somewhere in asf library that I should check if TX is ready to send before sending anything..
Once this will be resolved, I'll try to receive on the same board what I'm transmitting by connecting RX and TX together.
I only begin working on this processor and I'm not pretty familiar with it...
Thank you for your help
US_CSR_TXRDY is a constant, so while(US_CSR_TXRDY != 0 ) is a infinite loop. I think it should be while( (USART0->US_CSR & US_CSR_TXRDY) != 0 ).

Can't connect Arduino to RFID

I am using an A-Star 32U4 Micro Arduino and I'm trying to connect the RDM6300 - 125KHz Cardreader Mini-Module.
I'm using this sketch at the moment:
#include <SoftwareSerial.h>
// RFID | Nano
// Pin 1 | D2
// Pin 2 | D3
SoftwareSerial Rfid = SoftwareSerial(2,3);
void setup() {
// Serial Monitor to see results on the computer
Serial.begin(9600);
// Communication to the RFID reader
Rfid.begin(9600);
}
void loop() {
// check, if any data is available
if(Rfid.available() > 0 ){
// as long as there is data available...
while(Rfid.available() > 0 ){
// read a byte
int r = Rfid.read();
// print it to the serial monitor
Serial.print(r, DEC);
Serial.print(" ");
}
// linebreak
Serial.println();
}
}
With this circuit:
module TX --- Arduino pin 2
module VCC ----- 5v
module ground ---- ground
antenna pins ---- antenna
When I put the card in the sensor nothing shows up on serial port. I tried this setup and the exact same sensors on an Arduino Uno (same sketch) and it worked perfectly, but I cant get this working on the Micro.
Arduino UNO and Micro uses different processors, though they work fairly similarly, they are not totaly identical.
It seams that
not all pins on the Leonardo and Micro support change interrupts, so only the following can be used for RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).
From the SoftwareSerial Library description ( https://www.arduino.cc/en/Reference/softwareSerial )
Change the module TX from pin 2 to pin 8. and you should be good. :-)

Receive XBee signals on Arduino

Side A:
Arduino Uno R3 with Wireless Proto shield powered with USB
With XBee Pro S1, DH 0 DL FFFF MY 0 API 0
Wireless Proto shield has the serial select switch on the 'micro' position
side B:
XBee Explorer USB connected to a PC with XCTU software
With XBee Pro S1, DH 0 DL FFFF MY 0 API 0
(When I put both XBee modules in the USB explorer boards, connected with two PC's, I can send data back and forth without any problems, so I reckon the XBee settings are good.)
The Problem
Now I want the Arduino to capture the input from the B side (send with the XCTU terminal), but when I type anything in the terminal, the RSSI LED on side A just turns on for 5 seconds, but the Arduino does not seem to capture any data since it does not send data back like it should (Serial.print("I received: ");
Arduino sketch:
int incomingByte = 0;
void setup() {
Serial.begin(19200); //Both XBee chips are configured at 19200 Baud
Serial.print("start echo machine"); //This is received just fine on the B side
}
void loop() {
if (Serial.available() > 0) {
// Read the incoming byte:
incomingByte = Serial.read();
// Say what you got:
Serial.print("I received: "); //This never shows on the B-side
Serial.println(incomingByte, DEC);
}
}
How do I fix this problem?
You have to use a SoftwareSerial(RX,TX) for the XBee and the Serial for printing the output into the pc.
RX and TX of SoftwareSerial must be linked to the DOUT and DIN pin of the module into the Wireless Proto shield:
#include <SoftwareSerial.h>
// Connect pin 10 of Arduino to DOUT of Wireless Proto shield
uint8_t ssRX = 10;
// Connect pin 11 of Arduino to DIN of Wireless Proto shield
uint8_t ssTX = 11;
SoftwareSerial nss(ssRX, ssTX);
void setup() {
Serial.begin(19200);
nss.begin(19200);
Serial.println("Serial works");
}
void loop() {
if (nss.available()){
Serial.println("received packet:");
for(int i=0;i<25;i++){
Serial.print(nss.read(),HEX);
Serial.print(",");
}
Serial.println();
}
Many of the boards require the pull-up resistor on DIN to be enabled.
According to some sources this pull-up is enabled by default on the Digi Xbee module.
To ensure it is enabled or to enable it:
Put your Xbee module in a USB explorer and use X-CTU to check the PR configuration.
DIN is on bit 7 for the Xbee Pro S1, so in that case you need the last bit to be 1.
I put it like this: 00000001
Than you convert it to hex (01 in my case) and write that value to the Xbee module with X-CTU.
So it is an electronics issue and not a programming issue.

Resources