Pages: [1]   Go Down
Author Topic: help with encoder not working on high speed  (Read 1201 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,
I have a 12V DC motor from Faulhaber with an encoder with 16 pulses/rotation. What i am trying to do is to control the position of the motor using a potentiometer, and also controlling the speed of it.
The problem is that the positioning works(with the encoder and pid library) only for pwm values under 70. Over that value the arduino simply crashes and the motor keeps rotating at high speed without reading anything from the encoder.
I tested the motor without the encoder readings and it works fine at any speed or direction. When I try to use the encoder, something goes wrong.
The code is:


#include <PID_v1.h>
#include <Encoder.h>
int sensorValue = 0;
int outputValue = 0;
int k;
long positionLeft  = -999;
Encoder myEnc(3, 2); 
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
//PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
PID myPID(&Input, &Output, &Setpoint,2,0,0, DIRECT);
  void setup() {
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);


digitalWrite(4,HIGH);

setPwmFrequency(9, 1);
//initialize the variables we're linked to
  Input = 0;
  Setpoint = 0;

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  myPID.SetSampleTime(20);
  myPID.SetOutputLimits(-75, 75);                                                      //over 75 the encoder can't read anymore

}

void loop() {
 
  sensorValue = analogRead(A0);
  k=map(analogRead(A1),0,1023,-70,70);
  outputValue=sensorValue/4;
  Input = positionLeft;
  Setpoint= sensorValue;
 
  myPID.Compute();
 
  if(Output>0)
    {analogWrite(9,Output);
    analogWrite(10,0);}
  else
    {analogWrite(10,abs(Output));
    analogWrite(9,0);
  }
  positionLeft=myEnc.read();
  positionLeft/=1000;
}


Can you give any suggenstions about what could cause the encoder to not read at high speed?? (I am using Arduino Uno, a driver with L298 H bridge and the encoder channels are using the 2 and 3 interrupt pins on Arduino).
Thanks in advance.
Logged

0
Offline Offline
Shannon Member
****
Karma: 206
Posts: 12161
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

part numbers? datasheet?  We can't guess these.
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry for not posting this information. The motor is http://www.faulhaber-group.com/uploadpk/EN_2342_CR_DFF.pdf, has a 1:23 reduction rate, and has a built-in encoder http://www.faulhaber-group.com/uploadpk/EN_IE2-16_DFF.pdf with 16 lines/revolution.
edit: I have tested the motor with a simple program (working in one direction while modifying the PWM from a potentiometer) with the encoder library and the serial readings reveald that at pwm speeds around the value of 66 the serial is reading very slowly (even at 115200 band), and when the PWM is over 70, Arduino crashes(it doesen't respond to any commands other than reset, and the serial port is also frozen).
It must be something to do with the fact that Arduino can't keep up with the readings at high speed, but how can I solve this issue?
Thanks
Logged

South Texas
Offline Offline
Edison Member
*
Karma: 8
Posts: 1025
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is the encoder connected to the motor shaft or the output shaft?

What I suspect is that the encoder is sending too many pulses to the Arduino and causing a stack overflow. Once that happens the program is completely lost.

For high speeds you will have to learn to program in assembly language and all the other challenges involved with that endevor.
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6614
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Where did you get the Encoder library from? I can't tell what is going on without seeing the code for it.

Please use code tags when posting code.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The encoder is connected to the motor shaft. It seems that programming in assembly is far too complicated for me.
The library for encoder is Encoder.h from http://www.pjrc.com/teensy/td_libs_Encoder.html and I used the Basic example to make the readings.
The code for the encoder readings with the PWM control from a potentiometer is:

Code:
#include <Encoder.h>

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(2, 3);
//   avoid using pins with LEDs attached
int potpin = A0;
int potpin2=A1;
int k,k2;

void setup() {
  Serial.begin(115200);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
digitalWrite(4,HIGH);
}

long oldPosition  = -999;

void loop() {
  k=analogRead(potpin);
k2=map(analogRead(potpin2),0,1023,0,255);

 if (k>800) {
   analogWrite(9,k2);
   analogWrite(10,0);}   
 if (k<300) {
    analogWrite(10,k2);
    analogWrite(9,0);
 }

  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.print(newPosition);
    Serial.print('\t');
    Serial.print(k2);
    Serial.println();
  }


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Any suggestions about how I can read the encoder on high speeds? Without any hardware implications maybe, only from soft...
Can a better Arduino(Mega) do the trick? Or another board with better processor?
Logged

South Texas
Offline Offline
Edison Member
*
Karma: 8
Posts: 1025
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As long as you are using the ArduinoIDE you are going to get about the same performance from any of the various "compatible" boards. They all run at 16 - 20 Mhz and execute 1 instruction per clock, the only difference is available memory.

The only way to gain speed may be to go to assembly language. Assembler is only complicated until you have used it a bit. Arduino is only complicated until you have used it a bit. The difference is that in the Arduino environment ( C, C++ ) a lot of stuff is done for you and that stuff comes with certain assumptions. Because of those assumptions there is a certain amount of overhead that libraries add to make them behave well together. That "stuff" that makes the pieces parts play well together is not always needed, but it is there because the folks that wrote the libraries and such have no idea how you might want to use/abuse the code. In Assembler you get to make those descisions. I wrote some code for a Step/Direction stepper driver using, first the Uno and then an ATtiny2313. Original code was in Arduino and I got it down to 1200 bytes. I then did it in assembly. The Assembly version is 88 bytes and I know it could be 86, but those 2 bytes are just dummy data and don't affect execution. Smaller programs execute faster. Fewer instructions equals less time.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So you are saying that I should aim to modify the encoder library using assembly? And this should  solve my problem? I can find there some instructions that I don't need or can I implement something else to reduce the encoder counts with assembly language?
Thanks for info. 
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 46
Krazatchu Design Systems
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Did someone say assembly?
http://n0m1.com/2011/12/21/inline-assembly-a-fast-quadrature-decoder/
Logged

Michael
----------------------
http://www.krazatchu.ca

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I know this is an old post but...

Don't display your position with every change.  println takes up a lot of processor effort.  What I do is run an interrupt for the encoder reading, and then in the main loop display position ever 200 ms.

Code:
/*

  Read a rotary encoder using interupts
  Encoder common <-> ground
  ENCODER0_PINA <-> pin 2
  ENCODER0_PINB <-> pin 4

*/

#define ENCODER0_PINA 2
#define ENCODER0_PINB 4

volatile int ENCODER0_pos = 0;


void setup() {
 
  pinMode(ENCODER0_PINA, INPUT);
  digitalWrite(ENCODER0_PINA, HIGH);     // Turn on pullup resistor
  pinMode(ENCODER0_PINB, INPUT);
  digitalWrite(ENCODER0_PINB, HIGH);     // Turn on pullup resistor
 
  attachInterrupt(0, doEncoder, CHANGE);  // Encoder pin on interrupt 0 (pin 2)

  Serial.begin(115200);
  Serial.println("start");
 
}

void loop() {

   Serial.println (ENCODER0_pos,DEC);
   delay(200);
 
}

void doEncoder() {
  /* If PINA and PINB are both high or low -> Moving Forward
                                      else -> Moving Backward
  */
 
  if (digitalRead(ENCODER0_PINA) == digitalRead(ENCODER0_PINB)) {
    ENCODER0_pos ++;
  } else {
    ENCODER0_pos --;
  }
   
}
Logged

Austin, TX
Offline Offline
Full Member
***
Karma: 2
Posts: 182
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The encoder "library" you are using actually has an optimized assembly version. 
From the web page:
Code:
// This optional setting causes Encoder to use more optimized code,
// It must be defined before Encoder.h is included.
#define ENCODER_OPTIMIZE_INTERRUPTS
#include <Encoder.h>

Try that and see if you can get higher than 70.

The ISR for this encoder library is doing a lot of work, even the asm version. I'd suggest looking for an encoder library or function with less overhead.

Logged

Chris J. Kiick
Robot builder and all around geek.

Pages: [1]   Go Up
Jump to: