Arduino mega don't change pin value.

Hi!.
I am making a motor positioner with a arduino mega 2560, the motor is a 36 volt actuator, I use a mosfet to activate it and a relay to change the direction of rotation (the electronics have all the protections, diodes, optocouplers, etc).
The actuator have a reed switch to count pulses.
The problem is that the digitalWrite instruction inside the interrupt never executes.
Test code I did:

void setup() {
 pinMode(7,OUTPUT); //motor
 pinMode(26,OUTPUT); // direction
 pinMode(20,INPUT); //reed switch for count pulses
 pinMode(14,INPUT_PULLUP); //button to activate
 Serial.begin(115200);
 attachInterrupt(digitalPinToInterrupt(20), sumarPulsosM1, CHANGE);
}
int boton = 0;

void sumarPulsosM1() {
  digitalWrite(7, LOW);
}

void loop() {
  boton = digitalRead(14);
 if (boton == 0){
    Serial.println("pulso");
    digitalWrite(7,HIGH);
    delay(100);
  }
}

The code works, But the pin does not change state when the digitalWrite statement is executed within the interruption, it seems that the interruption is executed 2 or 3 more times and there if the pin takes the value 0.

The problem is more evident if within the interruption I do this:

void sumarPulsosM1() {
  status = false; //FLAG FOR TEST
  digitalWrite(7, LOW);
  detachInterrupt(digitalPinToInterrupt(20));
}

In that case, the flag is set to false, but the pin is still high and because the interrupt is not executed again because it is deactivated, the pin never changes state.

The pulses approximately have a frequency between 12 and 16 hz.

This happens always when the interrupt is in CHANGE mode, if I use RISING mode sometimes happens

I already tried several alternatives to digitalWrite:
digitalWriteFast -> not work
digitalWriteFastinterruptSafe -> not work
bitClear -> not work

sorry for my English

Thank you

How are you determining the state of pin 7? What is connected to pin 7? Post a wiring diagram.

Test with pin 7 connected to an LED > 220R - 1K resistor > ground.

jremington:
How are you determining the state of pin 7? What is connected to pin 7? Post a wiring diagram.

Test with pin 7 connected to an LED > 220R - 1K resistor > ground.

These are the connection diagrams.
If I place a LED on pin 7, and run the motor, the LED does not go out and the motor runs, but the flag is in false.

I can not only place a LED because the interruption will never be called, if I call the interruption manually with a button I do not believe that the problem is repeated. I think the problem is related to the speed of interruptions

motor pin 7.PNG

motor pin 7.PNG

the LED does not go out

For a test, get rid of the code in loop(), as loop() sets the LED high again. You may never see the LED go out.

motor pin 7.PNG

You do not need R1 in the top image.

jremington:
For a test, get rid of the code in loop(), as loop() sets the LED high again. You may never see the LED go out.

The LED only turns on if I press the button to move the motor, in this case it should move until the interruption is triggered and at that time it should go out. But the interruption is triggered and the pin dont change the value Then the cycle is repeated 2 or 3 times until the pin turns off

Yes R1 is not important, the voltage is less than 20v and the current is very low

Will this be the problem?
https://code.google.com/archive/p/arduino/issues/146

But the interruption is triggered and the pin dont change the value

You have not given convincing evidence for this.

I use constructions like that very often, and have never had a problem.

This problem:
https://code.google.com/archive/p/arduino/issues/146
was fixed long ago. Interrupts are turned off while digitalWrite modifies the port register.

jremington:
You have not given convincing evidence for this.

I use constructions like that very often, and have never had a problem.

This problem:
Google Code Archive - Long-term storage for Google Code Project Hosting.
was fixed long ago. Interrupts are turned off while digitalWrite modifies the port register.

I already did a lot of tests so I went to the forum.
If within the interruption I do this:

void sumarPulsosM1() {
  digitalWrite(7, LOW);
  status = false; //FLAG FOR TEST
  count++;
  detachInterrupt(digitalPinToInterrupt(20));
}

the value of count increases 1 by 1 as it should be and the flag takes the value false. But the pin is still high and in that case it will remain active forever since the interruption is not executed again

But if within the interruption I do that

void sumarPulsosM1() {
  digitalWrite(7, LOW);
  status = false; //FLAG FOR TEST
  count++;
}

The count value increases to 2 or 3 and the pin changes state. This clearly demonstrates that the interruption triggers about 2 or 3 more times because on the first trigger the pin not change state.

I think the problem is the speed of interruptions, using the interrupt in RISING mode works a little better.
With pulseIn I measured the time it takes the reed switch to pass from LOW to HIGH and it is about 20 to 23 ms

But the pin is still high

You failed to prove that to us.

I think the problem is the speed of interruptions

Your use of interrupts is the problem. You don't need interrupts at all for this task. Forget interrupts. With simple input polling you can check a pin tens of thousands of times each second.

Don't forget to check for and correct switch bounce.

jremington:
You failed to prove that to us.
Your use of interrupts is the problem. You don't need interrupts at all for this task. Forget interrupts. With simple input polling you can check a pin tens of thousands of times each second.

Don't forget to check for and correct switch bounce.

If I count the pulses inside the loop, when I want to refresh the screen, receive DISEQC commands, etc.
I will lose pulses because the arduino is busy while the engine is moving.

The code I uploaded is only a basic example of what happens. The complete code is more complex.

Then I upload a video showing the problem.

You can see that after a few movements the pin does not change the state and the motor is still running.

In this case, what happens is:
Motor rotates:
reed switch changes state
the interruption is triggered
I should turn off the engine (sometimes it does)
The interruption is deactivated.

As the pin did not change state in one of the interruption calls, the engine is still running.

If the interruption was not deactivated at the end of it. the engine would stop in 2 or 3 trigger of the interrupt and the count clearly shows that problem.

For me clearly the problem is the speed between one interruption and the next, if I reduce the motor speed it works perfectly

With the motor at low speed I have 15 pulses per second and at maximum speed 23 pulses per second

rodrigocabraln:
In this case, what happens is:
Motor rotates:
reed switch changes state

And the reed switch contact bounces .

Yes, the reed switch bounces.
But if that were the problem the motor has to be shut down and not keep working.

I can use this code:

void sumarPulsosM1() {
	pulsoAhora = micros();
	if ((pulsoAhora - ultimoPulso) >= 30000) {
		ultimoPulso = pulsoAhora;
		motor1PulsosActuales++;
			bitClear(PORTE, 3); //parar motor 1
	}
}

It improves a little, but the problem remains and fails randomly.
In addition the reed switch is optocoupled and has an RC circuit to debounce

rodrigocabraln:
...and has an RC circuit to debounce

680ohm pull up and 1uF calculates to about 500us.
Not much for a switch.

I don't see the point in using interrupts for mechanical switches.
Polling, in a fast loop should work equally well.
Leo..

Yes, the reed switch bounces.

Excellent reason not to use interrupts.

Wawa:
680ohm pull up and 1uF calculates to about 500us.
Not much for a switch.

I don't see the point in using interrupts for mechanical switches.
Polling, in a fast loop should work equally well.
Leo..

Inside the loop I have to do the following:
update LCD (liquidCrystal)
read serial to communicate with a PIC (16 characters at 115200 baud every 2 seconds approximately)
read serial to communicate with a PC (8 characters max at 115200 baud or more)
Verify that if I am moving the motor, the pulse count changes for safety reasons

I will change the code to try, but it seems to me that there is the possibility of losing some pulse in that way