Go Down

Topic: Arduino Due Interrupt Sensitivity with Stepper Motors (Read 1 time) previous topic - next topic

3dmax

Jun 24, 2014, 06:38 am Last Edit: Jun 24, 2014, 06:45 am by 3dmax Reason: 1
The short version:

Does anyone know what the threshold is for low to high and high to low transition when an interrupt pin is set up in CHANGE mode?

Long version:

I'm currently trying to run two stepper motors with encoder feedback on them, but I'm getting faulty interrupts whenever the motors are running. I'm using the interrupts to keep track of the encoders.
At the moment I've concentrated my efforts on getting only one motor with feedback working.
I've read other topics on this issues and have tried both external and internal pull up resistors on my encoder pins. I've grounded the chassis of both the motor and power supply with Earth ground.
I'm using Gecko Stepper drivers to drive my motors with 3.5Amps in Series configuration.
There are caps placed on my breadboard across 3.3V and Gnd.
I am able to successfully run the encoders with the motors being off with the code below. Only when the motors are on do I get issues with the interrupts!
I'm running the encoders in quadrature, only using channels A and B.

I measured the signals that are occurring on the interrupt pins and they're below 100mV. I know that a high to low transition signal needs to go from gnd to approximately 3.3V. I've attached images of this from my scope.

My code:
Code: [Select]
// pins to which Encoder is hooked up to
int encoderPinA = 5;
int encoderPinB = 4;

// variables used to keep track of the encoder position
long encoderCount = 0; // keeps track of the number of times the encoder turns
int encoderCountPrev = 1; // saves old value of encoder

boolean dirFlag = HIGH; // boolena value used to change direction of setpper
int stepPin = 52; // pin used to initiate a step
int directionPin = 50; // pin used to change direction
int enablePin = 48; // pin used to enable mtr controller

void setup()
{
  // setting up interrupt
   pinMode(encoderPinA, INPUT);
   pinMode(encoderPinB, INPUT);
   digitalWrite(encoderPinA, HIGH); // pull up resistors enabled
   digitalWrite(encoderPinB, HIGH);
   attachInterrupt(5, doOnA, CHANGE); // calling doOnX isr
   attachInterrupt(4, doOnB, CHANGE);
 
   pinMode(enablePin, OUTPUT);
   pinMode(directionPin, OUTPUT);
   pinMode(stepPin, OUTPUT);
   
   digitalWrite(enablePin, LOW);
   digitalWrite(directionPin, dirFlag);
   
   Serial.begin(115200);
}

void loop()
{
  for(int i =0; i < 200; i++)
  {
   takeAStep();
   delay(10);  
  }
  dirFlag = !dirFlag;
  digitalWrite(directionPin, dirFlag);
 
 if(encoderCountPrev != encoderCount)
 {
  Serial.print("Encoder value = "); // cake topping
  Serial.println(encoderCount, DEC); // print out the new value of the encoder count
  encoderCountPrev = encoderCount; // save the current value into the old M
 }
}


// performs this operation when A changes state on the encoder
void doOnA()
{
 if (REG_PIOC_PDSR & (1 << 25)) {  // look for a low-to-high on channel A
   if (!(REG_PIOC_PDSR & (1 << 26))) { // check channel B to see which way encoder is turning
     encoderCount++;
   }
   else {
     encoderCount--;
   }
 }
 else {                                     // must be a high-to-low edge on channel A
   if (REG_PIOC_PDSR & (1 << 26)) { // check channel B to see which way encoder is turning  
     encoderCount++;
   }
   else {
     encoderCount--;
   }
 }
}

//perform this operation when B changes state on the encoder
void doOnB()
{
 if (REG_PIOC_PDSR & (1 << 26)) {   // look for a low-to-high on channel B
   if (REG_PIOC_PDSR & (1 << 25)) { // check channel A to see which way encoder is turning
     encoderCount++;
   }
   else {
     encoderCount--;
   }
 }
 else {                                    // must be a high-to-low edge on on channel B
   if (!(REG_PIOC_PDSR & (1 << 25))) { // check channel B to see which way encoder is turning
     encoderCount++;
   }
   else {
     encoderCount--;
   }
 }
}

void takeAStep()
{
  REG_PIOB_SODR = 0x1 << 21; //set the pin high
  delay(1);
//     delayMicroseconds(5);
  REG_PIOB_CODR = 0x1 << 21; //set the pin low
}

Some of the things that are running through my mind with this issue:
1. EMF from motors is interacting with the digital pins, but would a 100mV signal trigger interrupts, when set up in CHANGE mode?
2. It can't be the noise from the connection between the Arduino Due and the Gecko stepper drivers as the drivers are opto-isolated and the encoders work fine with motors powered down, but stepper driver being on.
3. The breadboard is picking up the electromagnetic noise, since it is so close to the motors, but a 100mV signal causing faulty interrupt trigger?!

Anyways, any ideas on what could be going on?


3dmax


MarkT


The short version:

Does anyone know what the threshold is for low to high and high to low transition when an interrupt pin is set up in CHANGE mode?



Yes, the datasheet knows.  The Due has pins of varying types, some are schmitt-trigger,
some are not.

For a digital signal you should not be putting an analog voltage onto it in the first place
though, you perhaps need proper signal conditioning on your encoder signals.

1) cables should be screened, screen connected to Arduino ground only.
2) Keep encoder cable well away from motor wiring.
3) low-pass filter the encoder outputs with RC circuit, time constant of about 5us
perhaps (1k and 4.7nF)
4) then schmitt-trigger to clean up the output of the filter, use 74HC14 hex inverter
chip for this.
5) Make sure you are not passing motor ground currents through the Due.

The spikes that are triggering the interrupts only need to be about 1ns long
on the Due if I remember rightly - this is why a low-pass filter will make a difference
and why you can't see what's happening.

Make sure you have decoupling in all the right places.

Interference is often from the currents, not voltages, so if you don't
connect motor to driver you won't see any effect as there is no current.

[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

3dmax

Thanks MarkT

Using the filter and the schmitt trigger makes sense. I'll give it a go.

Out of curiosity, is there a difference with shielding wires with Earth Ground from an outlet and the Ground supply of the micro controller?
I feel that the arduino's ground wire and board inductance would cause unwanted noise on the ground versus using the earth ground where I'm not using it as a reference for any other voltage. Then again it shouldn't be a lot of current that needs to be dissipated through those grounding wires.


3dmax

Also most of the pins on the Due have Schmitt triggers on them except:
2. PIOA: Schmitt Trigger on all, except PA0, PA9, PA26, PA29, PA30, PA31
3. PIOB: Schmitt Trigger on all, except PB14 and PB22
4. PIOC: Schmitt Trigger on all, except PC2 to PC9, PC15 to PC24
5. PIOD: Schmitt Trigger on all, except PD10 to PD30
6. PIOE: Schmitt Trigger on all, except PE0 to PE4, PE15, PE17, PE19, PE21, PE23, PE25, PE29
7. PIOF: Schmitt Trigger on all PIOs
Page 13 of the datasheet

MarkT


Thanks MarkT

Using the filter and the schmitt trigger makes sense. I'll give it a go.

Out of curiosity, is there a difference with shielding wires with Earth Ground from an outlet and the Ground supply of the micro controller?
I feel that the arduino's ground wire and board inductance would cause unwanted noise on the ground versus using the earth ground where I'm not using it as a reference for any other voltage. Then again it shouldn't be a lot of current that needs to be dissipated through those grounding wires.




Mains earth is full of noise induced from the mains wiring, a no-no for small signals.

You want the ground that is the actual reference ground for signal in question, so that
induced common-mode noise doesn't affect the differential signal.  Its vital no ground
currents flow hence the shield needs to be connected to Arduino ground at the Arduino
and not connected to anything else.

Fault voltages in mains earth can be fairly high(*) BTW, but only till a fuse blows - so mains
earth is safe for humans but not for semiconductors.

(*) higher than half the mains voltage - typically earth wires are thinner than live and
neutral as they don't carry sustained current, only fault currents for a few ms while
the fuse wire vaporises.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up