Interrupts on Arduino Uno

Hello All,

I’m working on a small project in which I want to use a Raspberry Pi to control multiple slave Arduinos. I am using half-duplex RS485 for serial communications, I thought about using Modbus to facilitate multi-drop topology but it was a little complex for what I needed. I decided to try and work up a simple Interrupt based communications protocol instead.

Essentially, I want the Arduinos to monitor the serial line, if new data arrives I want them to read it, parse it and then take any necessary action.

The problem I seem to be having is that my interrupt only runs once, after the first iteration (which works fine) I get no response. I have tried resetting the interrupt flag but am something of a newbie.

Any advice would be appreciated. Code attached.

//Libraries

#include <SoftwareSerial.h>

//Constants & Pin Numbers

#define interrupt_Pin     2
#define LED_Pin           8
#define RS485_Toggle_Pin  9
#define RS485_Rx_Pin      10
#define RS485_Tx_Pin      11

#define RS485TX           HIGH
#define RS485RX           LOW

const byte bufferSize = 32;
char Buffer[bufferSize];
boolean newCommand = false;

//Software Serial Setup

SoftwareSerial RS485(RS485_Rx_Pin,RS485_Tx_Pin);

//Setup

void setup() 
{ 
  //Pin Modes

  pinMode(LED_BUILTIN,OUTPUT);
  pinMode(interrupt_Pin,INPUT_PULLUP);
  pinMode(LED_Pin,OUTPUT);
  pinMode(RS485_Toggle_Pin,OUTPUT);
  
  //Intialise Pins

  digitalWrite(LED_BUILTIN,LOW);
  digitalWrite(LED_Pin,LOW);
  digitalWrite(RS485_Toggle_Pin,RS485RX);

  //Hardware Serial - Serial Monitor Debugging

  Serial.begin(9600);
  Serial.println("Arduino Interrupt Based Communications - Slave");

  //Software Serial - RS485 Bus

  RS485.begin(9600);

  //Attach Interrupt

  attachInterrupt(digitalPinToInterrupt(interrupt_Pin),getCommand,FALLING);
}

void loop() 
{  
  if (newCommand == true)
  {
    Serial.println("Recieved from Pi: ");
    Serial.println(Buffer);

    digitalWrite(RS485_Toggle_Pin,RS485TX); //Enable RS485 Transmission

    RS485.println((char*)Buffer); //Send Response

    RS485.flush();
    digitalWrite(RS485_Toggle_Pin,RS485RX);

    newCommand = false;
  }
}

void getCommand()
{ 
  static boolean Receiving = false;
  static byte index = 0;
  char STX = 0x02;
  char ETX = 0x04;
  char currentByte;

  if (RS485.available() > 0)
  {
    while (RS485.available() > 0 && newCommand == false)
    {
      currentByte = RS485.read();
      if (Receiving == true)
      {
        if (currentByte != ETX)
        {
          Buffer[index] = currentByte;
          index++;
          if (index >= bufferSize)
          {
            index = bufferSize-1;
          }
        }
      else
      {
        Buffer[index] = '\0';
        Receiving = false;
        index = 0;
        newCommand = true;
      }
      }
      else if (currentByte == STX)
      {
        Receiving = true;
      }
    }
  }
}

:o :o

Why do you need to handle this through interrupts when you communicate a 9600 bauds over a serial line.. just have your arduino await for incoming data on the Serial line and build up the command as it goes...

Good questions ...

As I said I'm a bit of a newbie. My thinking was that handling the receipt of commands through interrupts would ensure there was no way to 'miss' a command and allow scope for expanding the interrupt in the future to facilitate sleeping the Arduinos to reduce power consumption.

Do you think I am over-complicating the issue?

Yes, all reception of Serial is already handle (via interrupts funny enough) in the Arduino framework. Just use Serial and have a look at Robin2's tutorial on Serial Input Basics.

IdleSam:
Do you think I am over-complicating the issue?

Yes... :slight_smile:

really just listen for the serial port for the time being

if you want to sleep your arduino - then what you can do is indeed have an ISR on pin 2 but make that just wake up the UNO, then read a command and when the command is handled, go back to sleep. Don't mix the "wake up call" with reading the data from within the ISR. (and you are likely going to empty your Serial buffer faster than you receive data.. so your way of handling serial is not great --> you should study Serial Input Basics)

There's an RS485 Peer-To-Peer sketch I posted on my github page that's free to use by anybody who wants. Might be a start. Doesn't use interrupts but uses packets and does address checking.

J-M-L:
Yes... :slight_smile:

really just listen for the serial port for the time being

if you want to sleep your arduino - then what you can do is indeed have an ISR on pin 2 but make that just wake up the UNO, then read a command and when the command is handled, go back to sleep. Don't mix the "wake up call" with reading the data from within the ISR. (and you are likely going to empty your Serial buffer faster than you receive data.. so your way of handling serial is not great --> you should study Serial Input Basics)

Thanks J-M-L,

I think I'll take your advice and handle this without interrupts then add in sleep/wake as a discrete interrupt later on.

Appreciate the help.

Best