Go Down

Topic: External interrupt on Atmega168 (Read 3391 times) previous topic - next topic

Wahrani31

The gree pin is connected to the GND of the L298 and the brown is connected to the VCC which is a 5V DC suplay

Whandall

And the GND of the Arduino is connected to the GND of the power supply?
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

westfw


Quote
my hall encoder has 360 points per round so i should count 360 coder ticks per round but what i count is just 90 ticks/round
Are you sure that "360 points" doesn't become "90 ticks" once you run it through quadrature decoding?

cattledog

#18
May 01, 2016, 03:29 am Last Edit: May 01, 2016, 03:29 am by cattledog
Code: [Select]
attachInterrupt(0, GestIntCodM01, RISING);
attachInterrupt(1, GestIntCodM02, RISING);


Code: [Select]
void GestIntCodM01()
{
  a++;
  }
  void GestIntCodM02()
{
  b++;
  }


westfw is correct. Selection of one pin Rising will read only one in four of the quadrature transitions. It will not handle a change in direction either. You have a choice of 90,180, 360 counts per revolution. What do you require?

You will need to read the state of the other encoder pin to determine direction.

Wahrani31

#19
May 01, 2016, 10:31 am Last Edit: May 01, 2016, 11:17 am by Wahrani31
And the GND of the Arduino is connected to the GND of the power supply?
Yes Sir all the components have a common GND to reach the full speed of motor.

Are you sure that "360 points" doesn't become "90 ticks" once you run it through quadrature decoding?
in the datasheet i have found this, i think if the encoder should return '90 ticks' so they would write '90' instead '360' didn't they ?



It will not handle a change in direction either. You have a choice of 90,180, 360 counts per revolution. What do you require?
You will need to read the state of the other encoder pin to determine direction.
For me sir, 90 ticks/rd is totaly enough but the probleme is that i get it just if i run in the slowest speed and when i increas the speed the ticks counted decrease so i can never calculate the real speed in this case, for now i don't need to detect the direction of the mototrs i want just define the speed.

westfw is correct. Selection of one pin Rising will read only one in four of the quadrature transitions.
so, i have to connect the 2 chanel of the encoder and incremant my counter "a" even if the interrupt come from chanel A or B to detect all the ticks is this right.

Wahrani31

i tried to incremant the counter even if the interrupt is received from the first chanel or the second and this is what i got for one motor, '2 X 90' tick



Thank you every one for encoraging me, i began to lose hope to use PID controller in my robot but with your help i am sure that i will do it soon  ;)

cattledog

Please post the latest version of your code.

Is the main problem that the counts go down with increasing speed?


Quote
The Same results for INPUT_PULLUP mode
Are they still in your latest code? The open collector Hall sensors will require some pullups.
The internal pullups may not be strong enough, and you can use external pullups of 4.7K to 5v on pins 2 and 3.

Wahrani31

Please post the latest version of your code.

Is the main problem that the counts go down with increasing speed?


Are they still in your latest code? The open collector Hall sensors will require some pullups.
The internal pullups may not be strong enough, and you can use external pullups of 4.7K to 5v on pins 2 and 3.
Hi mr.cattledog
here is the too last code that i tried

Code: [Select]
//#include <FlexiTimer2.h>
//#include <digitalWriteFast.h>
volatile long a=0;
volatile long b=0;
void setup() {
  // put your setup code here, to run once:
pinMode(8, OUTPUT);     //DR M02
pinMode(9, OUTPUT);     //PWM M01
pinMode(1, OUTPUT);     //DR M01
pinMode(0, OUTPUT);     //DR M02
pinMode(10, OUTPUT);    //PWM M02
pinMode(11, OUTPUT);    //DR M02
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
//analogWrite(9, 165);analogWrite(10, 73);
//analogWrite(9, 20);analogWrite(10, 30);
analogWrite(9,0);analogWrite(10, 75);
//digitalWrite(2, 1);digitalWrite(3, 1);
digitalWrite(8, 0);digitalWrite(11, 1);
digitalWrite(1, 1);digitalWrite(0, 0);
attachInterrupt(0, GestIntCodM01, RISING);
attachInterrupt(1, GestIntCodM02, RISING);
Serial.begin(9600);

}
void loop() {
 
  //rb=digitalRead(15);
  // put your main code here, to run repeatedly:
         
//else ra=0;
//if(rb==1) b++;
Serial.print("M01 = ");Serial.print(b);
//Serial.print("\r");
Serial.print("    M02 = ");Serial.println(a);
Serial.print("\r");
//Serial.print("b = ");Serial.println(b);
}
void GestIntCodM01()
{
  a++;
  }
  void GestIntCodM02()
{
  b++;
  }

befor using internel pull_up, i used 4.7k and 10k and even 39k ohm resistors but alwase the same results

westfw


Quote
 if the encoder should return '90 ticks' so they would write '90' instead '360' didn't they ?
It's a combination of the hardware and the software you are using.
It's called a quadrature encoder because it has four states that repeat when you rotate in either direction.  The software has to decode the states to figure out which direction the shaft is turning.  What I'm suspecting is that the motor encoder goes through 360 states per revolution, but the arduino software is "decoding" a full 4-state cycle before it reports a step in one direction or the other.  (probably, you need at least two or four states to determine direction, UNLESS you save the "last known direction" in the driver somewhere.  Since a lot of the arduino applications that use encoders are aimed at user knobs rather than  higher-speed motors, the library probably isn't trying to be a high-performance high-accuracy implementation.

Wahrani31

It's a combination of the hardware and the software you are using.
It's called a quadrature encoder because it has four states that repeat when you rotate in either direction.  The software has to decode the states to figure out which direction the shaft is turning.  What I'm suspecting is that the motor encoder goes through 360 states per revolution, but the arduino software is "decoding" a full 4-state cycle before it reports a step in one direction or the other.
Thank you very much bro, this analysis is logical, but My only problem with the engines is that it does not give me the same number of points for various speeds, and when the speed increase the number of counted ticks decrease.

Whandall

The code you show does not produce te output you show.

It blocks on serial with 9600 baud.

You do not have the sligthest chance to see the real counts.

The accesses are still unguarded.

Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

Wahrani31

The code you show does not produce te output you show.

It blocks on serial with 9600 baud.

You do not have the sligthest chance to see the real counts.

The accesses are still unguarded.


But i tried to print results using a fast baud rate "115000" and a slow baud rate "1200" and it shows me the same results

Whandall

The code you show does not produce the output you show.
BTW its hard to believe that b never gets incremented.

Code: [Select]
void loop() {
  Serial.print("M01 = ");
  Serial.print(b);
  Serial.print("    M02 = ");
  Serial.println(a);
  Serial.print("\r");
}

The above code can only print ascending numbers, apart from the artefacts that your non-guarding will produce.

Demo for you still unfixed guarding issue
Code: [Select]
void setup() {
  Serial.begin(115200);
  Serial.println(F("wait for error..."));
  // set up Timer 1
  TCCR1A = 0;                        // normal operation
  TCCR1B = bit(WGM12) | bit(CS10);   // CTC, no pre-scaling
  OCR1A =  10999;                    // compare A register value (1000 * clock speed)
  TIMSK1 = bit(OCIE1A);              // interrupt on Compare A Match
}
volatile unsigned long Counter;

ISR(TIMER1_COMPA_vect)
{
  Counter++;
}

void loop() {
  static unsigned long before;
  static unsigned long current;
  //  noInterrupts();
  current = Counter;
  //  interrupts();
  unsigned long differenz = current - before;
  if (differenz > 1) {
    Serial.print(F("from 0x"));
    Serial.print(before, HEX);
    Serial.print(F(" to 0x"));
    Serial.print(current, HEX);
    Serial.print(F(" diff 0x"));
    Serial.println(differenz, HEX);
  }
  before = current;
}
Code: [Select]
wait for error...
from 0x9FF to 0xAFF diff 0x100
from 0xAFF to 0xA01 diff 0xFFFFFF02
from 0x2DFF to 0x2EFF diff 0x100
from 0x2EFF to 0x2E01 diff 0xFFFFFF02
from 0x38FF to 0x39FF diff 0x100
from 0x39FF to 0x3901 diff 0xFFFFFF02
from 0x6BFF to 0x6CFF diff 0x100
from 0x6CFF to 0x6C01 diff 0xFFFFFF02
from 0x6EFF to 0x6FFF diff 0x100
from 0x6FFF to 0x6F01 diff 0xFFFFFF02
from 0x72FF to 0x73FF diff 0x100
from 0x73FF to 0x7301 diff 0xFFFFFF02
from 0x84FF to 0x85FF diff 0x100
from 0x85FF to 0x8501 diff 0xFFFFFF02
from 0x91FF to 0x92FF diff 0x100
from 0x92FF to 0x9201 diff 0xFFFFFF02
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

Wahrani31

The code you show does not produce the output you show.
BTW its hard to believe that b never gets incremented.
I assure you that it is the same code, i just don't need to read the 2 signals so i removed one chanel signal, that's all. i wanted to compare between values read from the same chanel for various speeds

cattledog

#29
May 02, 2016, 10:14 pm Last Edit: May 04, 2016, 01:10 am by cattledog
Here is how to modify your loop to make the protected copies of the volatile variables.
Declare your protected copies along with the voltatile variables.

Code: [Select]

volatile long a=0;
volatile long b=0;
long copy_a = 0;
long copy_b = 0;


Code: [Select]

void loop() {
 
noInterrupts();
copy_a = a;
copy_b = b;
interrupts();
 
Serial.print("M01 = ");
Serial.print(copy_b);
Serial.print("    M02 = ");
Serial.println(copy_a);
}

Go Up