Edit: I don’t really make a point of saying it, but the common ground between the modules isn’t necessary.
Here’s a video of the software running on the boards.
So for this example, there are 4 bytes being transmitted from the master to the slaves.
- Start of Transmission (0xDB)
- ID of the slave to talk to
- The type of command
- The data that is transmitted
A transmission to set the pwm value of the green led on the slave with the ID 1 to 100 would be:
0xDB 0x01 0x01 0x64
This is the schematic of the circuit for this example:
This is the code running on the master Arduino:
#include <SoftwareSerial.h>
int MAX485_Receiver_Output_PIN = 10;
int MAX485_Driver_Input_PIN = 11;
int MAX485_Driver_Output_Enable_PIN = 12;
#define NUMSWITCHES 3
int ID_switches[NUMSWITCHES] = {2, 3, 4};
int mode_switch = 5; 
byte IDs[NUMSWITCHES] = {1, 2, 3};
#define TXSIZE 4
SoftwareSerial software_serial (MAX485_Receiver_Output_PIN, MAX485_Driver_Input_PIN); // RX, TX
byte target_node_ID;
struct transmission {
  byte start = 0xDB;
  
  byte ID;
  byte type;
  byte message;
  const int tx_size = TXSIZE;
};
void setup()
{
  software_serial.begin(9600); // begin software serial
  
  pinMode(MAX485_Driver_Output_Enable_PIN, OUTPUT);
  digitalWrite(MAX485_Driver_Output_Enable_PIN, HIGH); // this disables Receiver Output Enable and enables Driver Output Enable
  
  for (int index = 0; index < NUMSWITCHES; index++)
  {
    pinMode(ID_switches[index], INPUT); 
  }
  
  pinMode(mode_switch, INPUT);
  
  target_node_ID = 0;
}
void loop()
{
  for (int index = 0; index < NUMSWITCHES; index++)
  {
    if ((byte)digitalRead(ID_switches[index]))
    {
      target_node_ID = IDs[index];
      break;
    }
  }
  
  transmission t;
  
  t.ID = target_node_ID;
  t.type = digitalRead(mode_switch);
  t.message = (byte)map(analogRead(0), 0, 1023, 0x00, 0xFF);
  
  byte message[TXSIZE] = {t.start, t.ID, t.type, t.message};
  
  software_serial.write(message, t.tx_size);
}
This is the code running on the slave Arduinos:
#include <SoftwareSerial.h>
int MAX485_Receiver_Output_PIN = 10;
int MAX485_Driver_Input_PIN = 11;
int MAX485_Driver_Output_Enable_PIN = 12;
int led_1_PIN = 5; 
int led_2_PIN = 6; 
unsigned long time = 0;  
unsigned long oldtime = 0; 
int state = 0;
int next_ID_button_PIN = 2;
#define NUMSTATES 3
int states[NUMSTATES] = {7, 8, 9};
byte IDs[NUMSTATES] = {1, 2, 3};
#define MESSAGELENGTH 3
SoftwareSerial software_serial (MAX485_Receiver_Output_PIN, MAX485_Driver_Input_PIN); // RX, TX
void setup()
{
  software_serial.begin(9600); // begin software serial
  
  pinMode(MAX485_Driver_Output_Enable_PIN, OUTPUT);
  digitalWrite(MAX485_Driver_Output_Enable_PIN, LOW);
  
  pinMode(led_1_PIN, OUTPUT);
  pinMode(led_2_PIN, OUTPUT);
  
  pinMode(next_ID_button_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(next_ID_button_PIN), next_ID, RISING); 
  
  set_LEDs();
}
void loop() // run over and over
{
  
  byte start_of_message = 0xDB;
  byte incoming_byte;
  byte message[MESSAGELENGTH];
  
  while (true)
  {
    if (software_serial.available())
    { 
      incoming_byte = software_serial.read();
      
      if (incoming_byte == start_of_message)
      {
        software_serial.readBytes(message, MESSAGELENGTH);
        process_message(message);
      }
    }
  }
}
 
void process_message(byte message[])
{
  byte system_ID = IDs[state];
  byte incoming_ID = message[0];
  byte incoming_mode = message[1];
  byte LED_brightness = message[2];
   
  if (incoming_ID == system_ID)
  {
    byte pin;
    
    if (incoming_mode == 0)
    {  
      pin = led_1_PIN;
    }
    else if (incoming_mode == 1)
    {
      pin = led_2_PIN; 
    }
    analogWrite(pin, LED_brightness);  
  }
}
void next_ID()
{
  time = millis();
  
  //soft debounce
  if (time - oldtime > 200) 
  {
    oldtime = time;
    
    state++;
    
    if (state >= (NUMSTATES))
    {
      state = 0;
    }
  }
  set_LEDs();
}
void set_LEDs()
{
  for (int index = 0; index < NUMSTATES; index++)
  {  
    if (index == state)
    {
      digitalWrite(states[index], HIGH);
    }
    else 
    {
      digitalWrite(states[index], LOW);
    }
  } 
}
			
