create multiple instances of a class with pointers

my goal is to use a for() loop later in the sketch to check for messages, incrementing through the NUMBER_OF_VALVES. I want a scalable program based on a single #define

So, I want to be able to create multiple instances of the MyMessage class, based on the #define:

    void (*msg1valve[ NUMBER_OF_VALVES + 1 ] )();
    void (*var1valve[ NUMBER_OF_VALVES + 1 ] )();
    void (*var2valve[ NUMBER_OF_VALVES + 1 ] )();

    MyMessage msg1valve0(0,V_LIGHT);
    MyMessage var1valve0(0,V_VAR1);
    MyMessage var2valve0(0,V_VAR2);

    MyMessage msg1valve1(1,V_LIGHT);
    MyMessage var1valve1(1,V_VAR1);
    MyMessage var2valve1(1,V_VAR2);
    
    MyMessage msg1valve2(2,V_LIGHT);
    MyMessage var1valve2(2,V_VAR1);
    MyMessage var2valve2(2,V_VAR2);
    //etc... etc...

how can I do that programmatically versus copying the constructor many times?

Something like this pseudo code:

    for (int i = 0; i <=MUMBER_OF_VALVES; i++)
    {
      MyMessage msg1valve[i](i,V_LIGHT);
      MyMessage var1valve[i](i,V_VAR1);
      MyMessage var2valve[i](i,V_VAR2);
    }

any suggestions?

Something like:

 for (int i = 0; i <=MUMBER_OF_VALVES; i++)
    {
      msg1valve[i] = new MyMessage (i,V_LIGHT);
      var1valve[i] = new MyMessage (i,V_VAR1);
      var2valve[i] = new MyMessage (i,V_VAR2);
    }

Untested, but that is the general idea.

MUMBER_OF_VALVES

?

Proof of concept:

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();

  String * mystrings [10];
  
  for (int i = 0; i < 10; i++)
    mystrings [i] = new String (i);
  
  for (int i = 0; i < 10; i++)
    Serial.println (*mystrings [i]);
  
  }  // end of setup

void loop () { }

thanks Nick, but I am still not able to figure this out.

using this:

void (*msg1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var2valve[ NUMBER_OF_VALVES + 1 ] )();
//
void setup() 
{ 
  for (int i = 0; i <= NUMBER_OF_VALVES; i++)
  {
    msg1valve[i] = new MyMessage (i,V_LIGHT);
    var1valve[i] = new MyMessage (i,V_VAR1);
    var2valve[i] = new MyMessage (i,V_VAR2);
  }
  //...

I get this error:

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.
Arduino: 1.0.6 (Mac OS X), Board: "Arduino Uno"
Sprinkler_V2.0_MySensors_V1.4.1.ino: In function 'void setup()':
Sprinkler_V2.0_MySensors_V1.4.1.ino:103: error: cannot convert 'MyMessage*' to 'void ()()' in assignment
Sprinkler_V2.0_MySensors_V1.4.1.ino:104: error: cannot convert 'MyMessage
' to 'void ()()' in assignment
Sprinkler_V2.0_MySensors_V1.4.1.ino:105: error: cannot convert 'MyMessage
' to 'void (*)()' in assignment

constructor is this format:

MyMessage(uint8_t childSensorId, uint8_t variableType);

Is it something to do what the argument mis-match?

I'm not going to sit here and try to guess what all your data types are.

http://snippets-r-us.com/

Post enough code that I can try compiling it, not just snippets.

Although this looks wrong:

void (*msg1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var2valve[ NUMBER_OF_VALVES + 1 ] )();

Do you have one function that takes an array, or an array of functions that take one argument?

OK....

Trying to set up multiple instances of MyMessage in order to sort the messages in a simple, extensible loop. There is the full code:

/*

 */
// 
//#include <avr/pgmspace.h>
#include <MySensor.h>
#include <SPI.h>
//
#define NUMBER_OF_VALVES 8 // Change this to set your valve count.
#define RESET_TIME 5000    // Change this (in milliseconds) for the time you need your valves to hydraulically change state
#define RADIO_ID AUTO
//
typedef enum {
  ALL_ZONES_OFF, SINGLE_ZONE_OPERATION, RUN_ALL_ZONES}
SprinklerStates;
//
SprinklerStates state = ALL_ZONES_OFF;
SprinklerStates lastState;
//
int valveTime [NUMBER_OF_VALVES + 1];
int valveSoloTime [NUMBER_OF_VALVES + 1];
int valveIntID [17] = { 0b1111111111111111, 0b1111111111111110, 0b1111111111111101, 0b1111111111111011, 0b1111111111110111, 0b1111111111101111, 0b1111111111011111, 0b1111111110111111, 0b1111111101111111, 0b1111111011111111, 0b1111110111111111, 0b1111101111111111, 0b1111011111111111, 0b1110111111111111, 0b1101111111111111, 0b1011111111111111, 0b0111111111111111};// this array is good up to sixteen valve positions, even if you select less.
int valveNumber;
unsigned long startMillis;
//
unsigned long oneHour = 3600000UL;
unsigned long hourTimer;
//
//Setup Shift Register
//
int latchPin = 8;
int clockPin = 4;
int dataPin  = 7;
int pin = 3;//
int ledPin = 5; // LED status blinks fast while changing a valve; steady during valve open or initialization; and slow blink when in stand-by
boolean buttonPushed = false;
// 
MySensor gw;
//

void (*msg1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var2valve[ NUMBER_OF_VALVES + 1 ] )();
//
void setup() 
{ 
  /*
  for (int i = 0; i <= NUMBER_OF_VALVES; i++)
  {
    msg1valve[i] = new MyMessage (i,V_LIGHT);
    var1valve[i] = new MyMessage (i,V_VAR1);
    var2valve[i] = new MyMessage (i,V_VAR2);
  }*/
  Serial.begin(115200);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(pin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  attachInterrupt(1, PushButton, CHANGE);
  digitalWrite (ledPin, HIGH);
  //
  gw.begin(getVariables, RADIO_ID, false); // Does not create a Radio repeating node
  delay(3000);
  gw.sendSketchInfo("NewSprinkler", "2.0");
  delay(3000);
  for (int i = 0; i <= NUMBER_OF_VALVES; i++)
  {
    gw.present(i, S_LIGHT);
    delay(3000);
  }
  Serial.println(F("Sensor Presentation Complete"));
  //
  updateRelays(valveIntID[0]);
  Serial.println(F("All Valves OFF"));
  /*
  for (int i = 0; i <= NUMBER_OF_VALVES + 1; i++)
   {
   //Set all valves off
   }
   */
  //getTimesVera();
  hourTimer = millis();
  digitalWrite (ledPin, LOW);//ready
  Serial.println(F("READY"));
}
//
void loop()
{
  gw.process();
  //
  if (buttonPushed)
  {
    if (state != RUN_ALL_ZONES);
    {
      state = RUN_ALL_ZONES;
      valveNumber = 1;
      startMillis = millis();
      Serial.println(F("Button Pressed!!!"));
      Serial.println(F("Manually directed cycling through all valves"));
      Serial.print(F("state = ")); 
      Serial.println(state);
    }
    buttonPushed = false;
  }
  if (state == ALL_ZONES_OFF) 
  {
    slowToggleLED (); 
    if (lastState != state)
    {
      updateRelays(valveIntID[0]);
    }
  }
  //
  if (state == RUN_ALL_ZONES)
  { 
    fastToggleLed();
    unsigned long nowMillis = millis();
    if (nowMillis - startMillis < RESET_TIME)
    {
      updateRelays(valveIntID[0]);
    }
    else if (nowMillis - startMillis < (valveTime[valveNumber] * 60000UL))
    {
      digitalWrite (ledPin, HIGH);
      updateRelays(valveIntID [valveNumber]);
    }
    else
    {
      updateRelays(valveIntID[0]);
      startMillis = millis();
      valveNumber++;
      if (valveNumber > NUMBER_OF_VALVES) 
      {
        state = ALL_ZONES_OFF;
        digitalWrite (ledPin, LOW);
        Serial.print(F("State = ")); 
        Serial.println(state);
      }
    }
  }
  //
  if (state == SINGLE_ZONE_OPERATION)// Run single valve
  {
    fastToggleLed();
    unsigned long nowMillis = millis();
    if (nowMillis - startMillis < RESET_TIME)
    {
      updateRelays(valveIntID[0]);
    }
    else if (nowMillis - startMillis < (valveSoloTime [valveNumber] * 60000UL))
    {
      digitalWrite (ledPin, HIGH);
      updateRelays(valveIntID [valveNumber]);
    }
    else if (nowMillis - startMillis > (valveSoloTime [valveNumber] * 60000UL))
    {
      updateRelays(valveIntID[0]);
      state = ALL_ZONES_OFF;
      digitalWrite (ledPin, LOW);
      Serial.print(F("State = ")); 
      Serial.println(state);
    }
  }
  lastState = state;
}
//
void updateRelays(int value)
{
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, highByte(value)); 
  shiftOut(dataPin, clockPin, MSBFIRST, lowByte(value));
  digitalWrite(latchPin, HIGH);
}
//
void PushButton(){ //interrupt with debounce
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  if (interrupt_time - last_interrupt_time > 200)
  {
    Serial.println(F("interrupt"));
    buttonPushed = true;
  }
  last_interrupt_time = interrupt_time;
}
//
void fastToggleLed()
{
  static unsigned long fastLedTimer;
  if (millis() - fastLedTimer >= 100UL)
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    fastLedTimer = millis (); 
  }   
}
//
void slowToggleLED ()
{
  static unsigned long slowLedTimer;
  if (millis() - slowLedTimer >= 1250UL)
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    slowLedTimer = millis (); 
  } 
}
//
void getVariables(const MyMessage &message)
{
  if (message.isAck()) 
  {
    Serial.println("This is an ack from gateway");
  }
  for (int i = 1; i<= NUMBER_OF_VALVES; i++)
  {
    if (message.sensor == i)
    {
      if (message.type == V_VAR1)
      {
        //get single duration
      }
      if (message.type == V_VAR2)
      {
        //get cycle duration
      }
    }
  }
}

Stripped down only for the purpose of creating the function pointer:

#include <MySensor.h>
#include <SPI.h>
//
#define NUMBER_OF_VALVES 8 // Change this to set your valve count.
//
int valveTime [NUMBER_OF_VALVES + 1];

// 
MySensor gw;
//

void (*msg1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var2valve[ NUMBER_OF_VALVES + 1 ] )();
//
void setup() 
{ 
  for (int i = 0; i <= NUMBER_OF_VALVES; i++)
  {
    msg1valve[i] = new MyMessage (i,V_LIGHT);
    var1valve[i] = new MyMessage (i,V_VAR1);
    var2valve[i] = new MyMessage (i,V_VAR2);
  }
}
void loop()
{
  
}

The last function of the entire sketch will be used to sort all of the incoming messages

You won't be able to compile it without the MySensors libraries... but I have the MyMessages.h and MyMessages.cpp attached here:

MyMessage.cpp (4.48 KB)

MyMessage.h (7.24 KB)

void (*msg1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var1valve[ NUMBER_OF_VALVES + 1 ] )();
void (*var2valve[ NUMBER_OF_VALVES + 1 ] )();

Shouldn't that be:

void (*msg1valve[ NUMBER_OF_VALVES + 1 ] )(uint8_t sensor, uint8_t type);
void (*var1valve[ NUMBER_OF_VALVES + 1 ] )(uint8_t sensor, uint8_t type);
void (*var2valve[ NUMBER_OF_VALVES + 1 ] )(uint8_t sensor, uint8_t type);

After all, when you do a "new" you are passing arguments to the constructors.

well, I am thinking I am approaching this in the wrong way... I tried your suggestion and with this sketch:

#include <MySensor.h>
#include <SPI.h>
//
#define NUMBER_OF_VALVES 8 // Change this to set your valve count.
//
int valveTime [NUMBER_OF_VALVES + 1];

// 
MySensor gw;
//
void (*msg1valve[ NUMBER_OF_VALVES + 1 ] )(uint8_t sensor, uint8_t type);
void (*var1valve[ NUMBER_OF_VALVES + 1 ] )(uint8_t sensor, uint8_t type);
void (*var2valve[ NUMBER_OF_VALVES + 1 ] )(uint8_t sensor, uint8_t type);
//
void setup() 
{ 
  for (int i = 0; i <= NUMBER_OF_VALVES; i++)
  {
    msg1valve[i] = new MyMessage (i,V_LIGHT);
    var1valve[i] = new MyMessage (i,V_VAR1);
    var2valve[i] = new MyMessage (i,V_VAR2);
  }
}
void loop()
{
  
}

compiler complains:

sketch_nov13a.ino: In function 'void setup()':
sketch_nov13a:20: error: cannot convert 'MyMessage*' to 'void ()(uint8_t, uint8_t)' in assignment
sketch_nov13a:21: error: cannot convert 'MyMessage
' to 'void ()(uint8_t, uint8_t)' in assignment
sketch_nov13a:22: error: cannot convert 'MyMessage
' to 'void (*)(uint8_t, uint8_t)' in assignment

I cannot figure this out.

would you approach this differently?

Replace:

void (*msg1valve[ NUMBER_OF_VALVES + 1 ] )(uint8_t sensor, uint8_t type);
void (*var1valve[ NUMBER_OF_VALVES + 1 ] )(uint8_t sensor, uint8_t type);
void (*var2valve[ NUMBER_OF_VALVES + 1 ] )(uint8_t sensor, uint8_t type);

by:

MyMessage * msg1valve [ NUMBER_OF_VALVES + 1 ];
MyMessage * var1valve [ NUMBER_OF_VALVES + 1 ];
MyMessage * var2valve [ NUMBER_OF_VALVES + 1 ];

And then it should compile.

After all, you want an array of MyMessage pointers, don't you?

I think you're over complicating it. Looking at the constructor, it's just expecting two uint8_t type values. One of these is Sensor (I don't really know what it's for) and the other is for sensorType.

Sooner or later you need to define what the value for sensor and sensor type are for each of your Valves. I'd suggest the best way would be in an array, just after that define statement.

So this is what I come up with as an example.

#include <MyMessage.h>

#define NUMBER_OF_VALVES 23
uint8_t SensorType[NUMBER_OF_VALVES]=
  {V_TEMP, V_HUM, V_LIGHT, V_DIMMER, V_PRESSURE, 
   V_FORECAST, V_RAIN, V_RAINRATE, V_WIND,V_GUST, 
   V_DIRECTION, V_UV, V_WEIGHT, V_DISTANCE, V_IMPEDANCE,
   V_ARMED, V_TRIPPED, V_WATT, V_KWH, V_SCENE_ON, 
   V_SCENE_OFF,V_HEATER, V_HEATER_SW
   //ETC..
   };

uint8_t Sensor[NUMBER_OF_VALVES]=
 {1,2,3,4,5,6,7,8,9,10,11,
  12,13,14,15,16,17,18,19,
  20,21,22,23};

MyMessage* msgValve   [NUMBER_OF_VALVES];

void setup()
{
for(int n=0;n<NUMBER_OF_VALVES;n++)
  msgValve[n]= new MyMessage( Sensor[n],SensorType[n]);
}

void loop()
{

}

Thanks Nick.

Compiles certainly, now to test to see if it works as I expect!

I'm going to muck around with that for a while...

I appreciate the assistance.

Ken,

Lemme look at what you did... I'll get back to you.

BulldogLowell:
Lemme look at what you did... I'll get back to you.

OK BTW if you were to follow my scheme of things (and excuse me if I'm teaching you to suck eggs) Within your loop you'd have to use the -> to get to the members of the MyMessage members. Rather like this.

#include <MyMessage.h>

#define NUMBER_OF_VALVES 23
uint8_t SensorType[NUMBER_OF_VALVES]=
  {V_TEMP, V_HUM, V_LIGHT, V_DIMMER, V_PRESSURE, 
   V_FORECAST, V_RAIN, V_RAINRATE, V_WIND,V_GUST, 
   V_DIRECTION, V_UV, V_WEIGHT, V_DISTANCE, V_IMPEDANCE,
   V_ARMED, V_TRIPPED, V_WATT, V_KWH, V_SCENE_ON, 
   V_SCENE_OFF,V_HEATER, V_HEATER_SW
   //ETC..
   };

uint8_t Sensor[NUMBER_OF_VALVES]=
 {1,2,3,4,5,6,7,8,9,10,11,
  12,13,14,15,16,17,18,19,
  20,21,22,23};

MyMessage* msgValve   [NUMBER_OF_VALVES];

void setup()
{
for(int n=0;n<NUMBER_OF_VALVES;n++)
  msgValve[n]= new MyMessage( Sensor[n],SensorType[n]);
}

void loop()
{
int n;
char buffer[30];
for(n=0;n<NUMBER_OF_VALVES;n++)
  {switch(SensorType[n])
    {case V_TEMP:
      sprintf(buffer,"Sensor %d: Temp=%d",n, msgValve[n]->getInt());
      break;
     case V_HEATER_SW:
       sprintf(buffer, "SWITCH %d is %s", n, (msgValve[n] -> getBool()) ? "ON":"OFF");
    }
    Serial.print(buffer);
  }
}

Obviously my implementation here is probably way off base as I haven't a clue what those member functions are all about.