using arduino to control a group of pneumatic solenoids

Hey all,

First time posting, and I am admittedly, new to Arduino and coding. I am trying to control a series of relays that will fire solenoids to open blast gates in our woodworking shop. I would like the Arduino to recongnize when a tool has been turned on, then signal the correct blast gates to open. I think i understand the electronics of this, but the coding is tripping me up. I have a 5v power supply that I can get the Arduino to digitalRead, and I can get the output pin to write, but the IF/ELSE statement does not appear to work correctly in my code to have the first cause the second. Could you take a look and let me know if you see what I am missing?

int solA = 1;
int solB = 2;
int solC = 3;
int solD = 4;
int solE = 5;
int senA = 6;
int senB = 7;
int senC = 8;
int senD = 9;
int senE = 10;

void setup() {
  
    pinMode(solA, OUTPUT);
    pinMode(solB, OUTPUT);
    pinMode(solC, OUTPUT);
    pinMode(solD, OUTPUT);
    pinMode(solE, OUTPUT);
    pinMode(senA, INPUT);
    pinMode(senB, INPUT);
    pinMode(senC, INPUT);
    pinMode(senD, INPUT);
    pinMode(senE, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
int val =  digitalRead(senB);
  if(senB == HIGH){
  digitalWrite(solB, HIGH);
  }else{
  digitalWrite(solB, LOW);
}
}

You’re almost there. Have a look at this:

#define NUM_SOLENOIDS   5

const int solA = 1;
const int solB = 2;
const int solC = 3;
const int solD = 4;
const int solE = 5;
//
const int senA = 6;
const int senB = 7;
const int senC = 8;
const int senD = 9;
const int senE = 10;

int grSolenoids[] = 
    {
        solA,
        solB,
        solC,
        solD,
        solE    
    };
    
int grSensors[] = 
    {
        senA,
        senB,
        senC,
        senD,
        senE    
    };


void setup() 
{
    for( int i=0; i<NUM_SOLENOIDS; i++ )
    {
        pinMode( grSolenoids[i], OUTPUT );
        pinMode( grSensors[i], INPUT_PULLUP ); 
        
    }//for
  
}//setup

void loop() 
{
    for( int i=0; i<NUM_SOLENOIDS; i++ )
    {
        if( digitalRead( grSensors[i] ) == HIGH )
            digitalWrite( grSolenoids[i], HIGH );
        else
            digitalWrite( grSolenoids[i], LOW );
            
    }//for
    
}//loop

It just takes your code and cleans it up a bit and takes advantage of arrays to simplify things and reduce the amount of repetition.

If this works, you might then want to think about how it actually operates. The microcontroller repeats the loop() code thousands time times a second. There’s no need to update the state of the sensors and solenoids at that rate/

This modified version (should) update the sensors/solenoids once every 75mS; even that may be unreasonably rapid. You can change it to whatever you want:

#define NUM_SOLENOIDS   5

const int solA = 1;
const int solB = 2;
const int solC = 3;
const int solD = 4;
const int solE = 5;
//
const int senA = 6;
const int senB = 7;
const int senC = 8;
const int senD = 9;
const int senE = 10;

int grSolenoids[] = 
    {
        solA,
        solB,
        solC,
        solD,
        solE    
    };
    
int grSensors[] = 
    {
        senA,
        senB,
        senC,
        senD,
        senE    
    };

int
    currSensorStates[NUM_SOLENOIDS],
    lastSensorStates[NUM_SOLENOIDS];

void setup() 
{
    for( int i=0; i<NUM_SOLENOIDS; i++ )
    {
        pinMode( grSolenoids[i], OUTPUT );
        pinMode( grSensors[i], INPUT_PULLUP ); 
        
        //get a copy of the sensors "initial states"
        lastSensorStates[i] = digitalRead( grSensors[i] );  
    
    }//for
      
}//setup

int ReadSensors( void )
{
    static unsigned long
        timeSensors = 0;
    unsigned long
        timeNow;

    //update the sensors/solenoids once every 75mS (e.g.)
    //get the systemmilliseconds count
    timeNow = millis();
    //if that count minus the previous time is less than 75(milliseconds), 
    //not enough time has passed yet so just return
    //time has passed for 
    if( (timeNow - timeSensors) < 75 )
        return;
    //time for a new update; save this time for the next update
    timeSensors = timeNow;

    //run through the array of sensors and check them
    for( int i=0; i<NUM_SOLENOIDS; i++ )
    {
        //read the current state of the sensor
        currSensorStates[i] = digitalRead( grSensors[i] );
        
        //is the state different than the last time checked?
        if( currSensorStates[i] != lastSensorStates[i] )
        {
            //yes; apply the change to the solenoid
            if( currSensorStates[i] == HIGH )
                digitalWrite( grSolenoids[i], HIGH );
            else
                digitalWrite( grSolenoids[i], LOW );
                
        }//if
        
        //record the current reading into the "last" register for the next time through
        lastSensorStates[i] = currSensorStates[i];
        
    }//for
    
}//ReadSensors

void loop() 
{
    //just call this repeatedly; when it's time, ReadSensors will update the
    //solenoids
    ReadSensors();
        
}//loop

If you want to add time to the solenoid you’ll need to get a bit more complicated with a so-called “state machine.”

crh2454:
I think i understand the electronics of this

Posting a schematic won't hurt, though.

OP you need to understand input pins and resistors to steer the pin to a known value when it's not being signaled by the monitored plant. (Maybe you do understand them, but you didn't mention it; forgive me if I'm covering stuff you do know.) Reason I raise this is that Blackfin has changed your pinMode()s from your INPUT to his INPUT_PULLUP, without asking if you have any resistors as pulldowns or pullups already.

Bit of a leap of faith there, @Blackfin: it's unknown if the OP has external pullups or pulldowns or none, at this stage.

Your (OP's) use of simple "INPUT" requires either an external pullup from the pin to 5V (and your pin is pulled low by the thing you're monitoring) or an external pulldown from the pin to ground (and your pin is pulled high by the thing you're monitoring).

Blackfin's "INPUT_PULLUP" approach switches on the Arduino's internal pullup resistors which holds your pin high, and you must arrange that the device you're monitoring takes that pin low.

OP's code says:

pinMode(senA, INPUT);

Blackfin's:

pinMode( grSensors[i], INPUT_PULLUP );

arduin_ologist:
Posting a schematic won't hurt, though.

...

Bit of a leap of faith there, @Blackfin: it's unknown if the OP has external pullups or pulldowns or none, at this stage.

Your (OP's) use of simple "INPUT" requires either an external pullup from the pin to 5V (and your pin is pulled low by the thing you're monitoring) or an external pulldown from the pin to ground (and your pin is pulled high by the thing you're monitoring).

Blackfin's "INPUT_PULLUP" approach switches on the Arduino's internal pullup resistors which holds your pin high, and you must arrange that the device you're monitoring takes that pin low.

OP's code says:

pinMode(senA, INPUT);

Blackfin's:

pinMode( grSensors[i], INPUT_PULLUP );

Tis true. There are a few possible configurations here:

If the sensor has a push-pull drive, the internal pull won't matter.
If the sensor has an open-drain/collector output the pull-up won't hurt if he already has one and is needed if he doesn't.
If he has a pull-down on that pin the internal resistor will mess him up as it will form a resistor divider with his PD leaving the logic level a the pin in doubt.

Perhaps I should have left well-enough alone. :confused:

At least it's easy to change.

Blackfin:
Perhaps I should have left well-enough alone

Yes, that was pretty much my point.

(Or at least asked and / or explained.)

BTW @OP, you can read all about pins' behaviour here.

Which Arduino, what are you sensing, what kind of sensor?

Blackfin:
You’re almost there. Have a look at this:

#define NUM_SOLENOIDS   5

const int solA = 1;
const int solB = 2;
const int solC = 3;
const int solD = 4;
const int solE = 5;
//
const int senA = 6;
const int senB = 7;
const int senC = 8;
const int senD = 9;
const int senE = 10;

int grSolenoids =
   {
       solA,
       solB,
       solC,
       solD,
       solE    
   };
   
int grSensors =
   {
       senA,
       senB,
       senC,
       senD,
       senE    
   };

void setup()
{
   for( int i=0; i<NUM_SOLENOIDS; i++ )
   {
       pinMode( grSolenoids[i], OUTPUT );
       pinMode( grSensors[i], INPUT_PULLUP );
       
   }//for
 
}//setup

void loop()
{
   for( int i=0; i<NUM_SOLENOIDS; i++ )
   {
       if( digitalRead( grSensors[i] ) == HIGH )
           digitalWrite( grSolenoids[i], HIGH );
       else
           digitalWrite( grSolenoids[i], LOW );
           
   }//for
   
}//loop




It just takes your code and cleans it up a bit and takes advantage of arrays to simplify things and reduce the amount of repetition.[snip]

You can get rid of the entire IF statement, and do it like this:

digitalWrite( grSolenoids[i], digitalRead( grSensors[i] ) );

This will write the status of the input directly to the corresponding output.
Should you need to invert the state, you can even do

digitalWrite( grSolenoids[i], !digitalRead( grSensors[i] ) );

GalFisk:
You can get rid of the entire IF statement, and do it like this:

digitalWrite( grSolenoids[i], digitalRead( grSensors[i] ) );

This will write the status of the input directly to the corresponding output.
Should you need to invert the state, you can even do

digitalWrite( grSolenoids[i], !digitalRead( grSensors[i] ) );

Good point. I get in guff from some people when I take shortcut tho, but there's no reason you couldn't compact source like this.

Blackfin:
I get in guff from some people when I take shortcut tho,

And quite rightly imo: if you do go for a fancy idea that saves a few lines, at least put a meaningful comment in, or take the long road with a comment saying it could be shortened. Nobody will think any worse of you along the lines of Haha Blackfin's a pillock for not combing those three lines into one.

Always remember your audience: often the nature of the question, and / or the OP's nickname iAmATotalNewbAtThisArduinoStuffSoGoEasyOnMePleasePeeps indicates a response should be simple in the sense of understandable, although it might lose brownie points for not being cutting edge state of the art fancy shmancy Oscar winning clever code.

arduin_ologist:
Always remember your audience: often the nature of the question, and / or the OP's nickname iAmATotalNewbAtThisArduinoStuffSoGoEasyOnMePleasePeeps indicates a response should be simple in the sense of understandable, although it might lose brownie points for not being cutting edge state of the art fancy shmancy Oscar winning clever code.

That should equally apply to those that jump all over noobs for not knowing anything, having bad form getting syntax wrong etc. I'm comfortable putting out a piece of code from which the individual can learn -- even if he has to ask or has to google it -- than just throwing out an insult like so many others here do.

I'm fine with my style but thanks for the suggestion.

Blackfin:
That should equally apply to those that jump all over noobs for not knowing anything

Not going to argue with you on that, that's for sure.

You only have to read many of PaulS's posts to see how to get to almost 100k without actually giving any help.