Pages: [1]   Go Down
Author Topic: Missing pulses in fast speeds although using interrupts  (Read 545 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all,

this is my project ( arduino uno, gear dc motor and encoder feedback, position control, display on LCD );

http://g1303.hizliresim.com/17/n/l8pjc.jpg
http://g1303.hizliresim.com/17/n/l8ppf.jpg
http://g1303.hizliresim.com/17/n/l8pqw.jpg

and this is entire code;

Code:
#include <LiquidCrystal.h>


const int analogInPin = A0;  //speed control with pot
const int analogOutPin = 9;
const int analogInPin1 = A1; //diection control with pot
const int in1 = 4;
const int in2 = 5;

#define encoder0PinA  2
#define encoder0PinB  3

int encoder0Pos = 0;


int analog = 0;
int analog1 = 0;       
int cikis = 0;
int yon = 0;
int buton = 0;
int in1d=0;
int in2d=0;
int ekran=0;
char ekr[4];
int a=0;

LiquidCrystal lcd(12, 11, 7, 6, 10, 8);

void setup() {
 
  Serial.begin(9600);
   lcd.begin(16,2);
  pinMode(in1,OUTPUT);
  pinMode(in2,OUTPUT);

pinMode(encoder0PinA, INPUT);
       // turn on pullup resistor
  pinMode(encoder0PinB, INPUT);
       // turn on pullup resistor

  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
 
  Serial.println("start");                // a personal quirk



}




void loop() {
 

 
  in1d=digitalRead(in1);
  in2d=digitalRead(in2);
 
  analog1=analogRead(analogInPin1);
  yon = map(analog1, 0,1023,0,255);
  analog=analogRead(analogInPin);
  cikis = map(analog, 0, 1023, 0, 255); 

  analogWrite(analogOutPin, cikis);
 
 
 

if (analog1 < 300 )
{
  digitalWrite(in1,HIGH);
  digitalWrite(in2,LOW);
}

if (analog1 > 600 )
{
  digitalWrite(in1,LOW);
  digitalWrite(in2,HIGH);
}

if (analog1 > 300 && analog1 <600 && in1d==LOW && in2d==HIGH )
{
  digitalWrite(in1,HIGH);
  digitalWrite(in2,LOW);
  delay(100);
  digitalWrite(in1,LOW);
  digitalWrite(in2,LOW);
}

if (analog1 > 300 && analog1 <600 && in1d==HIGH && in2d==LOW )
{
  digitalWrite(in1,LOW);
  digitalWrite(in2,HIGH);
  delay(100);
  digitalWrite(in1,LOW);
  digitalWrite(in2,LOW);
}


if (buton == HIGH )
{
if (in1d==LOW && in2d==HIGH )
{
  digitalWrite(in1,HIGH);
  digitalWrite(in2,LOW);
  delay(100);
  digitalWrite(in1,LOW);
  digitalWrite(in2,LOW);

 
}

if (in1d==HIGH && in2d==LOW )
{
  digitalWrite(in1,LOW);
  digitalWrite(in2,HIGH);
  delay(100);
  digitalWrite(in1,LOW);
  digitalWrite(in2,LOW);



 
}
 
 lcd.setCursor(0,0);
 lcd.print(encoder0Pos);
delay(1);

 
 
}


void doEncoder() {

  if (digitalRead(encoder0PinB) == HIGH ) {
    if (in1d==LOW && in2d==HIGH) {
    encoder0Pos++;
    }
    else
    {
    encoder0Pos--;
    }
   
  }
   
  Serial.println (encoder0Pos);

 
}


Problem is when I feed the motor about 5V I have 180 pulse per revolation and lover voltages too. But when I feed the motor 12V I see only 18-19 pulse on the lcd and serialmonitor and than it stops the counting.

I see healty pulses on the oscilloscope. It is about 300khz 12V feeding

I don't have any knowledge about clock cycle or perscale. But I think don't need any changing cause it have to enough speed with interrupts to count correct.

But I haven't try any feeding between 12..5 yet.

Please help If you have any idea immediately.

Thanks

Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Serial.print() inside an ISR is a bad idea.

Variables shared between ISR and other functions need to be volatile.
Logged

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

Thank you very much I moved serial.print void loop and now I have about 140 pulse per revolation but it have to be 180. If I use volatile int I can't write it LCD and what can I do else ?
Logged

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 50
Posts: 2210
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If I use volatile int I can't write it LCD and what can I do else ?

What?

Mark
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12568
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Obviously you will take the Serial.println() out of the interrupt and make encoderPos, in1d and in2d volatile.

You seem to be combining an interrupt with two digital reads that are done in loop().

I don't if that makes sense at all, but it makes me wonder how often you expect in1 and in2 to change state and what would happen if an interrupt occurred while they were changing.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

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

Holmes4 and PeterH firstly thanks for your interest,


My older problem was type of my encoder.

http://robotus.net/wp-content/uploads/2012/07/manyetik-encoder-forceup.jpg

 This is not usual rotary encoder. So, I tried a lot of example in Arduino Rotary Encoder Library. One of them was this code below.


Code:

/* read a rotary encoder with interrupts
   Encoder hooked up with common to GROUND,
   encoder0PinA to pin 2, encoder0PinB to pin 4 (or pin 3 see below)
   it doesn't matter which encoder pin you use for A or B 

   uses Arduino pullups on A & B channel outputs
   turning on the pullups saves having to hook up resistors
   to the A & B channel outputs

*/

#define encoder0PinA  2
#define encoder0PinB  4

volatile unsigned int encoder0Pos = 0;

void setup() {


  pinMode(encoder0PinA, INPUT);
  digitalWrite(encoder0PinA, HIGH);       // turn on pullup resistor
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinB, HIGH);       // turn on pullup resistor

  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
  Serial.begin (9600);
  Serial.println("start");                // a personal quirk

}

void loop(){
// do some stuff here - the joy of interrupts is that they take care of themselves
}

void doEncoder() {
  /* If pinA and pinB are both high or both low, it is spinning
   * forward. If they're different, it's going backward.
   *
   * For more information on speeding up this process, see
   * [Reference/PortManipulation], specifically the PIND register.
   */
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
    encoder0Pos++;
  } else {
    encoder0Pos--;
  }

  Serial.println (encoder0Pos, DEC);
}



When I use this code, I had confused but a kind of order numeric results like that;

-1
0
1
0
-1
0
1
0
-1
...

It seems like logical step like,
http://upload.wikimedia.org/wikipedia/en/6/68/Quadrature_Diagram.svg

I couldn't find anything to solve the problem, so I decieded to use only one channel.

And It works! But,

And than, new problem was I couldn't write the "encoder0Pos" to LCD 16x2 if I identify like "volatile unsigned int encoder0Pos = 0;".

Altough, I try a few type of conversation such as "itoa(x,encoder0Pos,10)" "itoa(x,encoder0Pos,16)" , it was not work.
So, I use only "int encoder0Pos = 0;". This is why I don't use volatile.

I hope I explained problems understandable.

Now I got only about %20 missing pulses per revolation, thanks to Paul. But it isn't acceptable mistake.

Thank a lot again.
Yours faithfully
Logged

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

In addition for PeterH,

In1 and In2 is driver carriers pins.

http://thumbnails.inkfrog.com/pix/noodlehed/l298_module3.jpg/596/0

ena--->pwm

and

If in1 high and in2 low motor turning clockwise rotation and if else else..

So, I don't compare two channel to relize rotation of the turning. I read In1 and In2 outputs value to understand rotation.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
And than, new problem was I couldn't write the "encoder0Pos" to LCD 16x2 if I identify like "volatile unsigned int encoder0Pos = 0;".
Why not? That is the question that you didn't answer. Fancy footwork, though.

What happens when you call lcd.print(encoder0Pos); when encoder0Pos is properly declared volatile? Does nothing print? Or, do you get some kind of compiler error?
Logged

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

Quote
And than, new problem was I couldn't write the "encoder0Pos" to LCD 16x2 if I identify like "volatile unsigned int encoder0Pos = 0;".
Why not? That is the question that you didn't answer. Fancy footwork, though.

What happens when you call lcd.print(encoder0Pos); when encoder0Pos is properly declared volatile? Does nothing print? Or, do you get some kind of compiler error?

I saw on the LCD confused characters like chinese alfabet. But I saw changes as the same time pulses. Moreover, although I write codes like "lcd.setCursor(0,0);" it shows that confused characters at (0,8) and (0,9).
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I saw on the LCD confused characters like chinese alfabet. But I saw changes as the same time pulses. Moreover, although I write codes like "lcd.setCursor(0,0);" it shows that confused characters at (0,8) and (0,9).
I know it's hard to type with your hands in your pockets, but just waving your hands is not productive.

"When I used this code:
Code:
some code goes here
I see this on the LCD:
<an image goes here>
Does anyone have any idea why?"
is a much more useful thing to do.
Logged

Offline Offline
Faraday Member
**
Karma: 61
Posts: 2865
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The lcd function might not like the "volatile" variable.

The suggested solution would be to have the "volatile" variable which the interrupt scheme requires,   and
to capture the value of that variable into another, non-volatile, variable just before calling the LCD function.
Logged

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

PaulS I will add photos and codes in a few day.

Michinyon, I try that you say, but as I said, if I able to write volatile unsigned int it is not enough also there is a problem that I couldn't compare two channel with rotary encoder libraries cides
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 602
Posts: 33379
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The lcd function might not like the "volatile" variable.
No there is nothing wrong with declaring a variable volatile, it will not affect how it is used in any other call.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12568
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I saw on the LCD confused characters like chinese alfabet.

This probably indicates either that your method of formatting the unsigned int to a string was incorrect, or that the volatile int was being updated by the ISR while you were using it - or perhaps both. The safe way to use the volatile variable from your main code would be to disable interrupts long enough to copy it to a local variable, and then use that.

In order to get more practical advice about the problem, you'd need to post your actual code and say what it did wrong.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sounds like EMI to me, as the motor speed increases it becomes a problem.  Do you have any noise suppression on the motor?  Are you trying to run the motor off of the arduino board's 5V supply?
Logged

Experience, it's what you get when you were expecting something else.

Pages: [1]   Go Up
Jump to: