External interrupt on Atmega168

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 :wink:

Please post the latest version of your code.

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

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.

cattledog:
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

//#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

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.

westfw:
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.

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.

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.

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

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

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

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;
}
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

Whandall:
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

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.

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

If you want to see signals per revolution, you have to reset the count on each round(*).

Printing the counts as fast as the (blocking!!!!) serial line allows, shows nothing, apart from ascending numbers.

(*) Yes, this reset has to be guarded by noInterrupts/interrupts too, because the fields are multi-byte and volatile.

You could try to print the counts each second

volatile long a = 0;
volatile long b = 0;

void GestIntCodM01() {
  a++;
}
void GestIntCodM02() {
  b++;
}
void setup() {
  Serial.begin(9600);
  pinMode(8, OUTPUT);     //DR M02
  pinMode(9, OUTPUT);     //PWM M01
  pinMode(1, OUTPUT);     //DR M01 ARE YOU SHURE ABOUT PIN 0 AND 1 ???
  pinMode(0, OUTPUT);     //DR M02 ARE YOU SHURE ABOUT PIN 0 AND 1 ???
  pinMode(10, OUTPUT);    //PWM M02
  pinMode(11, OUTPUT);    //DR M02
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  analogWrite(9, 0); analogWrite(10, 75);
  digitalWrite(8, 0); digitalWrite(11, 1);
  digitalWrite(1, 1); digitalWrite(0, 0);
  attachInterrupt(0, GestIntCodM01, RISING);
  attachInterrupt(1, GestIntCodM02, RISING);
}
void loop() {
  static unsigned long lastPrint;
  unsigned long topLoop = millis();

  if (topLoop - lastPrint >= 1000) {
    lastPrint = topLoop;

    noInterrupts();
    long copy_a = a;
    long copy_b = b;
    a = 0;
    b = 0;
    interrupts();

    Serial.print("M01 = ");
    Serial.print(copy_b);
    Serial.print("    M02 = ");
    Serial.println(copy_a);
  }
}

Whandall:
You could try to print the counts each second

volatile long a = 0;

volatile long b = 0;

void GestIntCodM01() {
 a++;
}
void GestIntCodM02() {
 b++;
}
void setup() {
 Serial.begin(9600);
 pinMode(8, OUTPUT);     //DR M02
 pinMode(9, OUTPUT);     //PWM M01
 pinMode(1, OUTPUT);     //DR M01 ARE YOU SHURE ABOUT PIN 0 AND 1 ???
 pinMode(0, OUTPUT);     //DR M02 ARE YOU SHURE ABOUT PIN 0 AND 1 ???
 pinMode(10, OUTPUT);    //PWM M02
 pinMode(11, OUTPUT);    //DR M02
 pinMode(2, INPUT_PULLUP);
 pinMode(3, INPUT_PULLUP);
 analogWrite(9, 0); analogWrite(10, 75);
 digitalWrite(8, 0); digitalWrite(11, 1);
 digitalWrite(1, 1); digitalWrite(0, 0);
 attachInterrupt(0, GestIntCodM01, RISING);
 attachInterrupt(1, GestIntCodM02, RISING);
}
void loop() {
 static unsigned long lastPrint;
 unsigned long topLoop = millis();

if (topLoop - lastPrint >= 1000) {
   lastPrint = topLoop;

noInterrupts();
   long copy_a = a;
   long copy_b = b;
   a = 0;
   b = 0;
   interrupts();

Serial.print("M01 = ");
   Serial.print(copy_b);
   Serial.print("    M02 = ");
   Serial.println(copy_a);
 }
}

Thank you Mr.Whandall
**i let my robot todey with a friend and i will recuperate it tomorrow to test the code that you provided to me, i hope that this one will work properly,Thank you Sir and I apologize for the disturbance :blush: **

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.

volatile long a=0;

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






void loop() {
 
noInterrupts()
copy_a = a;
copy_b = b;
interrupts()
 
Serial.print("M01 = “);
Serial.print(copy_b);
Serial.print(‚ÄĚ ¬† ¬†M02 = ");
Serial.println(copy_a);
}

Thank you too Mr.cattledog i will test the variables copy_a and copy_b and i will provide you with results
The next video shows the first test of my modest robot following a short black line
My_Line_Follower_First_Steps

Mr.Whandall, yes i am 100% sure about the OUTPUTS to control the motors direction,
however when i implemented your code into my robot i catched just one motor and the other was not moving.. this are the results for 2 different speeds "pwm" when the motor runs for 10 round and the 1 tiks chanels of the encoder are councted, so the results are for the same motor not for 2 motors

Thank You Very Much Mr.cattledog I got the following ressults using the modification that you told to me and the deffernce b'twin the number of ticks counted for slow and high speed is now Reduced


I made the motors to run until the ticks counted reach 90 ticks but i had a passing for about 10 or 15 ticks and my motor was doing 1.15 round, but when i diminuate the number of ticks to 80 ticks the motor was doing a perfect 1 round and the arduino counted 92 ticks/rd

Thank You So Much Sir, You and The Other Memebrs helped me alot.