Rs485 Rolling Master vs. MEGA2560 HWSerial help please...

Hi There,

Welcome for All, this is my first post. :slight_smile:

I would like to make a small Rs485 lan with Nick Gammon’s Rs485 Rolling Master packet transmit protocol.

Dear Nick, Thank you for your great works! These are very-very helpful for us! :slight_smile: :slight_smile: :slight_smile:

I have already made connection with 2pcs of Mega2560 and they communicating perfectly with software serial.

I really sorry, but I need to use the softSerial port for other communication (arduino GSM), therefore I would like to change the RS485 to Serial2 HW port.

I changed the labels from SoftSerial to Serial2 where I found in the origial example code…
I rearranged the port pins RX,TX to the proper place…

All of the debug LEDs functioning, the “searching leds” blinks, but the modules can not communicate…

I think it need more modification than I can do…

Here is the modificated source code:

/*
 Multi-drop RS485 device control demo.

 Devised and written by Nick Gammon.
 Date: 7 September 2015
 Version: 1.0

 Licence: Released for public use.

 For RS485_non_blocking library see: http://www.gammon.com.au/forum/?id=11428
 For JKISS32 see: http://forum.arduino.cc/index.php?topic=263849.0
*/

#include <RS485_non_blocking.h>
#include <EEPROM.h>


// the data we broadcast to each other device
struct
  {
  byte address;
  byte switches [10];
  int  status;
  }  message;

const unsigned long BAUD_RATE = 4800;
const float TIME_PER_BYTE = 1.0 / (BAUD_RATE / 10.0);  // seconds per sending one byte
const unsigned long PACKET_LENGTH = ((sizeof (message) * 2) + 6); // 2 bytes per payload byte plus STX/ETC/CRC
const unsigned long PACKET_TIME =  TIME_PER_BYTE * PACKET_LENGTH * 1000000;  // microseconds

// software serial pins
// transmit enable
const byte XMIT_ENABLE_PIN = 5;

// debugging pins
const byte OK_PIN = 6;
const byte TIMEOUT_PIN = 7;
const byte SEND_PIN = 8;
const byte SEARCHING_PIN = 9;
const byte ERROR_PIN = 10;

// action pins (demo)
const byte LED_PIN = 13;
const byte SWITCH_PIN = A0;


// times in microseconds
const unsigned long TIME_BETWEEN_MESSAGES = 3000;
unsigned long noMessagesTimeout;

byte nextAddress;
unsigned long lastMessageTime;
unsigned long lastCommsTime;
unsigned long randomTime;


// what state we are in
enum {
   STATE_NO_DEVICES,
   STATE_RECENT_RESPONSE,
   STATE_TIMED_OUT,
} state;

// callbacks for the non-blocking RS485 library
size_t fWrite (const byte what)
  {
  Serial2.write (what);
  }

int fAvailable ()
  {
  return Serial2.available ();
  }

int fRead ()
  {
  lastCommsTime = micros ();
  return Serial2.read ();
  }

// RS485 library instance
RS485 myChannel (fRead, fAvailable, fWrite, 20);

// from EEPROM
byte myAddress;        // who we are
byte numberOfDevices;  // maximum devices on the bus

// Initial seed for JKISS32
static unsigned long x = 123456789,
                     y = 234567891,
                     z = 345678912,
                     w = 456789123,
                     c = 0;

// Simple Random Number Generator
unsigned long JKISS32 ()
  {
  long t;
  y ^= y << 5;
  y ^= y >> 7;
  y ^= y << 22;
  t = z + w + c;
  z = w;
  c = t < 0;
  w = t & 2147483647;
  x += 1411392427;
  return x + y + w;
  }  // end of JKISS32

void Seed_JKISS32 (const unsigned long newseed)
  {
  if (newseed != 0)
    {
    x = 123456789;
    y = newseed;
    z = 345678912;
    w = 456789123;
    c = 0;
    }
  }  // end of Seed_JKISS32



void setup ()
  {
    
  // debugging prints
  Serial.begin (115200);
  // software serial for talking to other devices
  Serial2.begin (BAUD_RATE);
  // initialize the RS485 library
  myChannel.begin ();

  // debugging prints
  Serial.println ();
  Serial.println (F("Commencing"));
  myAddress = EEPROM.read (0);
  Serial.print (F("My address is "));
  Serial.println (int (myAddress));
  numberOfDevices = EEPROM.read (1);
  Serial.print (F("Max address is "));
  Serial.println (int (numberOfDevices));

  if (myAddress >= numberOfDevices)
    Serial.print (F("** WARNING ** - device number is out of range, will not be detected."));

  Serial.print (F("Packet length = "));
  Serial.print (PACKET_LENGTH);
  Serial.println (F(" bytes."));

  Serial.print (F("Packet time = "));
  Serial.print (PACKET_TIME);
  Serial.println (F(" microseconds."));

  // calculate how long to assume nothing is responding
  noMessagesTimeout = (PACKET_TIME + TIME_BETWEEN_MESSAGES) * numberOfDevices * 2;

  Serial.print (F("Timeout for no messages = "));
  Serial.print (noMessagesTimeout);
  Serial.println (F(" microseconds."));

  // set up various pins
  pinMode (XMIT_ENABLE_PIN, OUTPUT);

  // demo action pins
  pinMode (SWITCH_PIN, INPUT_PULLUP);
  pinMode (LED_PIN, OUTPUT);

  // debugging pins
  pinMode (OK_PIN, OUTPUT);
  pinMode (TIMEOUT_PIN, OUTPUT);
  pinMode (SEND_PIN, OUTPUT);
  pinMode (SEARCHING_PIN, OUTPUT);
  pinMode (ERROR_PIN, OUTPUT);

  // seed the PRNG
  Seed_JKISS32 (myAddress + 1000);

  state = STATE_NO_DEVICES;
  nextAddress = 0;

  randomTime = JKISS32 () % 500000;  // microseconds
  }  // end of setup

// set the next expected address, wrap around at the maximum
void setNextAddress (const byte current)
  {
  nextAddress = current;
  if (nextAddress >= numberOfDevices)
    nextAddress = 0;
  }  // end of setNextAddress


// Here to process an incoming message
void processMessage ()
  {
    Serial.print (F("process message"));

  // we cannot receive a message from ourself
  // someone must have given two devices the same address
  if (message.address == myAddress)
    {
    digitalWrite (ERROR_PIN, HIGH);
    Serial.print (F("** WARNING ** self address!!"));
    
    while (true)
      { }  // give up
    }  // can't receive our address

  digitalWrite (OK_PIN, HIGH);

  // handle the incoming message, depending on who it is from and the data in it

  // make our LED match the switch of the previous device in sequence
  if (message.address == (myAddress - 1))
    digitalWrite (LED_PIN, message.switches [0]);

  digitalWrite (OK_PIN, LOW);
  } // end of processMessage

// Here to send our own message
void sendMessage ()
  {
  digitalWrite (SEND_PIN, HIGH);
  memset (&message, 0, sizeof message);
  message.address = myAddress; 

  // fill in other stuff here (eg. switch positions, analog reads, etc.)

  message.switches [0] = digitalRead (SWITCH_PIN);

  // now send it
  digitalWrite (XMIT_ENABLE_PIN, HIGH);  // enable sending
  delay(10);
  myChannel.sendMsg ((byte *) &message, sizeof message);
  delay(10);
  digitalWrite (XMIT_ENABLE_PIN, LOW);  // disable sending
  setNextAddress (myAddress + 1);
  digitalWrite (SEND_PIN, LOW);

  lastCommsTime = micros ();   // we count our own send as activity
  randomTime = JKISS32 () % 500000;  // microseconds
  }  // end of sendMessage

void loop ()
  {
  // incoming message?
  if (myChannel.update ())
    {
    memset (&message, 0, sizeof message);
    int len = myChannel.getLength ();
    if (len > sizeof message)
      len = sizeof message;
    memcpy (&message, myChannel.getData (), len);
    lastMessageTime = micros ();
    setNextAddress (message.address + 1);
    processMessage ();
    state = STATE_RECENT_RESPONSE;
    }  // end of message completely received

  // switch states if too long a gap between messages
  if  (micros () - lastMessageTime > noMessagesTimeout)
    state = STATE_NO_DEVICES;
  else if  (micros () - lastCommsTime > PACKET_TIME)
    state = STATE_TIMED_OUT;

  switch (state)
    {
    // nothing heard for a long time? We'll take over then
    case STATE_NO_DEVICES:
      if (micros () - lastCommsTime >= (noMessagesTimeout + randomTime))
        {
        Serial.println (F("No devices."));
        digitalWrite (SEARCHING_PIN, HIGH);
        sendMessage ();
        digitalWrite (SEARCHING_PIN, LOW);
        }
      break;

    // we heard from another device recently
    // if it is our turn, respond
    case STATE_RECENT_RESPONSE:
      // we allow a small gap, and if it is our turn, we send our message
      if (micros () - lastCommsTime >= TIME_BETWEEN_MESSAGES && myAddress == nextAddress)
        sendMessage ();
      break;

    // a device did not respond in its slot time, move onto the next one
    case STATE_TIMED_OUT:
      digitalWrite (TIMEOUT_PIN, HIGH);
      Serial.print (F("Timeout..."));

      setNextAddress (nextAddress + 1);
      lastCommsTime += PACKET_TIME;
      digitalWrite (TIMEOUT_PIN, LOW);
      state = STATE_RECENT_RESPONSE;  // pretend we got the missing response
      break;

    }  // end of switch on state

  }  // end of loop

Thanks for your helps!

Greg