Do you know EIA-485 and DMX-512? Part 1

In the 1980s and 1990s, a recurring topic in computer magazines was the question of whether the serial interface or the parallel interface was better suited for external data transmission. The serial or RS232 interface (UART= Universal Asynchronous Receiver Transmitter) on the PC was mainly used for remote data transmission with modems (initially in the telex network), the parallel Centronics interface delivered data to the printer.

You know the result of the race for higher speeds: Internally in the processor, and on the mainboard, the width of the data busses has become wider and wider, externally the parallel interface has been displaced by USB (=Universal Serial Bus) and the networks. But the RS-232 interface has also largely disappeared because it had some considerable weaknesses: limited range and connection only between two devices.

As an intermediate step to today's networks, there were further developments of the serial interface RS-232, which are still used today: Among others, the RS-485 interface (the current standards are updated under the name EIA-485) bridges greater distances of up to 1000m due to the symmetrical structure of the signals on the two lines and enables the series connection of up to 32 devices, as long as the last devices in each case have a terminating resistor. As is so often the case, Wikipedia has very informative pages on UART, RS-232 and EIA-485 for those who want to know more.

In order to use the RS-485 interface, which is not available on the hardware side of today's computers, I bought a cheap USB-RS-485 adapter for the PC.

RS-485 USB adapter

For the micro controllers of the Arduino Uno type or compatible as well as the similar D1 R1 (with ESP8266) and D1 R32 (with ESP32) there is a corresponding shield, for the Raspberry Pi a HAT (Hardware Attached on Top).

RS-485 Pi Hat

In order to familiarise myself with this topic, which was new to me, I first collected information, e.g. on the homepage of our supplier for the Shield or the HAT: zihatec.

From there I downloaded the data sheet, application note and example sketches. But since I couldn't get the example to work initially, I want to take a different approach to the explanation:

First of all, what is to be achieved?

This introductory article is about the realisation of a MODBUS slave, as MODBUS is one of the most important applications for RS-485; it is an open protocol and has become a De-facto-Standard for programmable logic controllers (PLCs) in the industry.

A MODBUS system always requires a master and at least one slave. It is possible to implement both a master and slaves with the shield. However, when using a micro controller with Atmel 328, it is only possible to implement a master to a limited extent, as the RAM memory is very limited. For this reason, a MODBUS slave is implemented in the example and a PC is used as the master. 

Practically, the master would be, for example, a PLC or a central control computer to which various machines or devices with RS485 interfaces are connected as slaves. The master can now sequentially query and control all connected devices on the RS485 BUS via the MODBUS protocol. The units all have different bus addresses for this purpose.

The example sketch sends six analogue signals and the digital signal of a push button via the RS-485 connection to the PC and receives from there the information whether a LED should be on or off.

To do this, I plugged the shield onto the micro controller and connected the following circuit with six potentiometers to the analogue inputs A0 to A5, a LED with a series resistor to the digital pin 12 and a button with a pull-down resistor to pin 7.

Circulation

Fritzing Schedule

There are still some settings to be adjusted on the shield. This is done on the one hand with short-circuit plugs (jumpers) and on the other hand with the help of small switches (DIP switches, "mouse piano"). The labelling on the board is really helpful.

For our Micro Controller with Atmega 328 we plug the single jumper J1 to 5V, in the row next to pins 0 to 7 we plug the connection of the RX line to port 0 and the TX line to port 1, the third jumper is not needed for automatic RX/TX switching.

UART Pins

Attention: In this experiment we use the same pins as for the USB connection to the Arduino IDE. Therefore, either the entire shield or these two pins must be removed for the duration of programming the micro controller (uploading the sketch). The serial monitor in the IDE cannot be used.


Please set the DIP switches as shown in the following picture:

DIP Switches

The most important micro switch is the first one on SW 3: This activates the terminating resistor.

I modified Hartmut Wendt's sketch minimally, namely at the baud rate 9600 and in the void setup() with a short LED test: (Download the sketch folder with 3 files):

  /*
  * Test program for Arduino RS422/RS485 Shield
  * Version 1.0
  * Copyright (C) 2018 Hartmut Wendt www.zihatec.de
  *  
  * (based on sources of https://github.com/angeloc/simplemodbusng)
  *  
  *
  * 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/>.
 */  
 
 #include "SimpleModbusSlave.h"
 #define ledPin 12   // led
 #define buttonPin 7 // push button
 
 
 // Using the enum instruction allows for an easy method for adding and
 // removing registers. Doing it this way saves you #defining the size
 // of your slaves register array each time you want to add more registers
 // and at a glimpse informs you of your slaves register layout.
 
 //////////////// registers of your slave ///////////////////
 enum
 {    
   // just add or remove registers and your good to go...
   // The first register starts at address 0
   ADC0,    
   ADC1,        
   ADC2,
   ADC3,
   ADC4,
   ADC5,  
   LED_STATE,
   BUTTON_STATE,
   TOTAL_ERRORS,
   // leave this one
   TOTAL_REGS_SIZE
   // total number of registers for function 3 and 16 share the same register array
 };
 
 unsigned int holdingRegs[TOTAL_REGS_SIZE]; // function 3 and 16 register array
 ////////////////////////////////////////////////////////////
 
 void setup()
 {
   modbus_configure(960016TOTAL_REGS_SIZE0);    // 115200
   pinMode(ledPinOUTPUT);
   pinMode(buttonPinINPUT);
 //added as a first test  
   digitalWrite(ledPin,HIGH);
   delay(1000);
   digitalWrite(ledPin,LOW);  
 }
 
 void loop()
 {
   // modbus_update() is the only method used in loop(). It returns the total error
   // count since the slave started. You don't have to use it but it's useful
   // for fault finding by the modbus master.
   holdingRegs[TOTAL_ERRORS= modbus_update(holdingRegs);
   for (byte i = 0i < 6i++)
  {
     holdingRegs[i= analogRead(i);
     delayMicroseconds(50);        
  }
   
   byte buttonState = digitalRead(buttonPin); // read button states
   
   // assign the buttonState value to the holding register
   holdingRegs[BUTTON_STATE= buttonState;
   
   // read the LED_STATE register value and set the onboard LED high or low with function 16
   byte ledState = holdingRegs[LED_STATE];
   
   if (ledState// set led
  {          
     digitalWrite(ledPinHIGH);
  }  
   else if (ledState == 0// reset led
  {
     digitalWrite(ledPinLOW);
     holdingRegs[LED_STATE= 0;
  }
 }

On the PC side, I plugged the USB-RS-485 adapter into a USB port and installed the ModbusTester programme.

The serial connection is quite simple: two cables establish the connection of the respective ports A-A and B-B. For long lines, the cables should be twisted and the rule of thumb is that cable length times transmission rate should not be greater than 100 million, e.g. 50m and max. 2Mbit/s. 

With the Modbus Tester programme, it is important to set the same baud rate. The virtual COM port used is displayed under Windows settings and must be selected in the pull-down menu.

Output of values; In this screenshot, after clicking Read (bottom right), the values I set on the potentiometers are displayed in registers 1 to 6 as well as the state of the push-button in register 8.

Input of commands: Write sends the value of register 7 (here 1) to the micro controller to switch on the LED. To switch off, preselect 0 and press Write.

MODBUS Tester

Of course, this is only a first test of the devices used. Serious applications such as the integration of devices on watercraft according to NMEA-0183 (GPS etc.) can be found on the zihatec site. In a second part, I would like to turn to lighting technology with DMX. I also use the RS-485 shield for this.

For arduinoProjects for beginners

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN