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);
}
}
}

