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:
1 |
0xDB 0x01 0x01 0x64 |
This is the schematic of the circuit for this example:
This is the code running on the master Arduino:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
#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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
#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); } } } |
Hello,
Your slave sketch not compile
It compiles fine on my machine, what errors do you get? Let’s work though them
Hi,
I notice that you have a common ground between all three RS485 modules. My understanding is that RS485 is a balanced (longish range) two wire link, is that correct or have I confused it with RS232. I ask because I have a project in mind which uses some commercial RS485 modules and an arduino.
Regards Alan
Hi Alan,
You’re correct, the common ground isn’t necessary. You are also not the first person to point out this error, I’ll make a post updating the schematic soon.
Best,
Devon
Nice project, but can i use standard tx and rx pins on arduino instead of wasting some more pins? I’m trying with no luck
No you can’t really do this because of the way that this protocol is implemented. This prints messages to serial which will also go out over the tx and rx pins and mess everything up.
can you explain more? i don’t got it that why don’t use tx and rx pins in this project?
can we control other slaves, i mean slaves which are not arduino instead some other controller units including sensors and relays etc.
No! Because this example is more of a protocol. You would have to match the protocol of whatever you were trying to talk to.
Hi devon,
This is good.please update or send code for multiply relay controls as a example master send A0001 the slave a re ponce this activate pin4 high, master we type B1000 and B slave response and pin one high . i use A,B,C,D,etc…slaves and 4 relay model,Can you help me????
Hi, I can implement this for a cost, send me an email.
Hi Devon,
I have a project where Arduino Mega should control several (more than 20 Attinys 44)
Will this communication work with Attinys 44 ? Mega is the Master and Attinys are slaves.
Please reply & advice,
Thanks
Mike
Mike, You would have to write your own communication protocol, but it should work in theory.