@noiasca : As suggested, I removed the RS485 modules and went ahead for RXTX. I have changed the program and in the first step, to ask from the master managed to send data to the slave and in the second step I am able to get response from the Slave. I have noticed that when the master displays the data there is a random character added at every step of the response. I am unable to understand why? Here is the master and slave sketches for all of your analysis and point to my errors.
// Master sketch
// 03052024_1914
// Master & Slave : UNO compatible boards
// Using TTL onboard comm port
// RX of master goes to TX of slave
// TX of master goes to RX of slave
int FL = 0; // added variable for receving data from slave
int FC = 0; // added variable for receving data from slave
#define slaveSelect 8
void setup()
{
Serial.begin(9600); // baud rate
pinMode(slaveSelect, OUTPUT);
digitalWrite (slaveSelect, LOW);
}
void loop()
{
digitalWrite (slaveSelect, HIGH);
delay (1); // delay of 1mS for slave stabilisation
if (Serial.available() > 0)
{
int FL = Serial.parseInt();
Serial.print ("FL RXD: ");
Serial.println (FL);
}
/*
//Serial.println ("slaveSelect is HIGH");
for (int testVal=0; testVal<=255; testVal++)
{
Serial.write(testVal); //Write the serial data over
Serial.print ("testVal sent:");
Serial.println (testVal);
//delay(500);
}
*/
}
// Slave sketch
// 03052024_1914
// Master & Slave : UNO compatible boards
// Using TTL onboard comm port
// RX of master goes to TX of slave
// TX of master goes to RX of slave
int FL = 1999; //Initial values for multi variable send
//int FC = 900; //initial values for multi variable send
#define slaveSelect 8
void setup()
{
Serial.begin(9600); // baud rate
pinMode(slaveSelect, OUTPUT);
digitalWrite (slaveSelect, LOW);
}
void loop()
{
if (digitalRead (slaveSelect == HIGH))
{
Serial.write (FL); // write the serial data over the network
Serial.print("FL TXD: ");
Serial.println (FL);
/*
//Serial.println ("slaveSelect is now HIGH");
if (Serial.available() > 0)
{
int testVal = Serial.parseInt();
Serial.print("testVal rxd: ");
Serial.println(testVal);
}
*/
}
}
In the next step, I am trying to move the RX / TX to pins 2 and 3 using SoftSerial and will share the developments here.
@markd833: It was at the start of every line on the output (serial monitor). The first line had an a, the second line b and so on and forth and included numbers and some special characters and finally a question mark in a black box.
I then decided to rewrite the entire sketch all over and in line with the earlier suggestion from @noiasca, I have taken it up step by step and have implemented the SoftwareSerial library along with the slaveSelect and Command Character "S" as well. I am able to communicate between the master and slave arduinos as per the below attached sketches for your perusal. The GNDs are connected between both the arduinos as per @jim-p.
However, i need to draw your attention to the line 23 (with a why in the comment) in the master code - if I decide to comment out the code, the value received from the master is invalid. Similarly, if i take add the line no. 32 (with a why in the comment) of the slave code, again the value received is invalid, else, the value of FL transmitted and recieved are correct, but I feel the data coming onto the serial monitor is quite slow.
Master Code:
#include <SoftwareSerial.h>
#define RX_PIN 2
#define TX_PIN 3
#define slaveSelect 8
SoftwareSerial mySerial(RX_PIN, TX_PIN); // RX, TX
void setup()
{
Serial.begin(9600); // default serial port for debugging
mySerial.begin(9600);// communication with the SoftwareSerial library
pinMode (slaveSelect, OUTPUT);
digitalWrite (slaveSelect, LOW);
}
void loop()
{
digitalWrite (slaveSelect, HIGH); // Enableslave
//delay (1); // delay for slave to initialize
mySerial.print('S');// command char 'S' to the slave Arduino
Serial.println("Command character S sent"); // this has to be true for valid data - WHY?
//delay(1); // Wait for 1 mS before receiving
if (mySerial.available())
{
int FL = mySerial.parseInt(); // get the value of FL by the slave Arduino
if (FL != 0)
{
Serial.print("FL received: ");
Serial.println(FL);
}
else
{
Serial.println("No response");
}
}
}
Slave Code:
// Slave_04052024_1622
#include <SoftwareSerial.h>
#define RX_PIN 2
#define TX_PIN 3
#define slaveSelect 8
SoftwareSerial mySerial(RX_PIN, TX_PIN); // RX, TX
int FL = 1098; // test value to be sent back to master
int status;
void setup()
{
Serial.begin(9600);// default serial port for debugging
mySerial.begin(9600);// communication with the SoftwareSerial library
pinMode (slaveSelect, INPUT); // in case addition of second slave at a later point of time
digitalWrite (slaveSelect, LOW); // default value
}
void loop()
{
int status = digitalRead (slaveSelect);
if (status == HIGH)
{
if (mySerial.available())
{
char receivedChar = mySerial.read(); // check command character
if (receivedChar == 'S') // validity of command character
{
// Serial.println ("command char S received"); // this has to be false for valid data - WHY?
mySerial.print(FL); // Send the test value of FL to the master Arduino
Serial.print("FL sent:");
Serial.println(FL);
}
}
}
}
I really thank each of you for your time to help me out and teaching me.
At first glance, I can't see why commenting out the print statement in the master would affect the operation of the code. However, with it uncommented, it takes a while longer to go round the loop in the master.
I would start by slowing things down and adding a delay at the end of the loop in the master code. A 1 second delay should be a reasonable starting point.
As your master code stands, it will likely send several S characters to the slave before it gets it's first reply back. I would need to look at the library code to see what happens if the slave receive buffer fills up completely.
Perhaps a better strategy would be to send an S and then wait a preset time for a response from the slave before transmitting the next S.
@markd833: I have incorporated the changes suggested by you, viz. added a delay at the end of the loop. No change in the behaviour. Here is the screenshot of the result with the line (only in the slave sketch), but should I uncomment one of the line in the master the behaviour is similar. for forum.pdf (613.7 KB)
I'm not sure if can follow your development, are you with rs485 module or without? Why you set your select pin high in the loop and keep it high "forever"?
The above line in the slave code just after you set pinMode to input is sticking out too me..
Think it should just be removed..
If the master boots first and digitalWrites the line high, then the slave boots and writes it low..
idk what would happen, my head is screaming open drain..
@kmin : I am sorry I did not answer correctly, I was not paying attention and was in a very disturbed state of mind. Thank you for your inputs. I apologize to @qubits-us as well.
I am at present using without the RS485 module at present and using SoftwareSerial and have assigned pins 2 and 3 for RX and TX. I am as per @noiasca's advice, going one step at a time and once the data is received correctly between the master and slave, I will attempt the RS485 communication with the modules.
No apologies needed here, but thank you..
You know, just noticed, the slave prints the int, this converts into ascii chars, can't parseInt on that as it's now a string..
You could use Serial.write(FL,sizeof(FL)); to send the int or recv it as a string and convert to int..
@qubits-us and @kmin : I think i got over the first hurdle. I am able to receive data from the slave as per the below codes but it had not been easy.
I could get the data of only 2 of the dummy integer values and the balance 3 sometimes even 4 were garbage. When I finally managed to get all of the 5, it would slowly drift and get jumbled up. The first variable would display the third the second would be fifth until they all settle at some random fashion. The communication (or) power if interrupted to any of the board would result in another random fashion at the end.
That leaves with a couple of questions for you gurus to answer is
a. Is timing or the sequence of Code everything?
b. Would more lines of code make it more unpredictable?
vaThe next and hurdle is putting more slaves and trying it out. I will get a few more clone boards tomorrow and attempt communicating with multiple boards.
// Master
// 10052024
// Master and Slave are arduino Uno
// Data transfer in progress
#include <SoftwareSerial.h> // Include the library for alternative pins
SoftwareSerial mySerial(2, 3); // RX (pin 3), TX (pin 2) for serial communication
int FL, FLC, FC, FCR, FR; // Variables to store received sensor values
int Slave1 = 8;
void setup()
{
Serial.begin(9600); // Initialie serial comm with Slave1
mySerial.begin(9600); // Initialize software serial comm with Slave1
pinMode (Slave1, OUTPUT); // Declare Slave1 pin as Output - selection
digitalWrite (Slave1, LOW); // Set Slave1 LOW and make it high to select Slave1
}
void loop()
{
digitalWrite (Slave1, HIGH); // Enable Slave1
delay(1); // delay to stabilize the Slave1
mySerial.write('R'); // Send a command character requesting data from slave
// Read and store received values
if (mySerial.available() >= 4)
{
FL = (mySerial.read() << 8) | mySerial.read(); // Combine FL high and low bytes
FLC = (mySerial.read() << 8) | mySerial.read(); // Combine FLC high and low bytes
FC = (mySerial.read() << 8) | mySerial.read(); // Combine FC high and low bytes
FCR = (mySerial.read() << 8) | mySerial.read(); // Combine FCR high and low bytes
FR = (mySerial.read() << 8) | mySerial.read(); // Combine FR high and low bytes
Serial.println("Received values");
Serial.print("FL:");
Serial.println (FL);
Serial.print("FLC:");
Serial.println (FLC);
Serial.print("FC:");
Serial.println (FC);
Serial.print("FCR:");
Serial.println (FCR);
Serial.print("FR:");
Serial.println (FR);
}
delay(50); // Read data every second (adjust interval as needed)
}
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX (pin 3), TX (pin 2) for serial communication
int FL = 111;
int FLC = 222;
int FC = 333;
int FCR = 444;
int FR = 555;
void setup()
{
Serial.begin(9600);
mySerial.begin (9600);
}
void loop()
{
if (mySerial.available() > 0)
{
char command = mySerial.read();
if (command == 'R')
{
// Send sensor values in high and low bytes (MSB, LSB)
mySerial.write(highByte(FL)); // Send high byte of FL
mySerial.write(lowByte(FL)); // Send low byte of FL
mySerial.write(highByte(FLC)); // Send high byte of FLC
mySerial.write(lowByte(FLC)); // Send low byte of FLC
mySerial.write(highByte(FC)); // Send high byte of FC
mySerial.write(lowByte(FC)); // Send low byte of FC
mySerial.write(highByte(FCR)); // Send high byte of FCR
mySerial.write(lowByte(FCR)); // Send low byte of FCR
mySerial.write(highByte(FR)); // Send high byte of FR
mySerial.write(lowByte(FR)); // Send low byte of FR
}
}
delay(1); // Respond to requests more frequently (adjust as needed)
}
awesome progress..
The slave is missing some code..
Yes, it always needs to read the serial when available..
But it should only act on that command if it's line is high, so you should have a digitalRead and check if this slave is selected..
All slaves will need to read in code not for them and toss them away..
Answering the ??
a. a bit, i guess as each slave must check at the proper time if data recvd is actually theirs..
b depends on the code added, stay away from the delay function and you should be ok..
while waiting for the other board, maybe learn about structures..
Could take all those ints and put them into a packed structure and send and recv them with allot less code..
In your master code, I wonder if initially you meant to check for >=5 values as you are reading 5 values?
However, note that your slave code sends those 5 16-bit values as 10 bytes. If your intention is to wait until the serial buffer of the master has accumulated all the data, then you should be looking for >9 values - i.e 10 bytes in the serial receive buffer.
was bored, sorry..
new untested master code..
put vars into a structure, then an array of these one per slave..
select pins in an array..
move the actual reading to a separate function, returns true if slave was read..
utilized millis timers for reading that time out and delay between readings..
should be easily expanded when the other boards arrive..
maybe it gives you some ideas if anything..
// Master
// 10052024
// Master and Slave are arduino Uno
// Data transfer in progress
#include <SoftwareSerial.h> // Include the library for alternative pins
SoftwareSerial mySerial(2, 3); // RX (pin 3), TX (pin 2) for serial communication
#define NUM_SLAVES 1
struct __attribute__((packed)) SensorReadings {
int FL;
int FLC;
int FC;
int FCR;
int FR;
};
//array of recs 1 for each slave
SensorReadings Readings[NUM_SLAVES];
//slave select pins in arrays
const byte SlavePins[NUM_SLAVES] = {8};
//currently selected slave
byte currSlave = 0;
//millis timer for delay between reads
unsigned long lastRead;
unsigned long intervalRead = 1000;
// timeout timer for reasding
unsigned long readTimeout;
unsigned long intervalTimeout = 1000;
const byte Slave1 = 8;
void setup()
{
Serial.begin(9600); // Initialie serial comm with Slave1
mySerial.begin(9600); // Initialize software serial comm with Slave1
//init select pins
for (int i = 0; i < NUM_SLAVES; i++) {
pinMode(SlavePins[i], OUTPUT);
digitalWrite(SlavePins[i], LOW);
}
}
void loop()
{
unsigned long now = millis();
if (now - lastRead >= intervalRead) {
lastRead = now;
if (ReadSlave()) {
//got a good read..
Serial.print("Received values:");
Serial.println(currSlave);
Serial.print("FL:");
Serial.println (Readings[currSlave].FL);
Serial.print("FLC:");
Serial.println (Readings[currSlave].FLC);
Serial.print("FC:");
Serial.println (Readings[currSlave].FC);
Serial.print("FCR:");
Serial.println (Readings[currSlave].FCR);
Serial.print("FR:");
Serial.println (Readings[currSlave].FR);
//select next slave
currSlave++;
//roll back to 1st..
if (currSlave >= NUM_SLAVES) currSlave = 0;
} else {
Serial.print("Slave ");
Serial.print(currSlave + 1);
Serial.println(" did not respond..");
}
}
}
bool ReadSlave() {
//select slave
digitalWrite(SlavePins[currSlave], HIGH);
delay(5);//time for slave to see it's selected
mySerial.write('R');
//prep the timer
readTimeout = millis();
bool recvd = false;
bool timedOut = false;
byte buff[sizeof(SensorReadings)];
int bytesRecvd = 0;
//while not timed out or have not receved anythng..
while (!timedOut && !recvd) {
timedOut = (millis() - readTimeout >= intervalTimeout);
//have to recv a byte at a time..
if (mySerial.available()) {
buff[bytesRecvd] = mySerial.read();
bytesRecvd++;
if (bytesRecvd == sizeof(SensorReadings)) {
recvd = true;
memcpy(&Readings[currSlave], buff, sizeof(SensorReadings));
}
}
}
//un-select slave
digitalWrite(SlavePins[currSlave], LOW);
return recvd;
}
@qubits-us and @markd833 : Thank you for your comments and guidance. Please give me a little time to get back to on the forum. Suddenly my world has turned upside down and I had to rush my son to the USA to be of support to my sister and her family. I am extremely sorry for this break and will get back to the forum as quickly as possible.