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 =( 11111111) D5=1,D6=1,D7=1,D8=1,D9=1,D10=1,D11=1,D12=1
000 =( 00000000) D5=0,D6=01,D7=0,D8=0,D9=0,D10=0,D11=0,D12=0
127 =( 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
#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);
}