3

I am trying to make a simple debounce function as explained here but the condition if((millis()-timeCheck)>reboundDelay) is never met.

As you can see in my code below, I am trying to control a PWM with two push buttons. I am currently sending it on a LED.

With AS7 and vMicro I put some breakpoints and realized that timeCheck was stuck at 0 and was an unsigned int instead of the unsigned long I declared. With the debugger I looked inside of the millis() function and saw that timer0_millis wasn't increasing neither, stuck at 0.

Here is my short code (it's a sketch, it can surely be rewritten in a more efficient way) :

int PWM=9;
int dutyP=2;
int dutyM=3;
int duty=123;
bool stateP=0;
bool stateM=0;
bool prevStateP=0;
bool prevStateM=0;
unsigned long reboundDelay=500;
unsigned long timeCheck=millis();

void setup() {
  pinMode(PWM,OUTPUT);
  pinMode(dutyP,INPUT);
  pinMode(dutyM,INPUT);
}

void loop() {
  stateP=digitalRead(dutyP);
  stateM=digitalRead(dutyM);
  if(stateP != prevStateP || stateM != prevStateM) {
    timeCheck=millis();
  }
  if((millis() -  timeCheck) > reboundDelay) {
    if(stateP==1) {
      duty=duty+25;
    } else if(stateM==1) {
      duty=duty-25;
    }
    analogWrite(PWM,duty);
    prevStateP=stateP;
    prevStateM=stateM;
  }
}

And finally, the strange part. When I upload it on my Genuino Uno for like 30 seconds, the pushbuttons do nothing (it may be that the if works) and afterwards I can increase and decrease the duty cycle but without the delay that the condition should bring (the LED flashes really fast due to an overflow in analogWrite).

Any help is welcomed, the strange part is secondary to me but I would really like to make millis() work properly.

12
  • bool variables have two possible values true and false. 1 and 0 are technically ints, you might be OK but I wouldn't do it. You should also check for wrap on duty. Commented May 26, 2017 at 11:35
  • Would it be possible to just do this loop? loop(){Serial.println(millis());delay(500);} If you are right about millis not moving then this will prove it. There may be something in the debuggers that interfere with millis. Commented May 26, 2017 at 11:38
  • I tried to but nothing happen in the serial monitor despite : Port closed Uploading to I/O board Opening port Port open Commented May 26, 2017 at 12:01
  • Should I write stateP==true or false instead of 1 or 0 ? Commented May 26, 2017 at 12:02
  • Did you try with an empty project? If so you have a bigger problem :( Commented May 26, 2017 at 12:02

2 Answers 2

2

I think there is just a logic error that doesn't immediately jump out: When the button state is changed, it will always set timeCheck equal to millis(). For instance, as long as you are pressing "P", stateP will not be equal to prevStateP and so "timeCheck=millis()" will executed everytime thru the loop, so the difference will never reach 500.

if(stateP != prevStateP || stateM != prevStateM){
    timeCheck=millis();
}

Should be something like:

if(stateP == prevStateP && stateM == prevStateM){
    timeCheck = millis();
}

This will continually keep timeCheck = millis() until either button is pressed. Once the button is pressed, timeCheck will remain at the value of millis() read just before the press, until the debounce value is reached (unless noise/bounce and not a real press, or button is released early as 500ms is a relatively long time).

This is probably the simplest modification to the code I can come up with. Hope it helps.

1

I would suggest a few things:

1) comment on your code -> lay out the basic logic so that you and others can help you debug it;

2) use brackets liberally -> don't rely on memory (=faulty) on the order of operations. instead, define it explicitly;

3) check your logic -> make sure that your code does what you want it to do;

4) pay attention to data type: 8-bit vs. 16-bit, etc.

5) modularize your code -> this allows more efficient debugging and code reusing.

for example, your code can be simply described as

  button_state = read_button(); //read button state, with debouncing
  if (button_state = BUTTON_UP) pwminc_dc(pwm_dc); //increase duty cycle, with boundary checking
  if (button_state = BUTTON_DOWN) pwmdec_dc(pwm_dc); //decrement duty cycle, with boundary checking

with the code modularized, you just need to worry about getting individual pieces right.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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