Pages: [1]   Go Down
Author Topic: Working RS485 sketches wanted  (Read 4291 times)
0 Members and 1 Guest are viewing this topic.
Lake District, UK
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Electronics needs smoke to work, if it escapes its broken
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Would one of you kind individuals help me in obtaining a working multidrop sketch of Nick Gammons RS485 master and slave sketches.
OR
is there somthing i am missing with his two example sketches on his website.
I must admit i was hoping for plug and play, the RS485 is just a small part of my overall aim.

Im wanting to set up initially with one master and one slave on Arduino Uno's
my goal is to build somthing like a WAGO programmable controller/PLC for use in a homebuilt submersible vehicle (ROV)

Ive gone through the pain of discovering i had to go back to IDE version 0023 to get it to upload i also installed the IDE version 1.0 Sreial library into the Ver 023 lib folder to get the sketches to upload without errors.
I have 2 PCBs made up as per Nicks drawing with Max485 Ics and they are linked with 2m of CAT5 twisted pair wire.

Am i able to monitor the boards using the USB and the serial monitor or does this clash with the RS485 operation.
do i have to create data to send -my understanding of the code is that the master is reading its analogue port A0 and if it changes it transmits its response to the slave - i have left the analogue input floating so it should be jumping all over the place creating good data.

the slave just sits there and if i connect to it with the serial monitor, there is nothing from it. (baudrate and ports were set up correctly)

any assistance would be greatfully appreciated.

Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 499
Posts: 19065
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

He's referring to this page:

http://www.gammon.com.au/forum/?id=11428

This circuit:



@OP: don't make people work too hard to help you. Give them some links and clues about what you are asking.

Quote
Ive gone through the pain of discovering i had to go back to IDE version 0023 to get it to upload

It was written a while ago. I deleted the first line of the example sketch, namely:

Code:
#include "WConstants.h"

Then it compiled OK under version 1.0.1 of the IDE.



How about posting the actual master and slave sketch you are trying? You should be able to get them both to compile under 1.0.1 using the method I described above.
Logged


Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 635
Posts: 50263
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
i have left the analogue input floating so it should be jumping all over the place creating good data.
Random noise != good data.
Logged

Lake District, UK
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Electronics needs smoke to work, if it escapes its broken
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It was a handy way of getting it to produce values without having to connect up a whole load of test instruments just to acheive the same outcome
Logged

Lake District, UK
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Electronics needs smoke to work, if it escapes its broken
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i didnt pick up on was the difference between Hardware and Software and how it pertained to my setup.
Ie. if you used the hardware config it was the USB link i was using to upload the sketch etc.

I did discover it had been working all along, I quickly coupled the circuit together and must have skimmed over the part indicating the LED on pin 11. once inserted the Uno pair started working as expected.

I have a couple of quick questions if you don’t mind.
Im not able to find a way of breaking into the code on the master to allow PC interface/interaction, i want to be able to send and receive serial data from the master.

I have added a second serial connection in the code with a 9600 baud rate and it works at sending and receiving from the master whilst its running the 485 link however i don’t quite understand how to write or read data to be used in the 485 message.


The second question is how to understand the slaves return message, are you able to provide an explanation as to how this  is achieved.
as far as i can figure out  there is a return response which the master hears and hold LED on pin13 low unless there is a broken link, corrupted message or i guess a time out.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 499
Posts: 19065
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Im not able to find a way of breaking into the code on the master to allow PC interface/interaction, i want to be able to send and receive serial data from the master.

I don't know what you mean by "breaking into the code". If you want to have device-to-device and also communicate with a PC you probably need two serial connections (eg. software serial and hardware serial).

Quote
I have added a second serial connection in the code with a 9600 baud rate and it works at sending and receiving from the master whilst its running the 485 link however i don’t quite understand how to write or read data to be used in the 485 message.

I don't understand that question, if it is a question.

Quote
The second question is how to understand the slaves return message, are you able to provide an explanation as to how this  is achieved.
as far as i can figure out  there is a return response which the master hears and hold LED on pin13 low unless there is a broken link, corrupted message or i guess a time out.

As far as the RS485 stuff goes, with only 2 wires you can only have one master. So the master has to send a message "addressed" to one slave and stop being a master. Then the addressed slave becomes a master and replies. Then the master resumes being a master again. You would need some sort of time-out in case the slave doesn't reply.
Logged


Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17301
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you are struggling with two different concepts. First is the RS485 standard which just defines the physical electrical properties of the communications hardware that makes up a RS485 link. With the proper external chips, wire, termination resistors, and possibly a little tweaking of the serial driver you use to switch from transmit mode to receive mode that is pretty much a done deal, many have and are doing it and much should be avalible to help you implement this physical communications link.

 The second concept is what software communications protocol will you use for stuff you hook up to your RS485 link? There is no single standard software protocol that works, but rather several, and of course your free to design your own protocol that the master and slave devices will utilize in their software design. Modbus is one popular protocol often using RS485 type links.

So there are no simple answers for you questions. If you are trying to communicate to existing slave devices then you need to find out what software protocol they are expecting to be used with. If not you are free to design your own or just find a decent Modbus library and utilize that protocol.

Lefty
Logged

Lake District, UK
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Electronics needs smoke to work, if it escapes its broken
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Lefty/Mike
Your help has been really useful.
i am aware from having worked offshore for the last ten years that what i wanted is possible i just needed pointed in the right direction.
i think its peoples lazy description of the communication protocol which has confused me.
we use RS485 links to talk to an array of underwater instruments such as dopler, sonar, altimeter, bathy, profilers etc, many of which are on a RS485 bus called arcnet, believe it or not they all pass data back at very high speeds. Eg, a sonar would be useless if it couldnt return a message showing its signal its returns.  The general description is to call it RS485 instead of actually saying what communication protocol it is using.

*second serial port.
i tried to describe my intention to use both a hardware and software serial link in the master so that i could communicate via a PC to the BUS, i appolegise for any confusion.  I have come to the conclusion im really crap at asking questions, the guys on the forum seem to have dificulty understanding mine.
I do appreciate you are all unpaid for your assistance on the forum and have a life.

I have taken a look at modbus and over the next week or so will have a go at getting it to work for my simple Arduino programable logic controller.

I want to use RS485 because i want communication with devices over a 100m distance.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

good,i didnt pick up on was the difference between Hardware and Software and how it pertained to my setup.
Logged

Lake District, UK
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Electronics needs smoke to work, if it escapes its broken
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Chaps,
This is how far i have managed to get
Basic RS485 Master/Slave example from Nick Gammons code.
The changes made are the introduction of a bit weighted digital output on the slave and a PC host serial connection to the master module.

The design idea is to be able to use a host PC with a USB connection to a master module to control several slaves for use in hobby based micro controlled logical interface, this will differ from a programmable logic controller PLC as the code will be written to the device once and then the multiple devices will have various fixed functions which will only respond when controlled from the master commands.

Industrial systems would be like the Wago or an intelligent relay for example.
this system/project will be perfect for home automation, model railways, flight sims, robotic control to name but a few uses.

C# is not my preferred programming language so if its crap code, get over it

You need to do the following prerequisites before you can use this code.

I used Nick Gammons schematic for setting up my RS485 link
The code was loaded onto two separate Arduino Uno’s – master on one slave on the other

The Software serial version of the Arduino RS485 code was used – this leaves the USB serial link free for programming and interfacing with the devices
Nick code example used an analogue input to generate a value to be transmitted to the slave as a message, I commented this out and set up a variable to hold the incoming value – this value is used to hold the value to be used for driving the digital outputs D5,D6,D7,D8,D9,D10,D11,D12 these outputs are bit weighted, ie
255 smiley-cry 11111111) D5=1,D6=1,D7=1,D8=1,D9=1,D10=1,D11=1,D12=1
000 smiley-cry 00000000) D5=0,D6=01,D7=0,D8=0,D9=0,D10=0,D11=0,D12=0
127 smiley-cry 11111111) D5=1,D6=0,D7=0,D8=0,D9=0,D10=0,D11=0,D12=0
Got it – cool    don’t forget to attach LEDs to the digital outputs (with a load resistor).
D13 was left as an error indication LED
It’s a pain writing to two devices on one machine, remember to change serial port between uploading to devices – two masters or two slaves isn’t a good start, been there.

The initial problems I had using Nicks code was I didn’t read his instruction fully or correctly, sorry Nick. This led to me misunderstanding that using the hardware example was using the same pins as the USB port the second issue was I built the MAX485 physical link and for some reason felt that was it and it should work – I needed an LED on pin D11 of the master and an analogue input A0 on the slave.
Don’t make the same mistakes I made, getting impatient with Angry Mike,PaulS and Nick Gammon is not a good move, im still left out in the dark, sorry guys.

The next stage will be to add more Slave units for analogue input, analogue/PWM output and digital input.
On completion of basic operation, I plan to use the various modbus examples to actually incorporate a proper communication protocol.

Again don’t follow in my footsteps and ask general questions about how to use RS485 for communication, the guys on the forum are unforgiving and will eat you alive, yep we all know there are various communication methods/protocols when using RS485 links – so spell it out.  Thanks to Lefty for intervening and calming the waters.

Ok so once set up
Open the serial monitor tool and send digital values to the master
The format is as follows:
O***  where O is capital letter “O” followed by 0 to 255 formatted to 3 digits, 0 = 000 and 255 = 255
The modified master code is as follows
Code:

#include "WConstants.h"
#include <NewSoftSerial.h>
#include "RS485_protocol.h"

NewSoftSerial rs485 (2, 3);  // receive pin, transmit pin
const byte ENABLE_PIN = 4;
int channel = 0;
int data=0;
const byte LED_PIN = 13;
int incomingByte=0; // for incoming serial data
int thousands=0; int hundreds =0; int tens =0; int ones=0;
int inByte=0;
// callback routines
  
void fWrite (const byte what)
  {
  rs485.print (what);  
  }
  
int fAvailable ()
  {
  return rs485.available ();  
  }

int fRead ()
  {
  return rs485.read ();  
  }

void setup()
{
  rs485.begin (28800);
   Serial.begin(9600);
  pinMode (ENABLE_PIN, OUTPUT);  // driver output enable
  pinMode (LED_PIN, OUTPUT);  // built-in LED
}  // end of setup
  
byte old_level = 0;

void loop()
{

  // read potentiometer

 // byte level = analogRead (0) / 4;// commented out as it is now variable being written
  byte level = (incomingByte);
  // Serial.print(level);// print to serial monitor - for testing only
  
   if (Serial.available() > 0) {       //read value from host PC
    hostprotocol();
   }
  // no change? forget it
  if (level == old_level)
    return;
      
  // assemble message
  byte msg [] = {
     1,    // device 1
     2,    // turn light on
     level // to what level
  };

  // send to slave  
  digitalWrite (ENABLE_PIN, HIGH);  // enable sending
  sendMsg (fWrite, msg, sizeof msg);
  delayMicroseconds (660);
  digitalWrite (ENABLE_PIN, LOW);  // disable sending
  
// receive response  
  byte buf [20];
  byte received = recvMsg (fAvailable, fRead, buf, sizeof buf);
 
  digitalWrite (LED_PIN, received == 0);  // turn on LED if error  
  
  // only send once per successful change
  if (received)
{
    if (buf [0] != channel)
      return;  // not my device
      
    if (buf [1] != 2)
      return;  // unknown command
    
byte msg [] = {
       0,  // device 0 (master)
       data,  // turn light on command received
       //data

};
  
    old_level = level;

}

}  // end of loop

void hostprotocol()      //Serial commands received from host
{
  inByte = Serial.read();
    switch (inByte)
    {
      
 case 79: //O  out
 
        DigitalOut();
   break;
  
  }
}
void DigitalOut() {
    
 // send data only when you receive data:
Serial.print("Digital OK");
  
 // only if there are bytes in the serial buffer execute the following code
  if(Serial.available()) {
  
     //keep reading and printing from serial untill there are bytes in the serial buffer
     //while (Serial.available()>0){
       if (Serial.available()>2){ // got 3 characters
        
// assume comes in as hundreds, tens, ones
hundreds = Serial.read() - 0x30;  // read the byte & convert from ASCII to a number
tens = Serial.read() - 0x30;
ones = Serial.read() - 0x30;

// now make into a digit
incomingByte =  hundreds*100 + tens*10 + ones;
    
 }
 Serial.print(incomingByte);
    }
 
//int value = (incomingByte);
 }


Logged

Lake District, UK
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Electronics needs smoke to work, if it escapes its broken
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

2nd part

The modified RS485 slave code is as follows

Code:

#include "WConstants.h"
#include <NewSoftSerial.h>
#include "RS485_protocol.h"

NewSoftSerial rs485 (2, 3);  // receive pin, transmit pin
const byte ENABLE_PIN = 4;
int channel = 1;// Device ID

int Inputvalue =0; // Input value from Master

int ledPin = 12;// digital bit weighted outputs
int ledPin1 = 11;
int ledPin2 = 10;
int ledPin3 = 9;
int ledPin4 = 8;
int ledPin5 = 7;
int ledPin6 = 6;
int ledPin7 = 5;


void fWrite (const byte what)
  {
  rs485.print (what); 
  }
 
int fAvailable ()
  {
  return rs485.available (); 
  }

int fRead ()
  {
  return rs485.read (); 
  }
 
void setup()
{
  rs485.begin (28800);
  pinMode (ENABLE_PIN, OUTPUT);  // driver output enable
  //Bit weighted gigital outputs
  pinMode(ledPin, OUTPUT);  // initialize the LED pin as an output:
  pinMode(ledPin1, OUTPUT); // initialize the LED pin as an output:
  pinMode(ledPin2, OUTPUT); // initialize the LED pin as an output:
  pinMode(ledPin3, OUTPUT); // initialize the LED pin as an output:
  pinMode(ledPin4, OUTPUT); // initialize the LED pin as an output:
  pinMode(ledPin5, OUTPUT); // initialize the LED pin as an output:
  pinMode(ledPin6, OUTPUT); // initialize the LED pin as an output:
  pinMode(ledPin7, OUTPUT); // initialize the LED pin as an output:
}

void loop()
{
  byte buf [20];
 
  byte received = recvMsg (fAvailable, fRead, buf, sizeof (buf) - 1);
 
  if (received)
    {
    if (buf [0] != channel)
      return;  // not my device
     
    if (buf [1] != 2)
      return;  // unknown command
   
    byte msg [] = {
       0,  // device 0 (master)
       3,  // turn light on command received
    };
   
    delay (5);  // give the master a moment to prepare to receive
    digitalWrite (ENABLE_PIN, HIGH);  // enable sending
    sendMsg (fWrite, msg, sizeof msg);
    digitalWrite (ENABLE_PIN, LOW);  // disable sending
   
    //analogWrite (11, buf [2]);  // set light level AS WAS  JT

    Inputvalue =buf [2];// write register value to a variable JT

   // digital bit weighted outputs
   digitalWrite(ledPin, (Inputvalue >> 0 )% 2);// LSB
   digitalWrite(ledPin1, (Inputvalue >> 1)% 2);
   digitalWrite(ledPin2, (Inputvalue >> 2)% 2);
   digitalWrite(ledPin3, (Inputvalue >> 3)% 2);
   digitalWrite(ledPin4, (Inputvalue >> 4) % 2);
   digitalWrite(ledPin5, (Inputvalue >> 5) % 2);
   digitalWrite(ledPin6, (Inputvalue >> 6) % 2);
   digitalWrite(ledPin7, (Inputvalue >> 7) % 2); // MSB
   
   }  // end if something received
   
}  // end of loop
A Picture of the PCB layout for the MAX485 and a drawing showing the various connections will be provided later.





What has been achieved?

You can now drive 8 relays for example which are 1000m away from your PC over 2 wires (twisted pair TWP) a line resistor of 120 ohms will be needed between the A/B wire connections on both ends of the wire link.  Look at LVR.com where Jan Alexson explains serial communication and RS485 at great depth- especially calculating the line resistor for a given wire link/distance
(The remote board will obviously require its own power)

Issues
Data type is wrong for data value being transmitted; currently it’s a byte where the input from the host PC is a formatted string/decimal value.
Where the host PC sends O237 the slave works but when the value is less than 100 the slave doesn’t change.
In the slave code the value is parsed to give 100s, 10s and units, it is not needed the value should be able to be used directly.  This change has not been implemented yet.
Logged

Lake District, UK
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Electronics needs smoke to work, if it escapes its broken
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

With Nicks code above (all be it played with by me)
can someone please tell me how i can get to serial.print the received slave message from the master.
it obviously receives somthing as the Led on pin d13 does not light up indicating that there is no error and that the messege was acknowledged.

I would like the slave to pass messages back when polled and i belive this is already in place, i would like to be able to have several bytes sent in the return message which can be written to variable so that i can output them to the Host (pc connected to master module).
thanks
J.
Logged

Topsham, Vermont USA
Offline Offline
Edison Member
*
Karma: 33
Posts: 1926
... in The Woods In Vermont
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, the http://ArduinoInfo.Info WIKI now has a working RS485 example showing hardware, software and data direction control:

http://arduino-info.wikispaces.com/SoftwareSerialRS485Example

Logged

Regards, Terry King terry@yourduino.com  - Check great prices, devices and Arduino-related boards at http://YourDuino.com
HOW-TO: http://ArduinoInfo.Info

Pages: [1]   Go Up
Jump to: