Pins - On/Off

Hi - I'm trying to write a program that turns a switch on and off (one connected to an air compressor, another to a vacuum) from the serial port. I am able to turn the vacuum on, but not off, even if i first turn on, allow for a delay and turn off.

My code is below:

const byte air = 9; //z-axis const byte vac = 10; //vacuum void setup() { // initialize digital pin 12 as an output. // initialize digital pin 13 as an output. pinMode(air, OUTPUT); pinMode(vac, OUTPUT);

Serial.begin(115200);

}

void loop() { char x= Serial.read();

while (x == 'a' || x == 'b') { if (x == 'a') { zMotionON(); suctionON(); } if (x == 'b') { zMotionOFF(); suctionOFF(); } } }

void zMotionON() { digitalWrite(air, HIGH); // extend the air cylinder delay(3000); // wait for a second }

void suctionON() { digitalWrite(vac, HIGH); // Open up vacuum line to manifold delay(3000); // wait for a second }

void zMotionOFF() { digitalWrite(air, LOW); // retract the air cylinder delay(3000); // wait for a second }

void suctionOFF() { digitalWrite(vac, HIGH); // Open up vacuum line to manifold delay(1000); // wait for a second digitalWrite(vac, LOW); // Shut off vacuum line to manifold delay(3000); // wait for a second }

Tell us how you get out of the while loop.

When things don't work as expected, start putting Serial.println() statements in. Also, the if statements in loop() could be written more efficiently. Try:

const byte air = 9; //z-axis
const byte vac = 10; //vacuum
void setup()
{
  // initialize digital pin 12 as an output.
  // initialize digital pin 13 as an output.
  pinMode(air, OUTPUT);
  pinMode(vac, OUTPUT);

  Serial.begin(115200);
}


void loop()
{
  if (Serial.available() > 0) {
    char x = tolower(Serial.read());

    switch (x) {
      case 'a':
        zMotionON();
        suctionON();
        break;
      
      case 'b':
        zMotionOFF();
        suctionOFF();
        break;
        
      default:
        Serial.println("Not valid option");
        break;
    }
  }
}

  void zMotionON()
  {
    Serial.println("In zMo ON");

    digitalWrite(air, HIGH);   // extend the air cylinder
    delay(500);              // wait for a second
  }

  void suctionON()
  {
    Serial.println("In suction ON");
    digitalWrite(vac, HIGH);   // Open up vacuum line to manifold
    delay(500);              // wait for a second
  }

  void zMotionOFF()
  {
    Serial.println("In zMo OFF");
    digitalWrite(air, LOW);    // retract the air cylinder
    delay(500);              // wait for a second
  }

  void suctionOFF()
  {
    Serial.println("In suction OFF");
    digitalWrite(vac, HIGH);   // Open up vacuum line to manifold
    delay(1000);              // wait for a second
    digitalWrite(vac, LOW);    // Shut off vacuum line to manifold
    delay(500);              // wait for a second
  }

The call to tolower() means even a cap letter works. This assumes the monitor is set up with no line ending.

I don think this is efficient way… But…
replace

 char x= Serial.read(); 
 
 while (x == 'a' || x == 'b')

with

 while (char x = Serial.read() == 'a' || 'b')

There's a few points I'd make. Firstly, your use of while loops is inappropriate. Secondly, you're not checking if any serial is available before you attempt to read it.

I've tidied it up a bit, but obviously this is untested.

const byte air = 9; //z-axis
const byte vac = 10; //vacuum
void setup()
{
  // initialize digital pin 12 as an output.
  // initialize digital pin 13 as an output.
  pinMode(air, OUTPUT);
  pinMode(vac, OUTPUT);

Serial.begin(115200);

}


void loop()
{
if (Serial.available())
  {
  char x= Serial.read();
   switch(x)
     {
      case 'a':
      case 'A':
          zMotionON();
          suctionON();
          break;
          
      case 'b':
      case 'B':
          zMotionOFF();
          suctionOFF();
          break;
     }
   }

}

void zMotionON()
{
  digitalWrite(air, HIGH);   // extend the air cylinder
  delay(3000);              // wait for a second   
}

void suctionON()
{
  digitalWrite(vac, HIGH);   // Open up vacuum line to manifold
  delay(3000);              // wait for a second
}

void zMotionOFF()
{
  digitalWrite(air, LOW);    // retract the air cylinder
  delay(3000);              // wait for a second
}

void suctionOFF()
{
  digitalWrite(vac, HIGH);   // Open up vacuum line to manifold
  delay(1000);              // wait for a second
  digitalWrite(vac, LOW);    // Shut off vacuum line to manifold
  delay(3000);              // wait for a second
}

KenF: I'm curious why you prefer the "double case" conditions to simply using either toupper() or tolower() after the Serial.read() method and a single case for each expression. Otherwise, our code is very similar.

anilkunchalaece: I don think this is efficient way... But... replace

 char x= Serial.read(); 

while (x == 'a' || x == 'b')



with


while (char x = Serial.read() == 'a' || 'b') ```

'a' || 'b' is always true (aka 1) , but Serial.read() is unlikely to return 1, so I don't think that will work.

Very simple serial test code for turning a pin on and off.

// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later

//A very simple example of sending a string of characters 
//from the serial monitor, capturing the individual 
//characters into a String, then evaluating the contents 
//of the String to possibly perform an action (on/off board LED).

int ledPin = 13;
String readString;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); 
  Serial.println("serial on/off test 0021"); // so I can keep track
}

void loop() {

  while (Serial.available()) {
    delay(3);  
    char c = Serial.read();
    readString += c; 
  }

  if (readString.length() >0) {
    Serial.println(readString);

    if(readString.indexOf("on") >=0)
    {
      digitalWrite(ledPin, HIGH);
    }

    if(readString.indexOf("off") >=0)
    {
      digitalWrite(ledPin, LOW);
    }

    readString="";
  } 
}