How to use interrupts

Because... Why?

Does Arduino UNO support RISING edge trigger for interrupt?

Yes, it does.

I've tried changing it to RISING and I didn't see a difference

NMI interrupt of 8086 has ANDed both RISING Edge and active HIGH; whereas, Arduino UNO (the ATmega328P) has totally ignored active HIGH state. Has it been good considering that RISING edge might has been generated due to sudden noise spike?

I, too, would like to hear your reasoning.

I wrote that code because if LastPulseTime was left set from the last time the pulses stopped, calling "CountPulsesUntilTheyStop()" could return immediately. Let's say LastPulseTime is 3000 and millis() is now at 5000.

const unsigned MaxPulseLength = 20;

void CountPulsesUntilTheyStop()
{
//  noInterrupts();
//  LastPulseTime = millis();
//  interrupts();

  while (1)
  {
    noInterrupts();
    unsigned long LPT = LastPulseTime;  // 3000
    interrupts();

    // 5000 - 3000 = 2000.  2000 >= 20 so time to return.
    if (millis() - LPT >= MaxPulseLength)
    {
      // No pulse state change for a while.  Must have hit a stop
      return;
    }
  }
}

Unless the motor accelerates fast enough that there will ALWAYS be an interrupt before LastPulseTime is fetched, the code is needed to prevent a premature timeout.

At the moment, the motor goes at full speed clockwise. When it hits the stop, it doesn't stop and go anti-clockwise. It tries to keep moving and there are still pulses being seen on the scope.

:face_with_diagonal_mouth:

As @RayLivingston already stated, the UNO does. See here

https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

Please consider that Uno, Nano, Mini and other 328-based only support Pins 2 and 3

If you are afraid of EMI there is no difference between RISING or FALLING (because a spike has also both edges, of course). To detect the state LOW (which is supported by UNO while HIGH is not) you had to invert the input signal. That is possible of course. But quite likely not required, if you use an aedequate pulldown resistor at the pin (unless you are working in a electrically "messy" environment).

Do you have a possibility to manually control the motor ?

That would allow to check the sketch step by step. I have taken the code from post 19 and just modified setup() and loop() as follows:

In setup()

//  MoveToCenter();   // Just made it a comment

In loop()

void loop() {
  PulseCount = 0;
  WaitUntilPulseCount(10);
  CountPulsesUntilTheyStop();
  Serial.println(PulseCount);
  Serial.println("-------");
  }

Now if you could move the motor axis you should get data. I just tested it with an UNO and two wires, one connected to pin 2 and the other to 3.3V as the interrupt reacts on change. It works well as a bouncing counter ... :wink:

I can power the motor independently from the sensor rather than having it controlled in code

That sounds good ... If you would make the changes as I posted, you could test

  • first by just connecting some wires with or without a pusbutton instead of the sensor (just take care of the correct voltage!)
  • second - if that works - with the motor axis sensor connected to it ...

That might lead one step forward ... (hopefully) :innocent:

Got it wrong. Sorry about that.

There is a potential caveat. If CountPulsesUntilTheyStop is called with the motor powered and stalled CountPulsesUntilTheyStop will wait the full timeout before returning. It looks like the latest version uses 20 milliseconds which seems like an insignificant risk. 1 second seems troublesome.

I've added the new code and tested the motor with the sensor and the interrupt is picking up the signal nicely. From end to end it counted 1600 pulses.

So with the test code from post 30 the counting is ok? If this is correct, it would be good news because it means that @johnwasser 's ISR routine works as expected! Creating a software that works - without access to specific hardware - is not an easy task and requires some loops with you :wink:

A next step could be to test the further routines @johnwasser has provided, e.g. Clockwise(); and Anticlockwise(); but without damaging your hardware.

Can you remove/not use the endstops for a test or is it a fixed configuration?
If you can work without, you could just test both routines separately (e.g. by changing loop() in the test sketch (still have // MoveToCenter() as a comment in setup() ) to something like

void loop() {
  Clockwise();
  int count = 0;
  while (count < 100) {
    CountPulsesUntilTheyStop();
    Serial.println(PulseCount);
    Serial.println("-------");
    count++;  // inc(count) is Pascal ;-))
    delay(100);
  }
Stop();
while(1) {  }; // Wait here
}

If this works, change Clockwise() to Anticlockwise() and test it.

@ec2021 Tried to compile with the new loop and the inc(count); willnot compile, says inc not declared

Sorry, I mixed Pascal with C++ :wink:

inc(count) in Pascal is similar to count++ in C/C++

I corrected it in post 35 with a comment.

I've run the motor in both directions and it is counting up the pulses.

If you would return to the full code from @johnwasser, the issue would be like this

Correct?

Yes that is correct.

It motors clockwise and doesn't stop when it should stall.