how would i call different serial (Serial1, Serial2 , Serial3) in the same function
i have tried different things with more or less success , but i need to use ".parseInt() , so the code below doesnt work !
just an exemple
void SerialIn(byte Port, char Input) {
SerialBuffer[Port][index[Port]] = Input;
Index[Port]++;
if (Input == '}') { // end of message received by serail1 or 2 or3
Serial.println(SerialBuffer[Port]);
Index[Port] = 0;
// not possible to do ".parseInt()" on the serialbuffer right ?
}
}
void loop() {
if (Serial1.available() > 0) { SerialIn(0, Serial1.read()); }
if (Serial2.available() > 0) { SerialIn(1, Serial2.read()); }
if (Serial3.available() > 0) { SerialIn(2, Serial3.read()); }
}
this other code work with parseint , but i can't "compact" it in a single function , i would have to write the same thing 3 times but replacing "Serial1 , Serial2 , Serial3"
int ReceivedNumber[6];
void SerialIn2() {
while (Serial2.available() > 0) {
if (Serial2.read() == '{') { // start of message received by serial2
for (byte i = 0; i < 6; i++) {
ReceivedNumber[i] = Serial2.parseInt();
if (Serial2.read() == '}') { // end of message received by serial2
break;
}
}
for (byte i = 0; i < 6; i++) {
Serial.println(ReceivedNumber[i]);
}
}
}
void loop() {
if (Serial2.available() > 0) { SerialIn2(); }
}
so the main question , is how would i replace SerialX in the function SerialIn2 above
You handover a pointer to either Serial1, Serial2 or Serial3
additionally you should descripe what happens in your code
you receive characters from different ports
what kind of data?
only numerical digits?
very mixed stuff
with or without start/endmarker
assuming the function works how is the function used in the rest of your code?
i receive data from electrical powermeter that are always sending the same message with just different integer value.
message format is :
_a,int1,int2,int3,int4,int5!
only int1 to int5 can change
and sometimes if error happen on the sender side i receive only
_a,int1!
int1 beeing the error code
the code to handle the received data already work and do exactly what i want to
my question was more about learning new things and reducing the amount of lines in the sketch by not having a function writen 3 time for almost the same thing
Serial.parseInt() will lock you in the function until an integral number is received or a time out occurs
so if you use this function (or any similar function provided by arduino where there is a timeout) then you won't be able to listen to multiple Serial lines at the same time
ideally you would create a class buffering the input for you and that you can ask if you received a new message
does your message format have a trailing end mark like a \n ?
Sorry, but that won't work because the code will stay in the parseInt() function until a non numeric character is received or the serial timeout occurs
and it seems that you messages even have start-marker "_a"
normal message: _a,int1,int2,int3,int4,int5!
error-message: _a,int1!
and you have value-separators the comma.
This means you can write yur own receive-function that starts storing the characters
after receiving "_a" and goes on with receiving until the "!" is received
Then a flag completeMessageReceived is set true
and you can go on processing the integers
the length already tells you normal data or error
doing it this way enables to receive as fast as you can in a non-blocking way
and still receive everything
read this tutorial. See example 3 of this tutorial
it's not too complicated, may be something like that will do
I just typed it into wokwi to ensure it was compiling and did not test it, so you might have to tailor it a bit
click to see the code
/* ============================================
code is placed under the MIT license
Copyright (c) 2023 J-M-L
For the Arduino Forum : https://forum.arduino.cc/u/j-m-l
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
const size_t bufferSize = 64;
const byte wrongMessageFormat = 0x42;
class PowerMetter {
public:
PowerMetter(const char * name, HardwareSerial &s) : name(name), comPort(s), currentPos(0) {}
void begin(unsigned long baud, byte config) {
comPort.begin(baud, config);
}
void begin(unsigned long baud) {
comPort.begin(baud, SERIAL_8N1);
}
bool messageReady() {
bool ready = false;
if (comPort.available()) {
char r = comPort.read();
if (r == '!') {
messageBuffer[currentPos] = '\0';
ready = true;
currentPos = 0;
} else {
if (currentPos < bufferSize) {
messageBuffer[currentPos++] = r;
messageBuffer[currentPos] = '\0'; // always maintain a cString
}
}
}
return ready;
}
bool parseMessage(long longArray[5]) {
if (sscanf(messageBuffer, "_a,%ld,%ld,%ld,%ld,%ld", longArray, longArray + 1, longArray + 2, longArray + 3, longArray + 4) == 5) {
return true;
} else {
if (sscanf(messageBuffer, "_a,%ld", longArray) == 1) {
for (int i = 1; i < 5; ++i) longArray[i] = 0; // empty the other values
return false;
}
}
for (int i = 0; i < 5; ++i) longArray[i] = wrongMessageFormat; // all data set to wrongMessageFormat would mean wrong input
return false;
}
const char * message() {
return messageBuffer;
}
const char * meterName() {
return name;
}
private:
const char * name;
HardwareSerial& comPort;
char messageBuffer[bufferSize + 1]; // +1 for the trailing null
byte currentPos;
};
PowerMetter meters[] = {{"PW1", Serial1}, {"PW2", Serial2}, {"PW3", Serial3}};
void setup() {
Serial.begin(115200);
for (auto& aMeter : meters) aMeter.begin(9600); // whatever baud rate is used by your Power Meter
}
void loop() {
for (auto& aMeter : meters) {
if (aMeter.messageReady()) {
Serial.print(F("Message from ")); Serial.print(aMeter.meterName());
Serial.print(F(" => ")); Serial.println(aMeter.message());
long results[5];
if (aMeter.parseMessage(results)) {
Serial.print(F("int1=")); Serial.print(results[0]);
Serial.print(F(" and int5=")); Serial.println(results[4]);
} else {
if (results[1] != wrongMessageFormat) {
Serial.print(F("Error code: ")); Serial.println(results[0]);
} else {
Serial.print(F("wrong message format."));
}
}
}
}
}
(you might make the parsing more robust in storing the bang also in the messageBuffer in which case you need to add one extra byte to the buffer and modify the sscanf accordingly)
int ReceivedNumber[9];
while (Serial2.available() > 0) {
if (Serial2.read() == '_') { // start of message received by serial2
for (byte i = 0; i < 9; i++) {
ReceivedNumber[i] = Serial2.parseInt();
if (Serial2.read() == '!') { // end of message received by serial2
break;
}
}
}
My mistake. I had misunderstood what you were trying to do and your code looks like it should work. Personally I would be tempted to parse the incoming string into the array using the strtok() function, but that is a matter of personal choice