Multichannel linear actuator control - no arduino experience

I was bored earlier and took a quick stab at it.

A very simple one shot can be done in a couple lines of code, no problem. Properly extending that to multiple inputs? I can make it work, but I stopped after about 50 LOC. Gets complex because you have to handle multiple timeouts and triggers without blocking. Not hard, but time consuming. Maybe I’ll finish up if I’m bored tomorrow.

Thanks for the support, guys.

In terms of operating logic, do most arduino codes basically loop continuously looking for flags to take action, or do they process a series of commands in time that could delay the processor from capturing relevant events that also require its action?

I guess I’m curious about the programming philosophy for a real time response system that is receiving multiple inputs and taking numerous actions near simultaneously.

Unlike a PLC that examines the inputs and updates an input image table, solves the logic, then updates the outputs, then repeats over and over, all the micro computers need to be put into a loop to continuously process your code. Of course, you could also use interrupts to execute code, I suppose, although I have never done so.

Google ‘Arduino State machine’ and you’ll get some links to making the micro more like a PLC.

In terms of near simultaneous actions, the micros are often fast enough to process multiple inputs very very quickly, but it depends on your definition of real time.

Karimwassef:
Thanks for the support, guys.

In terms of operating logic, do most arduino codes basically loop continuously looking for flags to take action, or do they process a series of commands in time that could delay the processor from capturing relevant events that also require its action?

I guess I’m curious about the programming philosophy for a real time response system that is receiving multiple inputs and taking numerous actions near simultaneously.

I don’t know much about Arduino common practice but if you need to process inputs while an action is in process (like the example you’re building), there are various techniques to accomplish this. Hard real-time software is an engineering discipline all its own with rigorous analytical methods available to be sure all operations are done on schedule.

The basic method I think you’re asking about is to be sure that your input checks run at least fast enough so the program always knows their state. In this code I accomplish it by not using any blocking calls except the delay(1) at the top of the loop. Code is rather long and untested, but let me know if it works.

/*********************************************************************************************
This reads a set of input pins and activates actuators depending on the last state transition detected
on the inputs.
HIGH->LOW: activate actuator reverse direction for preset time
LOW->HIGH: activate actuator forward direction for preset time

Note that the code assumes the LOW/HIGH signal lasts a longer period than the actuation time. 
Otherwise the actuator will change direction as soon as the signal changes state

**********************************************************************************************/

// Constants
const int NUMBER_OF_CHANNELS = 4;

// Arduino pins used for input
const int _inputs[] = {1, 2, 3, 4};

// Pins for forward output control
const int _forward[] = {5, 6, 7, 8};

// Pins for reverse output control
const int _reverse[] = {9, 10, 11, 12};

// Time intervals for forward motion per channel
const int _forwardTime[] = {1000, 1000, 1000, 1000};

// Time intervals for reverse motion per channel
const int _reverseTime[] = {1500, 1500, 1500, 1500};

// Global state
int _inMotion[NUMBER_OF_CHANNELS];
bool _lastState[NUMBER_OF_CHANNELS];

void setup() 
{
  for (int i=0; i < NUMBER_OF_CHANNELS; i++)
  {
    pinMode(_inputs[i], INPUT_PULLUP);
    pinMode (_forward[i], OUTPUT);
    pinMode (_reverse[i], OUTPUT);
    digitalWrite(_forward[i], LOW);
    digitalWrite(_reverse[i], LOW);
    _lastState[i] = digitalRead(_inputs[i]);
  }
}

void loop() 
{
  bool currentState = LOW;
  int trigger[NUMBER_OF_CHANNELS];
  
  // 1 ms loop interval
  delay(1);

  for (int i=0; i < NUMBER_OF_CHANNELS; i++)
  {
    // Detect an edge
    currentState = digitalRead(_inputs[i]);
    if (digitalRead(currentState != _lastState[i]) )
    {
      // Is it a rising edge?
      if (currentState == HIGH)
      {
        // Go forward
        digitalWrite(_forward[i], HIGH);
        digitalWrite(_reverse[i], LOW);
        // Set forward time
        _inMotion[i] = _forwardTime[i];
      }
      // Falling edge
      else
      {
        // Reverse
        digitalWrite(_forward[i], LOW);
        digitalWrite(_reverse[i], HIGH);
        // Set reverse time
        _inMotion[i] = _reverseTime[i];
      }
    }

    // Update previous state
    _lastState[i] = currentState;

    // Now update motions
    if (_inMotion[i] > 0 )
    {
      // Decrement motion timer
      if ( --_inMotion[i] == 0 )
      {     
        // Timed out. Stop
        digitalWrite(_forward[i], LOW);
        digitalWrite(_reverse[i], LOW);
      }
    } 
  }   
}

Thanks!

My events operate on the order of seconds, so the processor speed should be able to simulate real time response given that I’m tolerant of a delay that’s as large as one second.

My concern is more with code that hangs up the execution due to waits or delays.

I’ll try out the code.

Still traveling so haven’t coded it in yet (Back on Friday), but I walked through the code.

Very simple and clear - thank you !

3 Quick questions:

The forward and reverse coded pulse duration are 1s and 1.5s. Did I read that right?

The time delay is 1ms - that’s to create a 1ms resolution and counter in the loop, but doesn’t the execution time count too or is it just so small compared to the 1ms that it’s negligible?

Does arduino have a global time variable so duration can be calculated by capturing the start event time stamp and calculating the difference to the current time stamp?

Are you ok with me posting the code in an application forum where others who may be trying to do this can have access? I can give you the credit and link back here if you like :slight_smile:

In case you want to see what I have so far… Pre-arduino

[<LINK_TEXT text=“http://i1062.photobucket.com/albums/t49 … giyt1g.jpg”>http://i1062.photobucket.com/albums/t496/karimwassef/B30C0225-3A52-4BFC-A698-4D43FF7175CD_zpsrzgiyt1g.jpg</LINK_TEXT>

That’s the controller and two H bridges (yes, very messy I know).

Here’s the actuator (very DIY)

[<LINK_TEXT text=“http://i1062.photobucket.com/albums/t49 … pxywpr.jpg”>http://i1062.photobucket.com/albums/t496/karimwassef/AE1066FE-A0AE-4D8A-AAE1-F78225184FE3_zpshnpxywpr.jpg</LINK_TEXT>](Photo Storage)](Photo Storage)

What is it?

It’s an actuated surge. There’s 100g container over a coral reef tank and based on the time of day, temperature, and different cycles, it releases 20g through each actuated valve. Two valves can be in sync or out of sync.

This simulates nature much more than pumps do. The result is rapid coral growth. That feeds the local need without resorting to gathering coral from the wild.

I put it together last year and it’s working well, but expanding to 4 channels is prohibitively expensive and limited in scope of returns. An expansion costs $200 and won’t be able to perform other basic activities like I expect arduino can do.

For example, I have one outlet to just create a timer with 5min off and 15sec on. Each outlets costs about $40 to enable.

20g of what, I’m just curious?

Karimwassef:
Still traveling so haven’t coded it in yet (Back on Friday), but I walked through the code.

Very simple and clear - thank you !

Thank you. It takes experience to make it simple and clear :-)

3 Quick questions:

The forward and reverse coded pulse duration are 1s and 1.5s. Did I read that right?

The time delay is 1ms - that’s to create a 1ms resolution and counter in the loop, but doesn’t the execution time count too or is it just so small compared to the 1ms that it’s negligible?

Does arduino have a global time variable so duration can be calculated by capturing the start event time stamp and calculating the difference to the current time stamp?

Are you ok with me posting the code in an application forum where others who may be trying to do this can have access? I can give you the credit and link back here if you like :slight_smile:

Yes, the time durations are in milliseconds. The delay is for the reasons you guessed. There are more precise ways of doing this, but it was a quick one-off and I figured it was good enough for what you described.

Sure, you can post the code if you want to. The only limitation I place on code I post online is I ask that if it’s going to be used as-is for commercial applications, the user contact me for a license. Otherwise, feel free to do with it as you wish!

I couldn’t read the label: what type of actuator is that?

It’s 20 gallons of saltwater. I’ll share a video.

The actuator is EzzyLift

I got it from eBay

http://m.ebay.com/itm/320948568171?_trk … mwBanner=1

[<LINK_TEXT text=“http://i1062.photobucket.com/albums/t49 … 64510f.jpg”>http://i1062.photobucket.com/albums/t496/karimwassef/9b588396-01fa-489f-8048-8935a5fc47fc_zpsab64510f.jpg</LINK_TEXT>

[<LINK_TEXT text=“http://i1062.photobucket.com/albums/t49 … a5344b.jpg”>http://i1062.photobucket.com/albums/t496/karimwassef/s5_zps4fa5344b.jpg</LINK_TEXT>

http://s1062.photobucket.com/user/karim … b.mp4.html

http://s1062.photobucket.com/user/karim … d.mp4.html](Photo Storage)](Photo Storage)

Why did you build a valve instead of using an off the shelf solenoid valve?

There are very few 2" PVC solenoid valves that can survive salt water corrosion. I only found one and it was ~$500 each.

Pool valves work but are very slow and they’re expensive too ~$400 and they need +24V/-24V just like my actuators do (+12V/-12V)

My setup cost ~$80 per valve, most of which was $50 for the linear actuator, which is now $35…

At two valves, it was $160 vs $1000! Now it’s $130 vs $1000 for the next two.

For an example of real-time programming with several inputs and outputs, see this link on the Arduino forum: http://forum.arduino.cc/index.php?topic=223286.0

Also, the Blink without Delay example that comes with the Arduino programming environment illustrates how to control devices without waits.

You can make a pinch valve pretty cheap from a section of bicycle inner tube and a solenoid, in case you ever want to try a lower cost version :slight_smile:

Can’t use rubber with salt water. It leaches into the water and kills the reef. I’m open to new ideas though.

By the way, I’m well into the programming now & trying things out. You’ve put me on the right track. I’ll update when it’s running or if I crash again.