Help converting a simple code from procedural to object oriented

Hello everyone !

I have this code where an arduino mega2560 will receive serial input from 2 different gps receivers then store the data and send them both to the usb port using the Serial.print function.
The code for Receiving and transmitting the serial data for both inut devices is almost identical.
I say almost because each gps needs to talk to a dedicated serial port on the arduino.
Here is the procedural code:

const byte MaxSize = 100;
struct SerialData
{
  char Data[MaxSize];
}; 
struct SerialData Dev1, Dev2;

void setup() 
{
  Serial.begin (38400); 
  Serial1.begin(9600);   
  Serial2.begin(38400); 
}

void loop() 
{
  RX_Dev1();
  RX_Dev2();
}

void RX_Dev1()
{
  static bool rcving = false; 
  static byte nde = 0;  //index
  char SM = '$';   //start marker
  char EM = '\n';  //end marker
  char rc;    
  while (Serial1.available()) 
  {
    rc = Serial1.read(); 
    if (rcving) 
    {       
      if (rc != EM)   
      {
        Dev1.Data[nde] = rc; 
        nde++; 
        if (nde >= MaxSize)  
        {
          nde = nde - 2;
        }
        Dev1.Data[nde] = '\0'; 
      }
      else   
      {
        Dev1.Data[nde] = '\n';
        nde++;        
        Dev1.Data[nde] = '\0'; 
        rcving = false;
        nde = 0;
        TX_Dev1();   // At this point the transmitted message is complete so i send it to the USB port     
      }
    }
    else if (rc == SM)
    {
      rcving = true;            
    }
  } 
}

void RX_Dev2()
{
  static bool rcving = false;
  static byte nde = 0;  //index
  char SM = '$';   //start marker
  char EM = '\n';  //end marker
  char rc;    
  while (Serial2.available()) 
  {
    rc = Serial2.read(); 
    if (rcving) 
    {       
      if (rc != EM)   
      {
        Dev2.Data[nde] = rc; 
        nde++; 
        if (nde >= MaxSize)  
        {
          nde = nde - 2;
        }
        Dev2.Data[nde] = '\0'; 
      }
      else   
      {
        Dev2.Data[nde] = '\n';
        nde++;        
        Dev2.Data[nde] = '\0'; 
        rcving = false;
        nde = 0;
        TX_Dev2();     // At this point the transmitted message is complete so i send it to the USB port 
      }
    }
    else if (rc == SM)
    {
      rcving = true;            
    }
  } 
}

void TX_Dev1()
{
  Serial.print(Dev1.Data);
}

void TX_Dev2()
{
  Serial.print(Dev2.Data);
}

and here is my attempt to convert it to object oriented


class Serial_Devices
{
  public:
    void RX();
    void TX();
  private:
    char Data[100];   
};
Serial_Devices Dev1,Dev2;

void setup() 
{
  Serial.begin(38400);
  Serial1.begin(9600);  
  Serial2.begin(38400);
}



void loop() 
{
  
}

void RX()
{
  static bool rcving = false; 
  static byte nde = 0;  //index
  char SM = '$';   //start marker
  char EM = '\n';  //end marker
  char rc;    
  while (Serial1.available()) 
  {
    rc = Serial1.read(); 
    if (rcving) 
    {       
      if (rc != EM)   
      {
        Dev1.Data[nde] = rc; 
        nde++; 
        if (nde >= MaxSize)  
        {
          nde = nde - 2;
        }
        Dev1.Data[nde] = '\0'; 
      }
      else   
      {
        Dev1.Data[nde] = '\n';
        nde++;        
        Dev1.Data[nde] = '\0'; 
        rcving = false;
        nde = 0;
        TX();        
      }
     }
  }
}

void RX ()
{
  
}

So what i do not know is, first, how to make both objects (Dev1 and Dev2) use the RX() function but each listen to it’s own dedicated serial port and second, how to make the RX function transmitt the received characters from the two different objects.

I thought that i could in the same class create different functions for RX Dev1 and RX Dev2 as well as TX for Dev1 and TX for Dev2 but that would not be the correct approach now would it ?

That is not how OOP works. When you create a class, you define methods within that class so each object will have its own RX and TX function. You could create a function in your class called begin() [just like serial] that takes a reference to which port you wish to use.

Look at how the Serial library is implemented

1 Like

I try to understand but in my case i have a very very poor knowledge in C and C++(programming whatsoever).
So my idea to create different functions for each object is correct then?

Ahh. Probably a silly question but where can i find the library’s files ?
I will try to take a look at the serial library as you suggested but i doubt i will be able to figure it out.

The Serial1 and Serial2 objects inherit their “.available()” and “.read()” behavior from the Stream class. A pointer to a Stream object can point to either one. Each instance has a pointer to a Stream, a buffer, a buffer index, and an update() method to do the work.

const byte BufferSize = 100;

const char SM = '$';   //start marker
const char EM = '\n';  //end marker

class GPSPort
{
  public:
    GPSPort(Stream *serialport) : serialport(serialport) {}
    void update();

  private:
    Stream * serialport;
    char buffer[BufferSize];
    byte bufferIndex = 0;  //index
};

void GPSPort::update()
{
  if (!serialport->available())
    return;

  char  rc = serialport->read();

  if (rc == EM)
    {
    Serial.println(buffer);
    bufferIndex = 0;
  }
  else // Not an end marker
  {
    // Add the character and closing null if there is room.
    if (bufferIndex < BufferSize - 1)
    {
      buffer[bufferIndex++] = rc;
      buffer[bufferIndex] = '\0';
    }
  }
}



GPSPort GPS1(&Serial1);
GPSPort GPS2(&Serial2);

void setup()
{
  Serial.begin(38400);

  Serial1.begin(9600);  // GPS1
  Serial2.begin(38400); // GPS2
}

void loop()
{
  GPS1.update();
  GPS2.update();
}
2 Likes

Wow. I didnt expect that you will write the code for me. Thank you !
I looked at your code and i dont really understand how it works. I hoped it would be a little easyer for me :stuck_out_tongue:
I do know that it is impossible for you to teach me C++.
I guess im not too bad for self-taught but I have to try my best and keep looking and reading so hopefully one day i will be able to understand what exactly is going on here :slight_smile:
P.S.
Where is that add karma button ?

@johnwasser Are you not looking for the start marker? Or, as usual, did I miss something?

-jim lee

1 Like

Yes, I left that out. In my rush, I did not see that part of the original sketch. It also had been left out of the “Object Oriented” attempt. Wouldn’t be hard to put in.

1 Like

Oops… My bad !

I have overlooked the else if part containing the start marker.
Sorry !

I am watching tutorials and reading articles in order to learn how to properly use the C++ language but the major problem i face is that the tutorials i use are for computer programming, not microcontroller programing. The other problem is that though i have a fairly good knowledge of the english language, I do not understand the terminology of the C++ language…

Here is a version with the Start Marker added.

const byte BufferSize = 100;

const char SM = '$';   //start marker
const char EM = '\n';  //end marker

class GPSPort
{
  public:
    GPSPort(Stream *serialport) : serialport(serialport) {}
    void update();

  private:
    Stream * serialport;
    char buffer[BufferSize];
    byte bufferIndex = 0;  //index
    bool foundStart = false;
};

void GPSPort::update()
{
  if (!serialport->available())
    return;

  char  rc = serialport->read();

  if (!foundStart && rc == SM)
  {
    foundStart = true;
  }
  else
  if (foundStart && rc == EM)
  {
    Serial.println(buffer);  // Send the buffer with a newline
    bufferIndex = 0;
    foundStart = false;
  }
  else // Not an end marker
  {
    // Add the character and closing null if there is room.
    if (foundStart && bufferIndex < BufferSize - 1)
    {
      buffer[bufferIndex++] = rc;
      buffer[bufferIndex] = '\0';
    }
  }
}



GPSPort GPS1(&Serial1);
GPSPort GPS2(&Serial2);

void setup()
{
  Serial.begin(38400);

  Serial1.begin(9600);  // GPS1
  Serial2.begin(38400); // GPS2
}

void loop()
{
  GPS1.update();
  GPS2.update();
}
1 Like

C++ is C++, a tutorial that teaches you the language will be fine whether you’re using it to program a PC or a micro controller.

Later on, it may help to get some more Arduino focussed help, but to get started it’s probably easier to write little programs on a PC because the debugging tools are more substantial.

+1

I can’t imagine trying to learn programming from scratch using an Arduino. No time spent learning C/C++ will be wasted, at least not until you’ve learned the basic concepts.

Any decent tutorial should be explaining the terminology as it, um, explains the terminology…

So maybe you haven’t found a decent tutorial or one that matches your learning style.

And there are online C/C++ compilers that will let you code and run and test all day long without worrying about uploading code, and as @wildbill points out, with way more ease of seeing what you are doing…

a7

I spent years as a “computer programmer”. I program the Arduinos just like they were “computers”. I really don’t notice much of a difference.

The real trick to coding is to not learn to speak in code. Teach your computer to speak in human.

-jim lee

Always oops is powerful and preferable

1 Like

Sometimes maybe never always.

a7

1 Like

Well it does but it is all in Hellenic language (my native language). Only some times it explains both in Hellenic and english so when i come across some other tutorial on the internet that is in english language, it gives me a really hard time to match the concepts in my head.

I want it so much to learn the C++ but it’s just overwhelming! Maybe the problem is or makes it worse that i have a poor knowledge of C.

To use c++ you don’t have to learn ALL of it. I only know a tiny subset, and I’m more’n happy with that.

-jim lee

1 Like

I suppose but i dont know what to keep and what to skip :stuck_out_tongue:

By the way i have an other question.

Within an object of a class do all methods have access to all private members (of the same object of that class) or only the acessor methods do ?

Hell, I don’t even know what an accessor method is.

When I develop classes, I tend start off by making everything public. Then later, I may make some stuff protected. Not sure what the difference between protected and private is though…

-jim lee