0

I am developing a project for my college.

PROJECT OUTLINE: There are 3 sensors (Temp., Accelerometer & Humidity) will read the respective parameters continuously. in between if I press 'PushButton1' for 2 seconds the Arduino must enter into programming mode.

The programming mode has 6 Switch cases. Each case gets selected one after one on the even of 'PushButton1' gets pressed for short time.

Also if I press 'PushButton1' again for 2 seconds in Programming mode the Arduino should come out of the programming mode.

PROBLEM: In my current sketch I have to press 'PushButton1' for 2 seconds in Programming Mode for 2 seconds to change the case. Also I don't understand how to get out of the Switch Case loop.

The sketch is attached with this topic.

const int btn = 2;     
const int ledPin =  13;     
int selector = 0;
boolean  volatile wait = false;
const unsigned long event=2000;
unsigned long a=0;
unsigned long b=0;
unsigned long c=0;
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(btn, INPUT);
attachInterrupt(digitalPinToInterrupt(btn),decoder,CHANGE);
}

void loop()
{
  while(wait) {  }
  if (digitalRead(btn) == LOW) {
    a = millis();
  }
  else
  {
    b = millis();
    c=b-a;
    Serial.println(c);
        if (c>=event)
            {
              doSwitchStatement();
              selector++;
              if (selector >6)
                  {
                  selector = 0;
                  delay(500);
                  }
            }
  }
  wait = true;
  interrupts();

}

void decoder()
{
  noInterrupts();
  wait = false;
}

void doSwitchStatement()
{
  switch(selector)
  {
  case 0:
    Serial.println("Case 0");
    break;

  case 1:
    Serial.println("Case 1");
    break;

  case 2:
   Serial.println("Case 2");
    break;

  case 3:
   Serial.println("Case 3");
     break;

  case 4:
   Serial.println("Case 4");
    break;

  case 5:
  Serial.println("Case 5");
    break; 

  case 6:
  Serial.println("Case 6");
    break;

  }
}
2
  • Using a blocking while statement on your loop and an interrupt is an ugly way to accomplish what you are trying to do. Your implementation will freeze the app in that while(wait) loop except when the button state changes, meaning you can't do anything else but respond to button state changes. – Duncan C Apr 27 '20 at 14:44
  • Where is your code to read and display the sensor values? – Duncan C Apr 27 '20 at 14:46
0

I would do it as a simple state without the blocking while define two bools

bool buttonPress = false;
bool inMenu = false;

and add it to the loop.
To differentiate between different press lengths you need to define them. There is nothing like an "automatic" short press recognition. Also use variables which are "speaking" making it easier to read code for others.

const unsigned long buttonPressLong = 2000;  // 2 seconds
const unsigned long buttonPressShort = 250;  // 0.25 secondis feasable
const unsigned long buttonPressDebounce = 50;  
// debouncing for too short presse Thanks Edgar Bonet
unsigned long buttonPressStart = 0;

The program below does what you want (tested on my uno test lab).
As Edgar Bonet commented before you should also debounce the button (look it up in WiKi) to exclude unwanted effects The times I use are practical on my hardware, so you could play around by looking at the serial monitor.

const int btn = 2;
const int ledPin =  13;
int selector = 0;
const unsigned long buttonPressLong = 2000;  // 2 seconds
const unsigned long buttonPressShort = 250;  // 0.25 secondis feasable
const unsigned long buttonPressDebounce = 50;  // debouncing for too short presse Thanks Edgar Bonet
unsigned long buttonPressStart = 0;

bool buttonPress = false;
bool inMenu = false;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(btn, INPUT);
  }

void loop() {
  if (digitalRead(btn) == LOW && !buttonPress ) {
    buttonPressStart = millis();
    buttonPress = true;
  }
  // The routine is only triggered if a previous pressing took place, otherwise it's ignored
  else if (digitalRead(btn) == HIGH && buttonPress) {
    if (millis() - buttonPressStart > buttonPressLong && millis() - buttonPressStart > buttonPressDebounce && inMenu) {
      Serial.print("Long press: ");
      Serial.println(millis() - buttonPressStart);
      buttonPress = false;
      inMenu = false;
    }
    if (millis() - buttonPressStart < buttonPressShort && millis() - buttonPressStart > buttonPressDebounce && !inMenu) {
      Serial.print("First short press ");
      inMenu = true;
    }
    if (millis() - buttonPressStart < buttonPressShort && millis() - buttonPressStart > buttonPressDebounce && inMenu) {
      Serial.print("Short press: ");
      Serial.println(millis() - buttonPressStart);
      doSwitchStatement();
      selector++;
      if (selector > 6) {
        selector = 0;
        delay(500);
      }
      buttonPress = false;
    }
  }
  // Here you could do other stuff as it is non blocking
}
doSwitchStatement(){...}// Stays the same as yours

Look at the code used as it is non blocking (of course there is room for improvement) but as a starter for your further experiments ...

2
  • Thanks a lot for such a great help. I am putting my entire Project theme again. – swa8788 Apr 29 '20 at 7:02
  • Please mark as accepted and thanks for the feedback – Codebreaker007 Apr 29 '20 at 7:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.