Switching between 4 digital output states. How to?

Trying to apply logic output to digital pins 9 & 10. This is for control of MS1 & 2 lines of an easydriver board.

On a user keypress, I want the outputs to be as follows:

Key not pressed, initial state is 00 (LOW PIN 9, LOW PIN 10)
1st keypress, change op to 01 (LOW PIN 9, HIGH PIN 10)
2nd 10 (HIGH PIN 9, LOW PIN 10)
3rd 11 (HIGH PIN 9, HIGH PIN 10
4th loop back to initial state 00

Assigning these different states to the digital pins within a loop is the best way to approach?

9 & 10 = LOW
if keypress detected
if 9&&10 = 0 then change 01
else if
9<10 then change to 10
else
if 9>10 then change to 11

Hope that makes sense, where do I begin?

You'll notice that your outputs are simply a binary count of the number of keypresses. (if I understand your spec correctly)
Just count the number of presses, and output that value on your output pins.

AWOL:
You'll notice that your outputs are simply a binary count of the number of keypresses. (if I understand your spec correctly)
Just count the number of presses, and output that value on your output pins.

I'll take a look at that. Thanks AWOL!

http://arduino.cc/en/Reference/BitRead
May be useful

negativ3:
if 9&&10 = 0 then change 01

To check for equality, use ==. You want to get in that habit when coding.

...or at least put the literal constant on the left hand side of a comparison, so even if you do accidentally drop an "=", the compiler will tell you.
e.g.if (3 = myState) will generate an error.

Ok, got this working using if statements but am very interested in bitRead. It sounds more economical. Care to share a bit more on how it works?

const int PRESSPin = 5;
const int MS1Pin = 9;
const int MS2Pin = 10;
int state = 0;
int lastState = 0;
int buttonCounter = 0;

void setup()
{
  //Start serial comms
  Serial.begin(57600);
  
  pinMode(MS1Pin, OUTPUT);
  pinMode(MS2Pin, OUTPUT);
  pinMode(PRESSPin, INPUT);
  digitalWrite(PRESSPin, HIGH);
}
void loop()
{
  state = digitalRead(PRESSPin);
  if(state != lastState) {
    if (state == LOW) {
      buttonCounter++;
    }
    lastState = state;
}
    {
    if (buttonCounter == 0)
    {
      digitalWrite(MS1Pin, LOW);
      digitalWrite(MS2Pin, LOW);
      delay(100);
      Serial.print(buttonCounter);
    }
    if (buttonCounter == 1)
    {
      digitalWrite(MS1Pin, LOW);
      digitalWrite(MS2Pin, HIGH);
      delay(100);
      Serial.print(buttonCounter);
    }
    if (buttonCounter == 2)
    {
      digitalWrite(MS1Pin, HIGH);
      digitalWrite(MS2Pin, LOW);
      delay(100);
      Serial.print(buttonCounter);
    }
    if (buttonCounter == 3)
    {
      digitalWrite(MS1Pin, HIGH);
      digitalWrite(MS2Pin, HIGH);
      delay(100);
      Serial.print(buttonCounter);
    }
    if(buttonCounter >= 4)
    buttonCounter = 0;
    delay(20);
  }
}

You only need to change the output when the input changes not every time round to loop.
Even better than bit read is the & operation bitwise AND, it's like bitRead for grown ups.

const int PRESSPin = 5;
const int MS1Pin = 9;
const int MS2Pin = 10;
int state = 0;
int lastState = 0;
int buttonCounter = 0;

void setup()
{
  //Start serial comms
  Serial.begin(57600);
  
  pinMode(MS1Pin, OUTPUT);
  pinMode(MS2Pin, OUTPUT);
  pinMode(PRESSPin, INPUT);
  digitalWrite(PRESSPin, HIGH);
}
void loop()
{
  state = digitalRead(PRESSPin);
  if(state != lastState) {
    if (state == LOW) {
      buttonCounter++;
    }
    lastState = state;
    if(buttonCounter >= 4)
    buttonCounter = 0;
    delay(20);
    // do the output bit only when something changes
    if(buttonCounter & 1) digitalWrite(MS1Pin, HIGH); else digitalWrite(MS1Pin, LOW);
    if(buttonCounter & 2) digitalWrite(MS2Pin, HIGH); else digitalWrite(MS2Pin, LOW);
    }
}
    if (buttonCounter == 0)
    {
      digitalWrite(MS1Pin, LOW);
      digitalWrite(MS2Pin, LOW);
      delay(100);
      Serial.print(buttonCounter);
    }
    if (buttonCounter == 1)
    {

Is there some value for buttonCounter that would trigger more than one if block to be executed? If not.

if(buttonCounter == 0)
{
}
else if(buttonCounter == 1)
{
}
else if(buttonCounter == 2)
{
}
// etc

would be better. Or a switch statement.

You set MS1Pin LOW when buttonCounter is less than 2. Otherwise, you set it HIGH.
You set MS2Pin LOW when buttonCounter is even. Otherwise, you set it HIGH.

Seems like you could use this pattern to replace a lot of code.

  if(buttonCounter < 2)
     digitalWrite(MS1Pin, LOW);
  else
     digitalWrite(MS1Pin, HIGH);
  if(buttonCounter % 2 == 0)
     digitalWrite(MS2Pin, LOW);
  else
     digitalWrite(MS2Pin, HIGH);
  delay(100);
  Serial.print(buttonCounter);

Altered to use switch/case and Auto-formatted (under Tools in the Arduino IDE)

const int PRESSPin = 5;
const int MS1Pin = 9;
const int MS2Pin = 10;
int state = 0;
int lastState = 0;
int buttonCounter = 0;

void setup()
{
  //Start serial comms
  Serial.begin(57600);

  pinMode(MS1Pin, OUTPUT);
  pinMode(MS2Pin, OUTPUT);
  pinMode(PRESSPin, INPUT);
  digitalWrite(PRESSPin, HIGH);
}

void loop()
{
  state = digitalRead(PRESSPin);
  if(state != lastState) {
    if (state == LOW) {
      buttonCounter++;
    }
    lastState = state;
  }
  switch (buttonCounter)
  {
  case 0 : 

    digitalWrite(MS1Pin, LOW);
    digitalWrite(MS2Pin, LOW);
    delay(100);
    Serial.print(buttonCounter);
    break;

  case 1 : 

    digitalWrite(MS1Pin, LOW);
    digitalWrite(MS2Pin, HIGH);
    delay(100);
    Serial.print(buttonCounter);
    break;

  case 2 : 

    digitalWrite(MS1Pin, HIGH);
    digitalWrite(MS2Pin, LOW);
    delay(100);
    Serial.print(buttonCounter);
    break;

  case 3 :

    digitalWrite(MS1Pin, HIGH);
    digitalWrite(MS2Pin, HIGH);
    delay(100);
    Serial.print(buttonCounter);
    break;

  default : // (buttonCounter >= 4)
    buttonCounter = 0;
  }
  delay(20);
}

I'd use the 'mod' (%) operator to wrap the counter, and bitwise and (&) to test which bits are set. If there were more than two bits I'd be inclined to process them in a loop, but for two I'd just put two copies of the code with the bit mask values hard coded. You could either use the ternary operator to output HIGH or LOW depending on the bit value, or break it out into if-then-else expressions.

counter = (counter + 1) % 4;

digitalWrite(MS1Pin, ((counter & 1) > 0)?HIGH:LOW);
digitalWrite(MS2Pin, ((counter & 2) > 0)?HIGH:LOW);

Why not use
counter = (counter + 1) & 3;
in place of
counter = (counter + 1) % 4;
It is more computationally efficient.

Thanks guys,

Now including a display routine per output "state"...

//Include the displayshield Library
#include <displayshield4d.h>
DisplayShield4d oled;

//Define pin assignments
const int LEFTPin = 3;
const int MS1Pin = 9;
const int MS2Pin = 10;
int msState = 0;
int lastState = 0;
int buttonCounter = 0;

//Define timer variables
long startTime; //Value returned from millis when menuFunction called
long duration; //Variable to store the duration [long duration - millis]
long timeout = 2000; //2 second delay before display blanks

void setup() {
  
  //Start serial comms
  Serial.begin(57600);
  
  //Initialise uLCD
  oled.Init();
  
  pinMode(MS1Pin, OUTPUT);
  pinMode(MS2Pin, OUTPUT);
  pinMode(LEFTPin, INPUT);
  digitalWrite(LEFTPin, HIGH); }

void menuFunction(char *text) {
  startTime = millis();
  oled.rectangle(0, 0, 128, 128, OLED_SOLID, oled.RGB(0, 0, 0));
  oled.setfont(OLED_FONT5x7);
  oled.setfontmode(OLED_FONT_OPAQUE);
  oled.drawstringblock(5, 5, 0, oled.RGB(255, 255, 0), 4, 4, text); }

void  blankFunction() {
    oled.Clear();}
  
void loop() {
  
   //Calculate delay since calling menuFunction
  long duration = millis() - startTime;
  
  msState = digitalRead(LEFTPin);
  if(msState != lastState) {
    if (msState == LOW) {
      buttonCounter++; }
    lastState = msState; }
    
    if (buttonCounter == 0) {
      digitalWrite(MS1Pin, LOW);
      digitalWrite(MS2Pin, LOW);
      delay(100);
      Serial.print(buttonCounter);
      menuFunction("00"); }
      
    if (buttonCounter == 1) {
      digitalWrite(MS1Pin, LOW);
      digitalWrite(MS2Pin, HIGH);
      delay(100);
      Serial.print(buttonCounter);
      menuFunction("01"); }
      
    if (buttonCounter == 2) {
      digitalWrite(MS1Pin, HIGH);
      digitalWrite(MS2Pin, LOW);
      delay(100);
      Serial.print(buttonCounter);
      menuFunction("10"); }
      
    if (buttonCounter == 3) {
      digitalWrite(MS1Pin, HIGH);
      digitalWrite(MS2Pin, HIGH);
      delay(100);
      Serial.print(buttonCounter);
      menuFunction("11"); }
    
    if(buttonCounter >= 4) {
    buttonCounter = 0;
    delay(20); }
    
    if (duration >= timeout) {
      blankFunction(); }
    }

I will start using the compiler autoformat feature.

Can you explain how these two lines decode the buttoncounter? I'm not seeing what the "&" is doing.

if(buttonCounter & 1) digitalWrite(MS1Pin, HIGH); else digitalWrite(MS1Pin, LOW);
    if(buttonCounter & 2) digitalWrite(MS2Pin, HIGH); else digitalWrite(MS2Pin, LOW);

Thanks

The AND operator isolates the individual bits

I'm not seeing what the "&" is doing.

You should look or learn to look. If you take the time then your eyes may open up and let ideas into your head.

The bitwise operations let you evaluate whole sets of conditions in no time flat. But you have to realize that you can do it before it makes sense to pack TRUE/FALSE (or ON/OFF, HIGH/LOW, etc) conditions as 1's and 0's into bytes (or unsigned or even signed ints) in the first place, else it's all Mumbo-Jumbo!

I've used video chips in PC's to evaluate whole blocks of bit conditions -really- fast back when CPU's were nothing compared to now. It's the same as with bytes and ints except many x many x many in one swoop. My eyes and mind were really open back then.

GoForSmoke:

I'm not seeing what the "&" is doing.

You should look or learn to look. If you take the time then your eyes may open up and let ideas into your head.

& - Arduino Reference

The bitwise operations let you evaluate whole sets of conditions in no time flat. But you have to realize that you can do it before it makes sense to pack TRUE/FALSE (or ON/OFF, HIGH/LOW, etc) conditions as 1's and 0's into bytes (or unsigned or even signed ints) in the first place, else it's all Mumbo-Jumbo!

I've used video chips in PC's to evaluate whole blocks of bit conditions -really- fast back when CPU's were nothing compared to now. It's the same as with bytes and ints except many x many x many in one swoop. My eyes and mind were really open back then.

Now knowing & = BitwiseAnd is a great help. Thanks for the pointer.

Now knowing & = BitwiseAnd is a great help

I told you that in reply #7 !

This may be helpful in understanding what the bitwise AND does (as well as all the other bitwise operators): Arduino Playground - BitMath