Add and remove 1 to a variable with interruptions

I need help making a program that adds 1 to a variable or subtracts 1 from it but using interrupts. I have been able to do the part of adding but I can not subtract 1 from the same variable. This is the program I have used (I am Spanish):

volatile int pin21 = 0;
volatile int pin20 = 0;
int antPin20 = 0;
int antPin21 = 0;
long Time = 0;
const int banda = 200;

void setup() {
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(21), vueltaMas, RISING);
  attachInterrupt(digitalPinToInterrupt(20), remove, RISING);
}

void loop() {
 if(antPin21 != pin21) {
   Serial.print(pin21);
   antPin21 = pin21;
 }
 if(antPin20 != pin20){
   Serial.println(pin20);
   antPin20 = pin20;
 }
}
void vueltaMas() {
  if (millis() - Time > banda){ 
  pin21++;
  Time = millis();
  }
}
 void remove(){
  if (millis() - Time > banda){
    pin20--;
    Time = millis();
  }
}

Welcome to the forum

pin21++;
    pin20--;

The same variable ?

I sincerely hope that those pins aren't just connected to push buttons.

Also, an 'int' type is non-atomic, which creates a critical section in your main code. You failed to protect the read by making a copy with interrupts disabled.

I understand now, but how can I turn the two variables into one while still using interrupts?

You also failed to make 'Time' volatile. Also it probably shouldn't be shared by two different functions. It's a time stamp.

I have no idea what you mean.

o yes, my bad :sweat_smile:

Ex.

void vueltaMas() {
  static unsigned long Time = millis();
  if (millis() - Time > banda){ 
  pin21++;
  Time = millis();
  }
}

if I can explain. I have two variables "pin21", which is the one that adds 1 and goes well and the "pin20" that should subtract 1 from a variable. They are two different variables because when I try to use a single variable I do not return any value or one variable or the other. What I try to solve is how I can use the same variable in addition and subtraction, always using the interruptions.

Well, I am confused. If you want to increment/decrement a single value, use a single variable. I can't imagine any possible problem in doing so. So you have to explain what your exact problem is.

If there is code that goes with your statement, "when I try", then please post it here. The code you already posted, doesn't try.

Also please try to use more descriptive names. "pin20" says absolutely nothing about what it does. Something like "count" or "pin_transition_count" does.

Also, what are the physical pins attached to? Is this because of a hardware requirement or is this just an academic exercise in learning about interrupts?

I'm doing the program again with your recommendations in a second I send it. It's physical, for a lap counter of a pneumatic screwdriver.

1 Like

Forgot to ask, what processor? By the way, check this out:
https://gammon.com.au/interrupts

im using a mega 2560, and thanks for that web, its very extended.

I have placed your code in the wokwi, made a few corrections so it actucally compikles and runs, and find that it works.

Take the link and play with it. You will see it works, except your thinking on debouncing is flawed, so each press will result in action on the press and release of the button.


volatile int pin21 = 0;
volatile int pin20 = 0;

int antPin20 = 0;
int antPin21 = 0;

long Time = 0;

const int banda = 20;

void setup() {
  Serial.begin(9600);
  Serial.println("Wake up!\n");

  pinMode(19, INPUT_PULLUP);
  pinMode(20, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(21), remove, FALLING);
  attachInterrupt(digitalPinToInterrupt(20), vueltaMas, FALLING);
}

void loop() {
 if(antPin21 != pin21) {
   Serial.print(pin21);
   antPin21 = pin21;
 }
 if(antPin20 != pin20){
   Serial.println(pin20);
   antPin20 = pin20;
 }
}

void vueltaMas() {
  if (millis() - Time > banda){ 
  pin21++;
  Time = millis();
  }
}

 void remove(){
  if (millis() - Time > banda){
    pin20--;
    Time = millis();
  }
}

If you replace pin21++ with pin20++ in vueltaMas() the buttons will one increment and the other decrement a single variable.

In all this I am assuming you are using interrupts for a better reason somewhere.

a7

It maybe a problem of translation but I am curious as to why the variables are named pin20 and pin21

@quexo have the variable names got anything to do with the pin numbers of the Mega board ?

yes, those pins are the ones that support interrupts, along with 2, 3, 18, and 19. Those I have occupied by other outputs

thanks but i still having a problem. The serial monitor didnt show a decrement. It show "-1, -2, -3..." but when i press the remove button it doesnt do anything. This could be and connection problem? Im using an industrial adaptor

I think I've fixed it. The problem I think is that the serial monitor doesn't give an answer when you subtract 1. I can not check it physically but here is the code, in case you can confirm it:

volatile int counter = 0;
volatile int long time = 0;
const int banda = 200;
int preCounter = 0;

void setup(){
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(21), add, RISING);
  attachInterrupt(digitalPinToInterrupt(20), remove, RISING);
}

void add(){
 static unsigned long time = millis();
 if (millis() - time > banda){
   counter++;
   time = millis();
 }
}
void remove(){
 static unsigned long time = millis();
 if (millis() - time > banda){
   counter--;
   time = millis();
 } 
}
void loop(){
if (counter != preCounter){
   Serial.print(counter);
   preCounter = counter;
 }
}

You can remove this line because the two interrupt service routines each contain a local variable named 'time' so they don't use the global variable.

Because 'counter' can change at any time, even half-way through comparing, you should disable interrupts when accessing it:

void loop()
{
  noInterrupts();
  int localCounter = counter;
  boolean print = localCounter != preCounter;
  interrupts();

  preCounter = localCounter
  
  if (print)
  {
     Serial.print(localCounter);
  }
}

That makes no sense. If counter has changed, your loop() will print the new value.

Your latest code works in the wokwi. If it does something else in real life, you have an issue that is not code related.

And your debounce idea still doesn't. Debounce. So each button press gets counted twice as there are RISING edges on both button down and button up.

a7