Modbus RTU

If anybody (including Epyon / PaulStoffgren) is interested in working on this to produce a non-specific-board centric solution I can provide a microSD image for the RPI 3 with the complete SCADA software. You will need to sign a simple NDA to get that.

Well, I definitely am interested in fixing any problem with Modbus RTU on Teensy 3.x & LC. If you give this library a try on Teensy and something about Modbus RTU isn't working, I will try to fix it. While I can't make any guarantees, I do have a long history of fixing problems with many Arduino libraries.

That said, I do believe there's a very good chance the edits I recently made resolve all the issues, making this library work on Teensy at least as well as it does on the 8 bit Arduino board it was originally meant to support.

If you encounter any issues, I'm going to need you to be specific and post non-proprietary test code here on this public forum. I'm not going to sign any NDA.

I have no intention of testing this lib on other non-Teensy hardware, other than perhaps running a copy of Uno or Mega which is supports. Sorry, I can only dedicate my engineering time to supporting Teensy hardware.
 
@PaulStoffregen

Thanks for the reply

Ok I will buy a Teensy board and give the modded library a try. Is there any specific board you recommend? I am looking at the PJRC Teensy 3.5 or the Sparkfun Teensy 3.5. I live in Thailand so both will take a week or so to get delivered (if they ever do :) )

I will do all the testing this end - if it is Modbus RTU it will work and initially I don't care if it is over RS232 or RS485! Sorry I can't release my code without an NDA there are 40 man years of software effort and two other individuals jointly have interest the IPR. Is the link posted on this thread pointing to the latest release?

Thanks for the fast Response
 
Teensy 3.2 or 3.5 should work fine. You could also use Teensy LC if you don't need 5V tolerance. You could buy from any of these distributors, if that helps.

https://forum.pjrc.com/threads/23601-Official-Distributors

If you do find a problem, you must post a small test program here. DO NOT post your proprietary code. But please do understand that you must create a small, non-proprietary program which just sends & receives 1 message, to demonstrate the problem. Yes, this is extra work for you to do. That's how things work here. Usually the work to create a very small program which only sends or receives 1 message is small. If you look over the many threads on this forum, we have an excellent track record of investigating and fixing problems when a complete test program is posted. Without a way to reproduce the same problem, odds of a solution are not good.
 
@PaulStoffregen

Thanks again for the fast response. I have just ordered the PJRC Teensy 3.5 mail order and it looks like I can get a Teensy 3.2 locally so should be able to start work soon. I understand the way you work and initially I will use something like QModbus to do the preliminary testing
 
Hi everyone,

I've used the ModbusMaster 2.0.1 library to use a Teensy 3.5 as a master for some pressure sensors. This was a pretty straightforward process - the only things I had to change were how the Serial was implemented. Essentially a find and replace to change from serial->whatever() to Serial1.whatever(). I'm not nearly good enough at programming to fix that one up properly but the library is definitely worth checking out
 
T3.2 Modbus RTU slave or Master...@Ben

@BEN

Your ModbusRtu.h of 01-18-2018, 05:15 AM works for me out of the box: TEENSY 3.2, Serial1. Compiled on Arduino 1.6.12, Teensyduino 1.31-beta2, with the Max3485 on this carrier (it has a 120 ohm terminator on it)

Max3485.JPG
I have two ADC SOLO 4824 on a network with them. Ran 9600 and 38.4 at SERIAL_8N2 perfect. Plugs right into my ABS4988T which is about like this ABS8825T. I used pin 23 for the utxenpin.....

ABS4658T.JPG

Using....

Modbus slave(1, Serial1, 23); // this is slave @1 serial, port 1, dere at do23/A9 teensy 3.2

and

slave.begin( 9600, SERIAL_8N2); // or try baud-rate at 38400

@PAUL I'll go back to yours tomorrow but the control pin is not switching for Serial1. too many #if defined (....) for this hour...
 
Well, I upgrades to Arudino 1.8.5/teensyduino 1.4.1 release. Pretty much same results. I did notice that I needed to try a few times before the BEN version of Modbusrtu.h would respond to a master request. Then tried the other. Nope. There is something in the constructor #if defined amiss....i think to so with serial port selection and also the txenpin ...never engages perhaps it got assigned to a different com port???...???
 
Any chance you could post a multiple-port test program? As you can see in msg #20, it seemed to work fine when I tested with a single port. If you can give me a program that shows the problem with multiple ports, I can dig into the code and fix whatever's wrong.
 
Single port TX1/RX1 code slave story.....

Just to be clear. I do have both(either) the master or the slave running on RX1/TX1 on a T3.2 with the ModbusRtu file from BEN's post....same setup with the ModbusRtu.h (one from your link) did not respond to a known good Master with no other changes on the ABS4988T board on same TX1/RX1 setup. This is the single port slave test code used (plagiarized heavily from Ben's example):


Code:
/**
 *  Modbus slave example 1:
 *  The purpose of this example is to link a data array
 *  from the Arduino to an external device.
 *
 *  Recommended Modbus Master: QModbus
 *  http://qmodbus.sourceforge.net/
 */

#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, 65535 };

/**
 *  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 slave(1, Serial1, 23); // this is slave @1 serial, port 1, dere at do23/A9 teensy 3.2

elapsedMillis sinceRead = 0;
elapsedMillis ledOffTime = 0;
uint8_t ledState = 0;
uint8_t address = 0;

void setup() {
  //
  pinMode( OUTPUT, 23);
  digitalWrite(23, LOW);
  
  slave.begin( 9600, SERIAL_8N2); // or try baud-rate at 38400
  //slave.begin( 19200, SERIAL_8E1 ); // 19200 baud, 8-bits, even, 1-bit stop

  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  //Serial.begin(9600);
}

void loop() {
  slave.poll( au16data, 16 );
  //Serial.print(au16data[4]);
  if (sinceRead > 100) {
    sinceRead -= 100;
   // slaveData[address] = analogRead(A0);
   // address++;
   // if (address > 15) address = 0;
    ledFlash (1);
  }
  if (Serial1.available()>=1) ledFlash(100);

  if (ledOffTime > 1000) {
    ledOffTime = 1000;
    digitalWrite(LED_BUILTIN, LOW);
    ledState = 0;
  }
}

void ledFlash(uint32_t duration) {
  digitalWrite(LED_BUILTIN, HIGH);
  if (ledState == 0 && ledOffTime >= duration) {
    ledOffTime -= duration;
  }
  ledState = 1;
  return;
}


That particular Board is currently using all other pins 2-13 for stepper control lines. but I could just pop one of the allegros out for the test.

I could however use a different carrier board and run TWO RTU masters (one on Serial1 and the other on Serial4) on a T3.6?? THat sounds like an adventure HAR.

On this board (TELEZ)

https://forum.pjrc.com/attachment.php?attachmentid=9165&d=1481908735

or would it be OK to try SoftwareSerial on pins 20/21/22 as that board (the ABS4988T) has strap holes in it for general utility.

PS: Just for my notes and some other people I am working with:

Anyway I have a group of friends working with me. We will run TTL (3.3v) point to point Modbus RTU slave on the T3.2 to an esp32 or esp8266 acting as a Modbus Master for a cloud link remote operator interface. The ESP will also have a local touchscreen (on the ESP) and wifi cloud linking SW to provide secure remote access via cell phone. This will leave the TEENSY practically full bandwidth for stepper/feedback control. With the esp handling graphics and remote requests.

On TELEZ we will run Modbus master rtu on the T3.6 TX1/RX1 port and another type of protocol as a master on TX4/RX4 and also run a Modbus TCP server on a Wiznet 820i CS0/MOSI0/MISO0/SCK0 (on 10,11,12,13). These are already tested on the TELEZ Board. With only the TX4RX4 left to implement. The Raspberry is the local headless IDE (linux). I don't plan on an ESP for the TELEZ board for now unless the linux box proves to cumbersome for remote USER access.


All the best.
 
RTU triple Axis controller.

triple_slave.gif

At the risk of talking to myself.....This is an RTU device that can control three axis (in this case peristaltic pumps, but I also do other things). I usually use this board as an I2C slave to TELEZ. For RTU, The device can be either master or slave. It can schedule profiles or run sequences in the T32. CLosed loop control is possible using the analog inputs or PGA strain gauge input for weight or pressure control. UF/DF or filtration control has been done with this unit as well as automatic sample preparation. Anyway, next I will partner it with an ESP32 running JavaScript for RTU to provide a gateway for Cell phone or local WiFi HMI (user interface).

triple_inside.gif
 
Hi,

Im trying to get the sample from BEN running on a Teensy 3.5 without success.
I would like to use the HW Serial. At the moment im trying it with a USB/Serial converter.

Code:
#include <ModbusRtu.h>

uint16_t slaveData[16];
Modbus slave(1, Serial2, 0); //Bus ID, port, RX-pin

elapsedMillis sinceRead = 0;
elapsedMillis ledOffTime = 0;
uint8_t ledState = 0;
uint8_t address = 0;

void setup() {
  //Serial.begin(9600);
  slave.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

void loop() {
  slave.poll(slaveData, 16);
  if (sinceRead > 100) {
    sinceRead -= 100;
    slaveData[address] = analogRead(A0);
    address++;
    if (address > 15) address = 0;
    ledFlash (1);
  }
  if (Serial2.available()>=1) ledFlash(100);

  if (ledOffTime > 1000) {
    ledOffTime = 1000;
    digitalWrite(LED_BUILTIN, LOW);
    ledState = 0;
  }
}

void ledFlash(uint32_t duration) {
  digitalWrite(LED_BUILTIN, HIGH);
  if (ledState == 0 && ledOffTime >= duration) {
    ledOffTime -= duration;
  }
  ledState = 1;
  return;
}

Regards Chris
 
I am not new to Arduino specifically (I backed the first Teensy Kickstarter and have been using the Arduino platform for a good while now) but I am somewhat new to Modbus and RU485 as it was not possible to do it natively with an Arduino until fairly recently when the SERCOM support was FINALLY implemented.

As usual, Teensy is leading the way with this. We have been considering using a ATSAMD21 or ATSAMD51 (ARM Cortex-M0 or ARM Cortex-M4) based board now that they are starting to be reasonable in price.

Looks like the M0, the Zero and now the M4 and the LC (?), 3.2 and now 3.5 and 3.6 should all support this (though unclear if it is just the 3.2 and beyond as those are based on the Cortex M4).

Anyway, my question is more related to is there any actual code for using RS485 and more specifically Modbus RTU over it using the Teensy (or for that matter any M4 based chip?)

I am trying to use an Arduino as a Master to speak to an actuator that, well, requires you to speak to it through half duplex Modbus RTU only (not ASCII). I asked around and was told that it was not supported at all, which does not appear to be the case and then when I looked into Section 34.6.3.6 of the roughly 2000 page manual (http://ww1.microchip.com/downloads/en/DeviceDoc/SAM-D5xE5x-Family-Datasheet-01507B.pdf) that does specify that it is possible, I was told it was possible but there is no code for it. The Zero has been out for 3+ years now so surely somebody has written something that, well, functions at least? I do see some software drivers out there but those are more for MEGAs and other hardware that does not support this natively which I would like to be able to do.

Looking around the forum, I do see a few references to serial though I cannot tell if there is any Modbus RTU code over RS485 out there or not.

So I guess I was wondering if anybody has any specific code that just works with regards to being able to send commands to a Modbus RTU slave over RS485? I know what I want to send to it, I just have no idea (not the current skill set) to create a RS485 link as well as a Modbus RTU framework.

https://forum.arduino.cc/index.php?topic=401006.0
This speaks to this a bit and has some example code regarding an Arduino Zero to Arduino Zero communication.

http://ww1.microchip.com/downloads/...S-485-Xplained-Pro_ApplicationNote_AT8547.pdf
Both the ATSAMD21 and the ATSAMC21 support hardware RS-485.

Ideally I would be looking for some method of being able to just send specific commands from within the sketch directly to the RS485 / Modbus RTU slave as if the Teensy or Zero / M4 was a terminal console and not have to create an entire protocol to make that work. Is this already built into the Teensy from around LC or 3.2 and beyond? Has this already been done? Even the documentation about it on the ATSAMD21 doesn't seem terribly comprehensive but it seems to be a selling point of the ATSAMD51 and newer 3.5 and 3.6 style of Arduinos. Except I have tried for several hours to actually locate, well, actual usable code without much success.

Am I misunderstanding the state of the new 6 port SERCOM hardware that enables RS485 and Modbus RTU on the Arduino or Teensy or is there really no usable code except for software implementations? I am more of a hardware person unfortunately and I do not think I would be able to (within a reasonable timeframe) write something like this.

A few extra resources:
https://www.arduino.cc/en/Tutorial/SamdSercom

Youtube video from Adafruit that goes over ATSAMD21 that talks about SERCOM.
https://www.youtube.com/watch?v=L2edpBP3AWE

Adafruit talks about this a bit more in depth but more from the SERCOM level rather than the RS485 level and from the perspective of the ATSAMD21 in their Zero line.
https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/muxing-it-up

Lastly, it is worth mentioning that there is a bit written about this here already. Though I am not quite sure that quite gets us there just yet, though it is helpful.
https://www.pjrc.com/teensy/td_uart.html

Except when you click on the link to learn more about "Modbus RTU (see RS-485 transmitter Enable function)", it literally takes you to this forum thread.
 
Last edited:
Hi,

Im trying to get the sample from BEN running on a Teensy 3.5 without success.
I would like to use the HW Serial. At the moment im trying it with a USB/Serial converter.

Code:
#include <ModbusRtu.h>

uint16_t slaveData[16];
Modbus slave(1, Serial2, 0); //Bus ID, port, RX-pin

elapsedMillis sinceRead = 0;
elapsedMillis ledOffTime = 0;
uint8_t ledState = 0;
uint8_t address = 0;

void setup() {
  //Serial.begin(9600);
  slave.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

void loop() {
  slave.poll(slaveData, 16);
  if (sinceRead > 100) {
    sinceRead -= 100;
    slaveData[address] = analogRead(A0);
    address++;
    if (address > 15) address = 0;
    ledFlash (1);
  }
  if (Serial2.available()>=1) ledFlash(100);

  if (ledOffTime > 1000) {
    ledOffTime = 1000;
    digitalWrite(LED_BUILTIN, LOW);
    ledState = 0;
  }
}

void ledFlash(uint32_t duration) {
  digitalWrite(LED_BUILTIN, HIGH);
  if (ledState == 0 && ledOffTime >= duration) {
    ledOffTime -= duration;
  }
  ledState = 1;
  return;
}

Regards Chris

Hello friends !
Not all Arduino codes are suitable for teensy (I didn't mean it wouldn't work).
I use Teensy products for industrial purposes, and I have not encountered any negativity until today.
The biggest mistake in processor programming is not solving the character of the product.
I would like to share the Modbus data flow method I wrote roughly.

Modbus Data Flow schema codes


Code:
#define HI(x)  ((x) >> 8)
#define LO(x)  ((x) & 0xFF)

const uint32_t SerBaud = 921600;
uint16_t BaudDelay = 144 ;
uint8_t msg[64] ;
uint8_t ndx = 10;
uint8_t BUS = 0x01;
uint8_t  INPUTS[] = {2,3,4,5};
uint8_t OUTPUTS[] = {6,7,8,9};


void setup() {
  delay(3000);
  Serial.begin(115200);  //0x1C200
  BaudDelay =   (20000000/SerBaud);
  if(BaudDelay > 16383){// Issue range of (unsigned int)
    Serial.println("Your COMM speed is very slow, change it !\nSystem Failed during calculation.");
  }else{ Serial1.begin(SerBaud); }
    
  delay(1000);
  Serial.println(BaudDelay);
  for(uint8_t i = 0; i < 4 ; i++){
    pinMode(INPUTS[i],INPUT);
    pinMode(OUTPUTS[i],OUTPUT);
  }
  Serial.println("READY !");
}

void loop() {
 if(Serial1.available() > 0){
  uint8_t c = Serial1.read();
  ndx = 0;
  if(c != BUS){
    while(Serial1.available() > 0){
      c = Serial1.read();
      delayMicroseconds(BaudDelay);
      ndx = 0;
      }
    }else{
      msg[0] = c ;
      ndx ++ ;
      while(Serial1.available() > 0){
        msg[ndx] = (uint8_t)Serial1.read();
        ndx++;
        delayMicroseconds(BaudDelay);
      }
      getDO();
    }
  }    
 }

 void getDO(){
  /*
  for(uint8_t i = 0; i < ndx; i++){
    if(msg[i] < 0x10) Serial.print("0");
    Serial.print(msg[i]);
    }
  Serial.println(); */
  uint16_t eCRC = CRC(ndx);
  if(eCRC < 1){
    //Serial.println(eCRC,DEC);
    if(msg[1] == 0x05){
      if(msg[4]==0xFF){
        digitalWriteFast(OUTPUTS[msg[3]],HIGH);
        }else{
          digitalWriteFast(OUTPUTS[msg[3]],LOW);
          }
      ADDCRC(0x06);
    }else if(msg[1] == 0x04){
      for(uint8_t i = 0;i < 4 ;i++){
        //burda kaldık
      }
    }
    
  }else{Serial.print("Wrong CRC :");Serial.println(eCRC,HEX);}
}
uint16_t CRC(uint8_t len){
    uint16_t crc = 0xFFFF;
    for(int pos = 0; pos < len;pos++){
      crc ^= (uint16_t)msg[pos];
      for(uint8_t i=8; i>0;i--){
        if((crc & 0x0001) != 0){
          crc >>= 1;
          crc ^= 0xA001;
        }else{crc >>= 1;      }
      }
    }
    return crc;
  }
void ADDCRC( uint8_t len){
  uint16_t crc = CRC(len);
  msg[len] = LO(crc);
  msg[len+1] = HI(crc);
  Serial1.write(msg,len+2);
  for(uint8_t i = 0; i < 0x40;i ++) msg[i] = 0x00 ;
  ndx = 0;
}
Remember to change the BaudRate value (most of the converter cannot be provided). (PC: side :I used an Moxa UPORT 1150, Teensy side: Automatic Flow detect-Isolated(ADUM) UART-RS485 Converter )

Python codes running smoothly at speeds of 921600bps :

Code:
import serial
import time
import binascii

ser = serial.Serial("com2",921600)#Max Speed isn't 921600bps
quer = "01050000ff008c3a",  "010500000000cdca"

for i in range(10):
    for e in quer :
        ser.write(binascii.unhexlify(e))
        time.sleep(0.0000)#Use function as delay
        print i,">> ",e,"<< ",binascii.hexlify(ser.read(ser.inWaiting()))
        time.sleep(0.0000)#Use function as delay
ser.close()

And PIN0 (Teensy pin 6) :

mbusOUT.png

IMPORTANT NOTES :
Can't use RX signal as flag (examp: 115200bps, you will not be able to commit time 86 micro seconds. Here we have two characters, but in reality there are 1.5 character spacing. transmission hardware does not respond on such short time.)

The above code in a variable named ndx(mean received message length(index)). This is your most important flag.Each time you need to make sure that the value of this variable. Otherwise it will return a CRC error.

I didn't write all the codes because "this section is required to be of personal". For example, the matshusita industrial processors does not directly access the data addresses. Before, you must create a link to the RAM address. Although it seems like a standard protocol Modbus, in practice it is a different character (data read permission, write permission, system priority, to exceed the address, etc.).
*** Don't use this code an 16Mhz arduino or another one !
I hope it will help someone.
Regards and have a nice day.
 
Last edited:
Hi all did anyone successfully get modbus tcp running on the teensy 3.5 or 3.6, I have a project to use the teensy as remote slave to drive stepper motors and a plc as modbus tcp master, I would like to know if modbus tcp is working or should I use rtu instead....please help
 
I would like to know before I buy, I havnt bought anything yet just researching but I would like to use modbus tcp on this board

Hi, you can do the Web interface with Teensy. However, you should use a faster processor for package tracking. A Minimum of two processors are used. The processor that handles the package is typically FPGA. It can be used on processors that support the hardware Ethernet interface (some Cortex M4 processor, frequency >= 100 Mhz). Your transmission speed cannot exceed 1megabit speed unless you are using FPGA.
What really happens is that : serial processors are not used as bridges or protocol converters (limits are low, such as computer processors).

The delay will not exceed the FTD value(FTD = Force Transmit Delay, min value = 1 ms). It's very hard to do with standard Ethernet to SPI converters. The speed of the processor is not that important, you need to process high speed I-O(input-output).

Buy and use the transducer (prices between $ 17-25) Example...

Life is short,life is short, not worth it!

Best regards, have nice day.
 
Here's my first attempt to clean up this library, in a way that won't interfere with its support for any other boards.

https://github.com/PaulStoffregen/Modbus-Master-Slave-for-Arduino

Hopefully they will be willing to merge these changes back into their copy.

Please let me know if this works for you? I'll wait for your confirmation before submitting a pull request back to the original code...

Hi Paul,
I tried your code using Teensy 3.6 at Serial2 (pin 9,10) which connected to a TTL to USB shield. I got no response from the Teensy.
Does your code work with Teensy 3.6?

John
 
Just a quick skim here - if it is working for T_3.5 it should work if the situation is connected the same for T_3.6 - but the TTL must be at 3.3V not 5V for T_3.6. Perhaps this has been tried/resolved - maybe the Rx & Tx are swapped - and GND must be connected
 
Just a quick skim here - if it is working for T_3.5 it should work if the situation is connected the same for T_3.6 - but the TTL must be at 3.3V not 5V for T_3.6. Perhaps this has been tried/resolved - maybe the Rx & Tx are swapped - and GND must be connected

Hi defragster, Thanks for the quick response. I have not tried the T 3.5. Not sure if the lib works for 3.5/3.6. it seems Kampfwurst could not get it working with T_3.5.
Wonder if anyone successfully running the lib using T3.5/3.6. BTW, I checked the TTL2USB shield connection using Serial2.print etc. It is connected o.k.
John C
 
Hi, you can do the Web interface with Teensy. However, you should use a faster processor for package tracking. A Minimum of two processors are used. The processor that handles the package is typically FPGA. It can be used on processors that support the hardware Ethernet interface (some Cortex M4 processor, frequency >= 100 Mhz). Your transmission speed cannot exceed 1megabit speed unless you are using FPGA.
What really happens is that : serial processors are not used as bridges or protocol converters (limits are low, such as computer processors).

The delay will not exceed the FTD value(FTD = Force Transmit Delay, min value = 1 ms). It's very hard to do with standard Ethernet to SPI converters. The speed of the processor is not that important, you need to process high speed I-O(input-output).

Buy and use the transducer (prices between $ 17-25) Example...

Life is short,life is short, not worth it!

Best regards, have nice day.

Thanx I appreciate the help,

Can anyone confirm Modbus rtu working with teensy 3.6 or 3.5
it seems some are having issues with the modified libraries. Has anyone got it working, I want to use this for remote steeper control connected to a raspberry pi running Codesys as plc.
 
Hello - Something I'm noticing is that my TX enable pin is being ignored.. As such. I'm using Paul's version of the library at https://github.com/PaulStoffregen/Modbus-Master-Slave-for-Arduino

Code:
Modbus slave(1,1,TXEN); // Third param TXEN is ignored for whatever reason
But when I do THIS, everything works fine. I'm using the hardware serial port on a Teensy 3.2, and for whatever reason my TX and RX polarity are flipped.
Code:
void setup() {
  Serial1.transmitterEnable(TXEN); // I have to set the TXEN HERE instead.
  slave.begin(38400, SERIAL_8O1_RXINV_TXINV); // baud-rate at 38400
}

I realize that in some place in my system, the serial polarity is getting flipped. I'm using a CLICK PLC from automation direct, over it's dedicated RS485 port. I don't know if I have a doofy PLC, a doofy line driver on the board my Teensy is mounted to, or what,but I need to flip both RX and TX polarity in the serial slave.begin statement. It just works. I of course assume I just have the two RS-485 lines switched, but apparently my understanding of how this works is wrong (any enlightenment would be appreciated)

This is what the scope is putting out at the Teensy's serial1 IN (Pin 0)

RS485_Andy.png

Yellow is TXEN on pin 2, blue is serial1 TX on 1. At it's default serial config, it doesn't work. At all. Flipped it's all working and glorious.

Thoughts on this and the TXEN being ignored?
 
Hi all,

There are a lot of RS485 modbus programs but the code below works out of the box and is fully tested on a T4.0, T4.1 and ESP32C3 for the ESP32C3 you need only change the Serial5 to Serial0.
Look at the SensorModbusMaster for the modbus registers.

Used modbus converter is a Grove RS485 see picture.
grove.jpeg



Have fun and it's totaly free!

Best regards,
Johan
Code:
// Modbus RS485
// J.G. Holstein @ 2023

#include <SensorModbusMaster.h>
// Define the sensor's ID modbus address
modbusMaster modbus1;
//modbusMaster modbus2;
//modbusMaster modbus3;

unsigned long poll = 100;
unsigned long previousMillis = 0;

// Set ID's for modbus device
byte modbusAddress1 = 1;    // SlaveID 1
//byte modbusAddress2 = 2;  // SlaveID 2
//byte modbusAddress3 = 3;  // SlaveID 3

float M1Measure;
String M1CapacityUnit = " ";

void setup() {
  Serial.begin(115200);             // Main serial port for debugging via USB Serial Monitor
  Serial5.begin(19200, SERIAL_8E1);  // Teensy 4.0 port for communicating with modbus device

  modbus1.begin(modbusAddress1, &Serial5);    // Device ID1
  //modbus2.begin(modbusAddress2, &Serial5);  // Device ID2
  //modbus3.begin(modbusAddress3, &Serial5);  // Device ID3

}

void loop() {

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= poll)
  {
    M1Measure = modbus1.float32FromRegister(0x03, 41216, bigEndian);
    if (modbus1.getRegisters(0x03, 0x81F8, 5)) {
      M1CapacityUnit = modbus1.StringFromFrame(7);
    }
    Serial.print("Measure M1 : ");
    Serial.print(M1Measure);
    Serial.print(",");
    Serial.print("M1CapacityUnit M1: ");
    Serial.print(M1CapacityUnit);
    Serial.print(",");
    previousMillis = currentMillis;
  }
}
 
Back
Top