Go Down

Topic: Reversing digital read. Using SML (Read 1 time) previous topic - next topic

Hexarx

Hello, I'm very new to programming and have been doing a project with arduino for a while, it's a timer game which involves 4 leds and 5 buttons. Kinda like whack a mole. Anyway I finished the coding with the help of another guy and the wiring designed by myself only to find that the coding/wiring is reversed ex. I have to hold all 5 buttons for the coding to declare all buttons are off before the game starts. I'm having a hard time fixing this, a guy told me to put a !(not) before every digital read but I don't understand how to do it as I get errors when doing it. If anyway who can help me fix or reverse the coding or wiring I would be greatly appreciated!
I'v put the fritzing jpg as an attachment.


Code: [Select]

#include <SM.h>
SM game(gameStart);
const int noControls = 4;
const byte led[noControls] = {9, 10, 11, 12};
const byte btn[noControls] = {2, 3, 5, 7};//pin 0 and 1 are for serial
const byte startBtn = 6;
const unsigned long limit = 120;//reaction time limit
byte currentCtrl;
enum btnState {noPress, correct, fault};

void setup(){
  Serial.begin(115200);
  for(byte i = 0; i<noControls; i++) pinMode(led[i], OUTPUT);
  randomSeed(analogRead(0));
}//setup()

void loop(){
  EXEC(game);
}//loop()

State gameStart(){
  if (not)(digitalRead(startBtn)){
    currentCtrl = random(noControls);//determine control number
    ledCtrl(1<<currentCtrl);//light correct led
    Serial.print("Started with:");
    Serial.println(currentCtrl);
    game.Set(randomLed);//change state
  }//if(stertBtn)
  for(byte i = 0; i<noControls; i++) if(digitalRead(btn[i])){//check if user cheats
    ledCtrl(15);//all leds on
    Serial.println("Cheat!");
    game.Set(miss);//change state
    break;//no need to check further
  }//if(cheat)
}//gameStart()

State randomLed(){
//  if(game.Timeout(limit)){//check for Timeout
//    ledCtrl(15);//all leds on
//    Serial.println("Timeout");
//    game.Set(miss);//change state
//  }//if(Timeout)
  btnState pressed = noPress;
  for(byte i = 0; i<noControls; i++){//scan all buttons
    if(digitalRead(btn[i])){//check individual button
      if(i == currentCtrl){//check validity of btn
        pressed = correct;//we have a hit
      }else{//incorrect btn
        pressed = fault;//false press
        break;//abort scan
      }//()
    }//if(btn[i])
  }//for(i)
  switch(pressed){//act on press
    case correct:
      currentCtrl = 1;//reuse currentCtrl for display
      ledCtrl(currentCtrl);
      Serial.println("Hit");
      game.Set(success);//change state
      break;//case correct
    case fault:
      ledCtrl(15);//all leds on
      Serial.println("Wrong button");
      game.Set(miss);//change state
      break;//case fault
  }//switch(pressed)
}//randomLed()

State miss(){
  if(game.Timeout(1000)){
    ledCtrl(0);//all leds off
    Serial.println("Back to start from miss");
    game.Set(gameStart);
  }//()
}//miss()

State success(){
  if(game.Timeout(300)){//wait 300ms
    currentCtrl <<= 1;//shift 1 bit
      if(currentCtrl<(1<<noControls)){//more ledsd to show?
        ledCtrl(currentCtrl);
        game.Set(success);
      }else{//back to start
        ledCtrl(0);//all leds off
        Serial.println("back to start from success");
        game.Set(gameStart);//change state
      }
  }//if(wait 300 ms)()
}//success()

inline void ledCtrl(byte ctrl){
  for(byte i = 0; i<noControls; i++) digitalWrite(led[i], !!(ctrl&(1<<i)));
}//ledCtrl()


Delta_G

Well, there are two ways a button can work.  It can read HIGH when it is not pressed and LOW when it is, or it can work the opposite.  The way you have the buttons wired up they are LOW all the time and go HIGH when they are pressed. 

The easiest thing to do would be to go through the code and invert the logic.  So:

Code: [Select]

if(digitalRead(somePin)){


becomes:

Code: [Select]

if(!digitalRead(somePin)){


where the ! means NOT. 

But that solution requires that you know at least some of the basics of programming and how this program works.  And looking at your solution that may not really be the case.  So there is another solution.  You can just make the switches you have match the program.  Turn your switches into active LOW switches. 

Right now you have the switches wired up where one side goes to +5V and the other goes to the pin and through a resistor to ground.  Reverse that so that one side of the switch goes directly to ground and the other side goes to the pin and through a resistor to +5V.  Now your switches will read LOW when they are pressed.
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

Go Up