"begin" was not declared in this scope, but not being called

I am trying to learn how to define and iterate an array of arrays and I am struggling with syntax. Can anyone help me understand why it is talking about begin when it was never used, and what I am doing wrong? *(pure code no hardware required)

This compiles if you remove;

  for (const auto& relayArray : relayGroups) { 
    for (const auto& relay : relayArray) {
      Serial.println(relay.name);
    }
  }

All the code;

#include <String.h>

class Relay {
public:
  Relay(String name, int pin, bool reversed=false, bool state=false) 
  :name(name), pin(pin_), reversed(reversed_), state(state) {}
  String name; int pin; bool reversed; bool state;
  void enable() {
    if (!reversed_) {
      digitalWrite(pin_, HIGH);
    } else {
      digitalWrite(pin_, LOW);
    }
  }
  void disable() {
    if (!reversed_) {
      digitalWrite(pin_, LOW);
    } else {
      digitalWrite(pin_, HIGH);
    }
  }
  void printName() {
    Serial.println(name);
  }
private:
int pin_;
bool reversed_;
};

Relay valveRelays[] = {
 Relay("VALVE_INPUT", 13),
 Relay("VALVE_MIXER", 14),
 Relay("VALVE_RES_1", 15),
 Relay("VALVE_RES_2", 16)
};
Relay pumpRelays[] = {
 Relay("PUMP_MAIN", 13),
 Relay("PUMP_NUT_1", 14),
 Relay("PUMP_NUT_2", 15),
 Relay("PUMP_NUT_3", 16),
 Relay("PUMP_NUT_4", 17),
 Relay("PUMP_NUT_5", 18),
 Relay("PUMP_NUT_6", 19),
 Relay("PUMP_NUT_7", 20),
};
Relay* relayGroups[2] = {
  valveRelays, pumpRelays
};

Relay getRelay(String name) {
  for (Relay relay : valveRelays) {
    if (relay.name == name) {
      return(relay);
    }
  }
  for (Relay relay : pumpRelays ) {
    if (relay.name == name) {
      return(relay);
    }
  }
  return(Relay("NOT FOUND", 0));
}

void setup() {
  delay(1000);
  Serial.begin(9600);
  delay(1000); 
};

bool loopSetup = false;
void loop() {
  for (const auto& relayArray : relayGroups) { 
    for (const auto& relay : relayArray) {
      Serial.println(relay.name);
    }
  }
  delay(10000);
};

"c++ for begin was not declared in this scope"

...the answer is in the first hit.

I wish that were more help. I am not sure what to modify.

guess I'm ganna use Vector instead

relayGroups is an array of pointers. for / range loops cannot work for pointers (i.e., relayGroups[0] and relayGroups[1]). There's no way, in general, for the compiler to know the range.

I'm struggling to understand why two for-loops is so offensive.

mostly because in modern languages this can be as simple as
for x in y: for a in x: do(a)
so from what I can tell it isn't possible at all with arrays
I am working on trying vectors instead

Those languages do not have pointers.

I assume you are failing to either understand or read or both. It works for arrays. It does not work for pointers.

There is, of course, overhead with vectors. If your application can tolerate that then it's very likely a reasonable choice.

I hope it goes well for you.

  for (Vector<Relay> relayGroup : relayGroups) {
    for (Relay relay : relayGroup) {
      Serial.println(relay.name);
      relay.printName();
    }
  }

prints nothing. so not really.

#include <String.h>
#include <Vector.h>

class Relay {
public:
  Relay(String name, int pin, bool reversed=false, bool state=false) 
  :name(name), pin(pin_), reversed(reversed_), state(state) {}
  String name; int pin; bool reversed; bool state;
  void enable() {
    if (!reversed_) {
      digitalWrite(pin_, HIGH);
    } else {
      digitalWrite(pin_, LOW);
    }
  }
  void disable() {
    if (!reversed_) {
      digitalWrite(pin_, LOW);
    } else {
      digitalWrite(pin_, HIGH);
    }
  }
  void printName() {
    Serial.println(name);
  }
private:
int pin_; bool reversed_;
};

Vector<Relay> valveRelays;
Vector<Relay> pumpRelays;
Vector<Vector<Relay>> relayGroups;
void setup() {
  delay(1000);
  Serial.begin(9600);
  delay(1000); 

  // RELAY CODE
  valveRelays.push_back(Relay("VALVE_INPUT", 13));
  valveRelays.push_back(Relay("VALVE_MIXER", 13));
  valveRelays.push_back(Relay("VALVE_RES_1", 13));
  valveRelays.push_back(Relay("VALVE_RES_2", 13));
  valveRelays.push_back(Relay("PUMP_MAIN", 13));
  valveRelays.push_back(Relay("PUMP_NUT_1", 13));
  valveRelays.push_back(Relay("PUMP_NUT_2", 13));
  valveRelays.push_back(Relay("PUMP_NUT_3", 13));
  valveRelays.push_back(Relay("PUMP_NUT_4", 13));
  valveRelays.push_back(Relay("PUMP_NUT_5", 13));
  valveRelays.push_back(Relay("PUMP_NUT_6", 13));
  valveRelays.push_back(Relay("PUMP_NUT_7", 13));
  relayGroups.push_back(pumpRelays);
  relayGroups.push_back(valveRelays);
};

bool loopSetup = false;
void loop() {
  if (!loopSetup) {
    loopSetup = true;
  }
  delay(1000);
  for (Vector<Relay> relayGroup : relayGroups) {
    for (Relay relay : relayGroup) {
      Serial.println(relay.name);
      relay.printName();
    }
  }
  delay(1000);
};

I guess iterating nested objects is either syntactically trash or too picky to sort out, so I won't do it because I don't need to. Tired of being frustrated with this.

Maybe I can get a basic example working with Dictionary.

Does your solution demand for / range?

Try to define the relaygroups not as just a pointers, but as a structure, containing a pointer to array and it size. In that case you could iterate the inner for loop by indexes.

Side note: do not forget the fact that now you program a microcontrollers with a memory of few kilobytes and not a PC with gigabytes of RAM. Your classes are very memory consuming. For example, why do you need a relay names, so obvious as combination of "Relay" and index?

Get rid of the strings and use definitions. a definition will substitute the text with its value before compiling.

#define VALVE_INPUT 0
#define VALVE_MIXER 1
#define BLAH_BLAH 2

If you need to access what the valve is within the class you can also store the definition number as a int8_t (1 byte)
Eg.

int8_t relayType = VALVE_MIXER;

If (relayType == VALVE_MIXER)

As an added bonus the definition can match the position in the array.

You can then also reference the array,

relayArray[VALVE_MIXER]

Hello underhilll

Do you need to use a "class definition" for your project?

My practical recommendation is to use a structured array with member functions, as already mentioned by b707.

Have a nice day and enjoy coding in C++.

So that the code is change tolerant and easy to add and remove things without a ton of mucking about

I could easily manually size everything, manually declare both sub lists and the full list of relays, duplicate code and a million other things

I am an object oriented developer so doing it this way makes sense to me, I am at the point where I know I can get a result and I don't need years of lessons in another language to get the result I want. So screw it.

I just wanted to know better, know a little more, find some better practices, but I don't need to and I'm done with it.

I think I need to get a raspberry pi.

This is 8 or 10 lines and the functionality replaces 100 other lines of code or more;

class Relay {
public:
  Relay(String name, int pin, bool reversed=false, bool state=false) 
  :name(name), pin(pin_), reversed(reversed_), state(state) { }
  String name; int pin; bool reversed; bool state;
  void enable() { if (!reversed_) { digitalWrite(pin_, HIGH); } else { digitalWrite(pin_, LOW); } }
  void disable() { if (!reversed_) { digitalWrite(pin_, LOW); } else { digitalWrite(pin_, HIGH); } }
  void printName() {
    Serial.println(name);
  }
private:
  int pin_; bool reversed_;
};

Everything for C++ is so code heavy it is like a puddle a billion miles wide. And then people get picky about syntax! I say if your indents and braces are right, who cares. Whatever.

I can't stress enough that my frustration is with the lack of instantiable, interactable objects and iterating and manipulating them during runtime. This shouldn't be lacking from (or in) any platform at this point.

But who the heck am I to complain about something to which I need not subject myself?

Why not use an enum...
Same amount of binaries, typesafe, easily expandable, no chance you will have two things defined with same number.

I really think you should stop yelling and read how to properly do this. OOP works without any problems on even the smallest arduino.
And nested loops should also be no problem.
You are simply doing something wrong...

4 Likes

enums are just named constants, not even paired to anything, I am going to take a stab at making a state machine and I may use one there but they don't help track real world components with various factors about them in any sane way

I wanted a framework that was easier to develop on so I wanted to figure some patterns out and get some classes going to make manipulating things easier in code. which I guess I did. I don't need nested iteration, it was just education.

It seems to me that you just don’t want to go beyond the boundaries of the usual and admit that the principles of using OOP may be different on different platforms. What is good for Raspberry Pi is not suitable for Arduino Uno. But you can continue to think differently

1 Like

I dont understand what the problem is. I do all of my projects object orientated with enheritance and polymorphism. I use arrays of objejcts, itterate through them manually, track the bounds etc. The only pain is the arduino ide when scrolling through 50 tabs of .h and .cpp files.

You obviously need to be careful with memory management especially if creating new objects that wont live the life of the program.

I write my own librarys (displays, gps, magnometers, nrfs etc) because i hate the bloat that comes with the premade ones (especially ardafruits sensor librarys) - but i find digging through datasheets fun.

If you want to use python, use a raspberry pi. For a microcontroller i think python is too slow, bloated and non deterministic.

For your valve and pumprelay arrays, why not use inheritance, make a base class relay and throw them all in one array?

No problem with any of that. The whole thing was about using them.

Just two arduino problems;

  1. The language is unable to iterate pointed objects with most of its own built ins, or something. Whatever.
  2. Apparently String is considered entirely unsafe, guess the garbage collection doesn't exist or lacks.

Kinda lame that things are arranged that way... I do WANT to use Python. I also WANT to branch out and learn more. But this stuff feels like COBOL or BASIC, featureless and demanding as hell on the developer and not at all change tolerant the way it is meant to be done.

Here's your "not going beyond", a total rewrite of the project. I do want to learn, but this language is 1970-and-late, it is extremely abstract and what seems like intent constantly ends up as a roadblock.

I mean how dare I attempt to iterate a nested object in a programming language using standard syntax? GOD FORBID! :open_mouth:

#include <String.h>

class Relay {
public:
  Relay(String name, int pin, bool reversed=false, bool state=false) 
  : name(name), pin(pin_), reversed(reversed_), state(state) { }
  String name; int pin; bool reversed; bool state;
  void enable() { if (!reversed_) { digitalWrite(pin_, HIGH); } else { digitalWrite(pin_, LOW); } }
  void disable() { if (!reversed_) { digitalWrite(pin_, LOW); } else { digitalWrite(pin_, HIGH); } }
  void printName() { Serial.println(name); }
private:
  int pin_; bool reversed_;
};
Relay valveRelays[] = {
 Relay("VALVE_INPUT", 13, true),
 Relay("VALVE_MIXER", 14, true),
 Relay("VALVE_RES_1", 15, true),
 Relay("VALVE_RES_2", 16, true)
};
Relay pumpRelays[] = {
 Relay("PUMP_MAIN", 13),
 Relay("PUMP_NUT_1", 14),
 Relay("PUMP_NUT_2", 15),
 Relay("PUMP_NUT_3", 16),
 Relay("PUMP_NUT_4", 17),
 Relay("PUMP_NUT_5", 18),
 Relay("PUMP_NUT_6", 19),
 Relay("PUMP_NUT_7", 20)
};

Relay getRelay(String name) {
  for (Relay relay : valveRelays) { if (relay.name == name) { return(relay); } }
  for (Relay relay : pumpRelays ) { if (relay.name == name) { return(relay); } }
}

void disableAllRelays() {
  for (Relay relay : valveRelays) { relay.disable(); }
  for (Relay relay : pumpRelays ) { relay.disable(); }
}

void setup() {
  delay(1000);
  Serial.begin(9600);
  delay(1000);
  disableAllRelays(); 
};

enum mixingStates {
  END,
  DELAY,
  START,
  FILL,
  MIX,
  FINISH,
} mixingState;

mixingStates stateAfterDelay;
unsigned long delayUntil = millis();
bool interruptMixingCycle = false;
void mixingCycle() {
  while( !interruptMixingCycle && mixingState != END ) {
    switch (mixingState) {
      case DELAY:
        if ( delayUntil < millis() ) { mixingState = stateAfterDelay; }
        continue;

      case START:
        Serial.println("MIXING CYCLE START!");
        stateAfterDelay = FILL; delayUntil = millis() + 3000; mixingState = DELAY;
        continue;

      case FILL:
        Serial.println("FILL");
        // getRelay("VALVE_INPUT").enable();
        stateAfterDelay = MIX; delayUntil = millis() + 5000; mixingState = DELAY;
        continue;
      
      case MIX:
        Serial.println("MIX");
        // getRelay("VALVE_MIXER").enable();
        stateAfterDelay = FINISH; delayUntil = millis() + 5000; mixingState = DELAY;
        continue;

      case FINISH:
        disableAllRelays();
        Serial.println("CYCLE DONE!");
        mixingState = END;
    }
  }
}

bool loopSetup = false;
void loop() {
  if (!loopSetup) {
    loopSetup = true;
    mixingState = START;
  }
  // check a button state here
  // to initiate mixing, set mixingState to START if button
  mixingCycle();
};

There is no specific "arduino language"
The language you speak about is a standard C++ 2017

4 Likes