Object orientation and iteration requirements

I'm new to the Arduino and real-time/real-world code in general. I'm enjoying coding for a modestly complex Arduino application. I've never done much in C, but until I face arcane issues of one kind or another I'm finding it simple enough.

I'm also relatively unschooled in object oriented programming, though I understand the basics and have coded some here and there over the years. My current project could definitely benefit from object coding, but a real-time issue is leaving me puzzled.

I need to gradually brighten a lamp using PWM on cue; e.g., when a particular input condition is met, capture current millis() in a timer variable, and use MAP to get an 8 bit level for the PWM from the brightening duration. At least that's what I'm doing and it works simply and quite well.

But having a lot of lamps for which this must be done suggests -- to my noob mind, anyway -- that it'd be less hassle to instance an object for each lamp, with a brighten method in play.

Question: how the heck could a "brighten" method in a lamp object work during each iteration of the main loop to change the PWM incrementally on each pass? Passing to the method a duration of brightening, a beginning level and an end level, for example (400, 0, 255) -- well, I can't imagine how it would work.

It'd be nice of the Arduino would multithread. ;)

Anyone have any ideas for this? It's possible I'm entirely missing something obvious, but for the life of me I can't figure this out.

Just now I have a "brighten" function I call from a "lamps" function, which moves most individual lamp code out of loop, of course, but very little out of the "lamps" function. The timers and everything really clutter that up. The lamps function basically just takes which lamp to act on, what timer variable corresponds to it, and then it does the brightening using a MAP statement.

I just don't think it can all be in the object. Am I right?

I just don't think it can all be in the object. Am I right

You're probably wrong. There's no real reason the lamp state (current brightness, last update time, brightness increment) can't be held as "private" variables within the object (class).

You're talking about properties alone -- the crux of my puzzlement was this: " how the heck could a 'brighten' method in a lamp object work during each iteration of the main loop to change the PWM incrementally on each pass? Passing to the method a duration of brightening, a beginning level and an end level, for example (400, 0, 255) -- well, I can't imagine how it would work."

If I can't get most of what I need to do in the object -- if the object needs so much external help because it doesn't execute code during each loop (or doing so would defeat its purpose) -- then that is defeating, I believe, one of the purposes of using the object.

Objects can be useful for their properties, true enough. I'm just wondering, in the instance of the case I'm facing, whether in real-time systems they're useful for methods which don't always involve instant action -- methods which, when triggered, must do something over an interval during which the main loop must not be neglected.

Argh.

that it'd be less hassle to instance an object for each lamp

Definately!

It sounds like you are making your classes too "course grained" (too much functionality in too few classes). The solution is simple: you need more classes. The trick is to identify them and assign responsibilities.

Let's talked about the actors. You've identified the first: Lamp. From your description, Lamp knows its current brightness and is capable of changing to a new brightness.

Hopefully some questions will help identify the other actors...

Who decides when a brightness should change? Who decides what the new brightness should be? Is it the same actor making both decisions?

What are you building? An art display? A smart room?

when a particular input condition is met

Such as?

Passing to the method a duration of brightening, a beginning level and an end level, for example (400, 0, 255) -- well, I can't imagine how it would work

No, all that goes to the constructor, or to the initialiser method.

"course grained" (too much functionality in too few classes).

"coarse-grained" (too few English classes) :D

"coarse-grained" (too few English classes)

You mean too few English courses? ;)

If I wish for the object to provide methods for fading, dimming, brightening, offing, or oning a lamp (each lamp is an instance), I'm not constructing the thing every time I'm fading, dimming, brightening, offing, or oning it. Right? The constructor would receive which output I'm working with. Methods for each verb in that list would receive relevant parameters. If I wish to brighten a lamp from 0 to 255 over 400 mS, I'd pass that to the method when necessary. Or, for that matter, I could add a "when?" parameter, so that the method could act at a later time.

As for having too few classes, I'm not sure that strikes at the root of the problem -- which is how an object is going to act during the 400 mS in question, during which it needs to increment an analogWrite starting at 0 and ending at 255, while simultaneously the loop cannot be neglected.

To cut to the chase, how would I brighten two lamps simultaneously over 400 mS -- using a "brighten" method in an object instanced for each lamp?

That's really the fundamental question I'm having a problem with. Everything else is just a devil in the details.

If I wish for the object to provide methods for fading, dimming, brightening, offing, or oning a lamp (each lamp is an instance)

Things like off and on are properties of Lamp.

Things like “fading” or “dimming” are often performed by other classes. Like a Fader. Which is why I said, “it sounds like you are making your classes too course coarse-grained.” :slight_smile:

I’m not constructing the thing every time I’m fading, dimming, brightening, offing, or oning it. Right?

Right.

Or, for that matter, I could add a “when?” parameter, so that the method could act at a later time.

And with that, you’ve gone from 200 grit to 80 grit.

As for having too few classes, I’m not sure that strikes at the root of the problem

From what you’ve described, it does. But, it’s your project.

– which is how an object is going to act during the 400 mS in question, during which it needs to increment an analogWrite starting at 0 and ending at 255, while simultaneously the loop cannot be neglected.

This should give you some ideas…

class Lamp
{
public:

  void fade( unsigned long _duration );
  void update( void );

private:
  enum { Idle, Fading } _mode;
  unsigned long _start;
};

void Lamp::fade( unsigned long _duration )
{
  _mode = Fading;
  _start = millis();
}

void Lamp::update( void )
{
  if ( _mode == Fading )
  {
    unsigned long ThisMS = millis();

    if ( ThisMS - _start < 400 )
    {
      // ThisMS - _start is how long we've been fading.  Calculate and output the desired value here.
    }
    else
      _mode = Idle;
  }
}

Call fade to start a fade. Call update every pass through loop.

rasqual,

I think what you're looking for is an array of "Lamp" objects. In your main loop, for each pass through the loop, you'll have to iterate over the array, calling the appropriate method for each instance in the array. You could pass in the current time when you call the method, or call 'millis()' within the method, to know if it's time to change the state of a Lamp.

If you wanted to do it in a non-oo fashion, you could have an array of structures, with each array element holding the state of one lamp. In the main loop, you would iterate through the array, and call an update function with a pointer to the structure.

It sounds like you're asking if using objects can keep you from having to iterate through all the Lamps in the main loop. I can't think of a reasonable way to do it without iteration, with or without objects.

Regards,

-Mike

Thanks for those last couple responses. I have a lot of thinking and playing around to do with this. A SQL and netadmin scripter (and sometimes-dotnet coder), the real-time thing is an entirely new dimension for me.

You're quite right about the granularity thing, and an array seems most practical as the number of lamps grows (or may be considered arbitrary).

Things like "fading" or "dimming" are often performed by other classes.

Would be bad coding practice, other objects have no business meddling around with the properties of the lamp. That said, there is an exception, but wrappers are rarely refered to as just 'classes', since they are strictly dependend on the object they're wrapping.

So yes, all in all I always love reading comments regarding 'people usually do this' or 'bad coding practice', since they defer from the main topic without adding.. well, usually anything :P

As for the question at hand:

To cut to the chase, how would I brighten two lamps simultaneously over 400 mS -- using a "brighten" method in an object instanced for each lamp?

If you give your lamp class an Update method, which will perform delayed actions such as fading, but could also be used for any delayed action (turn it off after a second for instance), you call Update for each lamp object each time in the loop function. (note: you'd probably let it call the respective method at that time, I'd advise against putting fading logic in the update method) You could either pass the time that has passed since the last Update invocation to the Update method, or give the current time and let Update take care of that too. All that would be left if you have this construction, is to create versions of your functions that accept a 'delay' parameter that lets you specify how long it needs to wait before doing its thing ;)

edit: Mike Murdock mentioned using millis() in the method, you could do this to get the time in the Update method aswell, but I'm not a fan of doing so. Mainly because you'll have no control of the timing in your sketch.. You might experience time-drift, where certain things don't happen synchronised (that the millis() value shifts between lamp objects). This really is something of personal preference, there is no right or wrong regarding this.

Things like "fading" or "dimming" are often performed by other classes.

Would be bad coding practice, other objects have no business meddling around with the properties of the lamp.

A system in which objects are not allowed to interact will be rather boring.

That said, there is an exception

There is more than one exception. I'll leave it to your imagination to figure out the other(s).

So yes, all in all I always love reading comments regarding 'people usually do this' or 'bad coding practice', since they defer from the main topic without adding.. well, usually anything

It isn't your decision to determine if my posts are deferring from the main topic. It isn't your decision to determine if my posts are or are not adding anything. Those decisions lie entirely in rasqual's hands. If rasqual feels I am off topic I will do (and have done) my best to get back on topic. If rasqual feels I am a detriment then I will, without hesitation, bow out of the conversation.