using structs as pointer i multiple function.

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys. 

 

Im quite new to this AVR world but have background as PLC programmer.

 

 

My qustion is about, what is the best/most correct way to solve this situation.

 

I'm planning to build a little machine which have 4 identical "units" each unit could have 1 motor, couple of sensors and so on, but they are completely identical.

 

 

 

As I have read or tryid to figure out until now, this solution should be fine to go with. Are I'm right? Is there some pitfalls I should think about here?

 

The 4 units will be running at the same time, and the data most be possible read read from outside the function itself (PUBLIC).

 

all comments and suggestions are more than welcome. 

 

struct machineCommands
{
    bool start, stop, restart, acknowledgeFaults;
};
machineCommands machineCommands[4];  // the array of 4 is an array for each unit.

struct recipeDisc
{
uint16_t amount, speedH, speedL;
};
recipeDisc recipeDisc[4];  // the array of 4 is an array for each unit.

void discProgram(struct machineCommands * machineCommands, struct recipeDisc * recipeDisc)
{

//Read and write instantly to the referenced variables

if(machineCommands->start)
//do stuff

//load paramemters from recipe
 var = recipeDisc->speedH;
}

void loop(){

   //Unit 1 - array position 0
   discProgram(&machineCommands[0], &recipeDisc[0]);

    //Unit 2 - array position 1
   discProgram(&machineCommands[1], &recipeDisc[1]);

      //Unit 3 - array position 2
   discProgram(&machineCommands[2], &recipeDisc[2]);

      //Unit 4 - array position 3
   discProgram(&machineCommands[3], &recipeDisc[3]);

}

 

 

 

 

 

 

 

 

Kasper Vissing

Last Edited: Mon. Jun 24, 2019 - 10:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like you’re using Arduino, so you can use classes in C++. Basically the same as what you’ve done, but a bit ‘nicer’.

As an aside, rather than using ‘magic numbers’ like 4, use a #define like #define NUM_RECIPES 4

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

By class, you mean wrap it up in a header?

 

It just thought it was at litle too much since its not a "Lib" for reuse?

Kasper Vissing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

By ‘class’ i mean a c++ class. You have four objects that work the same, that’s reuse! The idea of objects is to combine data and code together. You write methods to operate on that data. Rather than an array of four data structures, you would have an array of four objects.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C++ class'es are the natural evolution of struct{}. Now you not only group the data items that apply to some "object" but you also group with it the functions that act on the data. So you discProgram() would now become part of the class. Because you can now set the data items to be "private:" or "public:" you can keep as much of the data "hidden inside" the object as possible.

 

Oh and whether you use struct{} or class{} don't put multiple members on one line:

struct machineCommands
{
    bool start;
    bool stop;
    bool restart;
    bool acknowledgeFaults;
};

machineCommands machineCommands[4];

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your help.

 

I could use a little more help/link for figuring out how to write a public struct in the class. ? :/ 

 

 

Kasper Vissing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Roughly...

// machine.h
class machine {
    struct machineCommands
    {
        // surely it's only ever one of these so these should be an
        // enum then a state variable of that enum type?
        bool start;
        bool stop;
        bool restart;
        bool acknowledgeFaults;
    };

    struct recipeDisc
    {
        uint16_t amount;
        uint16_t speedH;
        uint16_t speedL;
    };

    void discProgram(struct machineCommands * machineCommands, struct recipeDisc * recipeDisc);
    void setRecipe(uint16_t amnt, uint16_t spdH, uint16_t spdL) {
        recipeDisc.amount = amnt;
        recipeDsic.speedH = spdH;
        recipeDisc.speedL = spdL;
    }

private:    
    machineCommands machineCommand;  // the array of 4 is an array for each unit.

    recipeDisc recipeDisc;  // the array of 4 is an array for each unit.
};
// machine.cpp 
void machine::discProgram()
{

    //Read and write instantly to the referenced variables
    
    if(machineCommands.start)
        //do stuff
        
        //load paramemters from recipe
         var = recipeDisc.speedH;
    }    
}
// main.cpp

machine machines[4];

int main(void) {
    machines[0].setRecipe(12345, 300, 700);
    machines[1].setRecipe(22222, 200, 900);
    machines[2].setRecipe(10000, 400, 500);
    machines[3].setRecipe(13579, 300, 800);

    while(1) {
        machines[0].discProgram();
        machines[1].discProgram();
        machines[2].discProgram();
        machines[3].discProgram();
    }
}

The point in C++ being that all that is "known" about the object is held within. So apart from the calls to setRecipe() which first configure each object nothing outside in main() needs to know about anything "inside" each of the 4 objects that have been created.

 

Also as my comment says I can't help thinking that:

    struct machineCommands
    {
        // surely it's only ever one of these so these should be an
        // enum then a state variable of that enum type?
        bool start;
        bool stop;
        bool restart;
        bool acknowledgeFaults;
    };

looks like it really ought to be something like:

    enum machineState
    {
        // surely it's only ever one of these so these should be an
        // enum then a state variable of that enum type?
        START,
        STOP,
        RESTART,
        ERROR
    };

then the private: members of the class might include:

machineState eState;

or similar.

 

One other thing my example shows is that for the "big" functions in the class you declare them in the class header but define them in a separate .cpp file (where classname:: identifies them as being the implementation of functions in that class) but for small functions (often "getters" and "setters" you can just put the short implementation into the header based class declaration ( as in setRecipe()).

 

I haven't mentioned constructors and destructors here but when a "machine" is created you can have a special function run to initialise some things within it.

 

Oh and the class implementation doesn't need to worry about [] indexing of multiple objects. You simply create the [4] element array of objects and each gets its own private set of machineCommand and recipeDisc etc.

 

When the code in the machine.cpp runs and it makes access to class members it means that member in the "current" object - this is known in the trade as "this". It's like when the function is called it's really:

void machine::discProgram(class Machine * this)
{

    //Read and write instantly to the referenced variables
    
    if(this->machineCommands.start)
        //do stuff
        
        //load paramemters from recipe
         var = this->recipeDisc.speedH;
    }    
}

Unlike Python (which uses "self") C++ avoids the need to specifically use this-> to identify the things that belong to the class it acts on.