I wonder how to use serial port name as a variable to avoid multiplying code for every serial port
simple example:
#define SerialNR1 1 #define SerialNR2 2
byte serialData;
void ReadSerial(int SerialNR)
{
// How to execute serial1,2,3 etc. as a function parameter. Something like
// SerialNR.read(); ? I want to avoid constructions like switch case, or condition
// my "classic" approach
switch (SerialNR)
{
case SerialNR1:
{
serialData = Serial1.read();
}
break;
case SerialNR2:
{
serialData = Serial2.read();
}
break;
}
}
ReadSerial(SerialNR1); //function execution, serial1 as a parameter
int readSerial(Stream *s);
void setup() {
int i;
i = readSerial(&Serial);
i = readSerial(&Serial1);
i = readSerial(&Serial2);
}
void loop() {
}
int readSerial(Stream *s) {
return s->read();
}
I try like that, this gives me a flood of data (Serial1 buffer size), looks like condition "s->available() > 0" is always true, even if serial1 buffer size is "0" and s->available() returns "0"
cdxa:
this gives me a flood of data (Serial1 buffer size), looks like condition "s->available() > 0" is always true, even if serial1 buffer size is "0" and s->available() returns "0"
Using s->available() is exactly the same as Serial1.available(). It looks like the problem is you don't fully understand how it works. Take a look at @Robin2's Serial Input Tutorial.
the Arduino IDE hides the definitions of Serial, Serial1, Serial2 and Serial3 as variables of type HardwareSerial (they are at the bottom of HardwareSerial.h)
like any variable with structure, a pointer of that variable type can be used in place the variable to access internal elements using "->" instead of ".".
i've used a Serial pointer when developing code on the Mega which has several Serial interfaces and ported that code to an Uno which has just one. Writing the code using a Serial pointer and using an interface other that Serial on the Mega which was used for debugging, allow me to easily use Serial in place of Serial3 for example without needing to rewrite any code.
HardwareSerial* s = NULL;
void
setup (void)
{
# if 1
s = &Serial3;
# else
s = &Serial;
# endif
s->begin (9600)
}
void
loop (void)
{
byte c = (byte) NULL;
if (s->available()) {
c = s->read ();
// do something with c
}
}
gcjr:
the Arduino IDE hides the definitions of Serial, Serial1, Serial2 and Serial3 as variables of type HardwareSerial
Not true on all boards in the Arduino Ecosystem. Not every "Serial" object is an instance of HardwareSerial. But, they are all instances of Stream. Use a pointer to that class.
If I move serial availability checking into other function everything works well
void setup()
{
Serial.begin(115200);
Serial1.begin(9600);
}
int readSerial(Stream *s) {
return s->read();
}
int SerialAvailable(Stream *s) {
return s->available();
}
void loop()
{
if (SerialAvailable(&Serial1)) // this condition is true only when serial buffer is > 0
{
Serial.write(readSerial(&Serial1));
}
}
Maybe i'm really don't understand that, and im be appreciated if some one could me explain why this condition always is true?
int readSerial(Stream *s) {
if ( s->available() > 0) // this is always true no matter from buffer bytes count
{
return s->read();
}
else
return -1;
}
I can put in condition even 100, 1000 and no matter what else, is always true ( s->available() > 1000)
no matter what number I use to compare, the condition is always true, even if buffer chars count is zero. This is what wondering me.
@TheMemberFormerlyKnownAsAWOL
Condition works OK, that's my fault, sorry
Here is my code, I want to store serial port number in structure Serial DataSet.SerialPort and use it in readSerial(), appropriate to present used structure, but I don't know how to do
typedef struct SerialDataSet
{
public:
uint8_t SerialPort; // here i want to store my serial port nr
byte SerialData[64]; // my serial buffer copy
} SerialDataSet;
SerialDataSet SerialPort1;
SerialDataSet SerialPort2;
void readSerial( SerialDataSet & data);
void readSerial( SerialDataSet & data)
{
while (Serial1.available() > 0) // here i want to point to serial port stored in SerialDataSet.SerialPort, but I don't know how?
{
uint8_t incomingchars = Serial1.available();
data.SerialData[data.SerialData[0]+1] = Serial1.read();
data.SerialData[0] = data.SerialData[0] + incomingchars;
}
}
void setup()
{
Serial.begin(115200);
Serial1.begin(9600);
Serial2.begin(9600);
// set variables
SerialPort1.SerialPort = 1; // here i want to store port number 1 = Serial1
SerialPort1.SerialData[0] = 0; // zero chars in buffer
SerialPort2.SerialPort = 2; // here i want to store port number 2 = Serial2
SerialPort2.SerialData[0] = 0; // zero chars in buffer
}
void loop()
{
readSerial(SerialPort1); // read SerialPort1 and store in SerialPort1.SerialData buffer
readSerial(SerialPort2); // read SerialPort2 and store in SerialPort2.SerialData buffer
if (SerialPort1.SerialData[0] > 0) // send data from my buffer do serial for debug purposes
{
for (int i = 1; i <= SerialPort1.SerialData[0]; i++)
{
Serial.write(SerialPort1.SerialData[i]);
}
SerialPort1.SerialData[0] = 0;
}
}
The serial port number you are referring to means nothing to the Arduino. The instance names could just as easily be Bob, Sam, Frodo, and Satan.
If you want the user to supply a number, and for the Arduino use that number to know which instance name to use, that isn't going to happen unless YOU write some code to map the number to a pointer to an instance (which isn't that hard).
Ok so for example a want to store in struct "Bob" it means Serial1 and Satan means Serial2 how to pass command to proper port based on settings from structure? To simplify numeric values will be enough, 1=Serial1 , 2=Serial2
Ok, but how to store pointer in structure?
As you can see thanks to your advice im trying to use, I use &Serial1 and thats works, but I want to pass to functions different structures, every of it has own serial port number, exactly as in code from post #14, but I don't know how to store pointer in the structure
consider the following code tested using one serial interface on an Uno (tested on Uno)
i hope this illustrates the used of structs, static initialization and pointers
typedef struct
{
HardwareSerial *port;
byte data [64];
} SerialDataSet_t;
SerialDataSet_t serialData [] = {
{ & Serial },
// { & Serial2 }, // Uno has only 1 interface
// { & Serial3 }, // Uno has only 1 interface
};
#define N_SERIAL (sizeof(serialData)/sizeof(SerialDataSet_t))
// -----------------------------------------------------------------------------
int readSerial (SerialDataSet_t *s)
{
while (s->port->available() > 0)
{
byte c = s->port->read();
s->data [1 + s->data [0]] = c;
s->data [0]++;
if ('\n' == c)
return s->data [0];
}
return 0;
}
// -----------------------------------------------------------------------------
void setup()
{
serialData [0].port->begin(115200); // Uno has only 1 interface
}
// -----------------------------------------------------------------------------
void loop()
{
for (unsigned n = 0; n < N_SERIAL; n++) {
SerialDataSet_t *s = (& serialData [n]);
if (readSerial (s)) {
// echo received data back
s->data [s->data [0]] = 0; // insure that it is NUL terminated
Serial.print ("received: ");
Serial.println ((char*) & (s->data [1]));
s->data [0] = 0;
}
}
}
Notes:
seems unnecessary for structure sub-field names to include the name of the struct or variable
structs, while similar to class, don't require public
the "_t" suffix indicates the symbol name is a typedef
variables are always NOT capitalized
an array of struct can be statically initialized within a table (e.g. serialData)
unspecified field values in a static initialization are set to zero (e.g. data [])
the N_SERIAL macro is a conventional way to let the compiler determine the # of struct elements
readSerial() is passed a pointer which avoids knowledge of how the variable is maintained (i.e. discrete variables, array element, ...) And save space in the code
my Serial monitor is configured to terminate all lines with a '\n' making it easier to detect the end of t a line. At 115200, transmission was fast enough that the while only captured one character
readSerial () returns a non-zero result only after seeing the '\n'
setup() demonstrate directly referencing an array element
loop() demonstrates passing a pointer to the serialData array element to readSerial()
loop() echos the received string back on the same Serial interface because the Uno has just on port