user52245: I am using a 4wd robotic car to measure straight distances. I have attached two encoders on the front two wheels to measure the distance and I am using the back two wheels to adjust the car and keep it driving straight by using a compass as a reference. The Problem is that when my program is executing the section that drives the back wheels this somehow triggers the interrupt and increments the number of ticks. What is causing this issue?
volatile unsigned long enc_l = 0;
volatile unsigned long enc_r = 0;

void driveStraight(float drive_distance, int motor_power)
{
  Serial.print("\n");
  Serial.println("num_tick_l \t num_tick_r \t diff_l \t diff_r \t enc_1_prev \t enc_r_prev \t Power_l \t Power_r \t Power_a \t Power_b ");

  unsigned long num_ticks_l;
  unsigned long num_ticks_r;

  // Set initial motor power
  int power_l = motor_power;
  int power_r = motor_power;

  // Used to determine which way to turn to adjust
  unsigned long diff_l;
  unsigned long diff_r;

  // Reset encoder counts
  enc_l = 0;
  enc_r = 0;

  // Remember previous encoder counts
  unsigned long enc_l_prev = enc_l;
  unsigned long enc_r_prev = enc_r;

  // Calculate targer number of ticks
  float num_rev = (drive_distance * 10) / wheel_c;   // Convert to mm
  unsigned long target_count =  29; //num_rev * counts_per_rev;


  /*
    // Debug
    Serial.print("Driving for ");
    Serial.print(drive_distance);
    Serial.print(" cm(");
    Serial.print(target_count);
    Serial.print(" ticks) at ");
    Serial.print(motor_power);
    Serial.println(" Motor Power");
  */

  //Drive until on of the encoders reaches desired count
  while ((enc_l < target_count) && (enc_r < target_count))
  {

    bluetooth();                                // if new bluetooth value received break from loop
    if (blueToothVal == 5) {
      break;                                    // If a 'Stop' Bluetooth command is received then break from the Loop
    }

    // Sample number of encoder ticks
    num_ticks_l = enc_l;
    num_ticks_r = enc_r;

    // Sample out current number of ticks
    Serial.print(num_ticks_l);
    Serial.print("  \t\t");
    Serial.print(num_ticks_r);

    // Drive
    drive(power_l, power_r);

    // Number of ticks counted since last time
    const int StraightDriveOffset = 1;                    // Increase this or even make it a negatie number to tweak the

    diff_l = num_ticks_l - enc_l_prev;                    // + StraightDriveOffset;
    diff_r = num_ticks_r - enc_r_prev;


    Serial.print("  \t\t");
    Serial.print(diff_l);
    Serial.print(" \t \t");
    Serial.print(diff_r);


    // Store current ticks counter for next time
    enc_l_prev = num_ticks_l;
    enc_r_prev = num_ticks_r;


    Serial.print("   \t \t");
    Serial.print(enc_l_prev);
    Serial.print(" \t \t");
    Serial.print(enc_r_prev);


    // If left is faster, slow it down and speed up right
    if ( diff_l > diff_r) {
      power_l -= motor_offset;
      power_r += motor_offset;
    }

    // If right is faster, slow it down and speed up right
    if ( diff_l < diff_r) {
      power_l += motor_offset;
      power_r -= motor_offset;
    }

    // Debugging
    Serial.print(" \t\t");
    Serial.print(power_l);
    Serial.print(" \t\t");
    Serial.println(power_r);


    // Brif pause to let motors respond
    delay(20);
  }

  StopCar();
  //Buzzer();
}

void drive(int power_a, int power_b)
{
  getCompass();                                                     // Update Compass Heading
  bluetooth();                                                      // Check to see if any Bluetooth commands have been sent

  if (blueToothVal == 5) {
    break; // If a Stop Bluetooth command ('5') is received then break from the Loop
  }

  // Constrain power to between -255 and 255
  power_a = constrain(power_a, -255, 255);
  power_b = constrain(power_b, -255, 255);

  if ( abs(desired_heading - compass_heading) <= compass_dev )      // If the Desired Heading and the Compass Heading are within the compass deviation, X degrees of each other then Go Forward
    // otherwise find the shortest turn radius and turn left or right
  {
    // Left motor direction
    if ( power_a < 0)
    {
      motor2.setSpeed(abs(power_a));       // Motor is the front left wheel
      motor2.run(BACKWARD);

    }
    else
    {
      motor2.setSpeed(abs(power_a));       // Motor is the front left wheel
      motor2.run(FORWARD);

    }

    // Right Motor direction
    if ( power_b < 0)
    {
      motor4.setSpeed(abs(power_b));       // Motor is the front left wheel
      motor4.run(BACKWARD);

    }
    else
    {
      motor4.setSpeed(abs(power_b));       // Motor is the front left wheel
      motor4.run(FORWARD);

    }

  }

  else
  {
    int x = (desired_heading - 359);                          // x = the GPS desired heading - 360
    int y = (compass_heading - (x));                          // y = the Compass heading - x
    int z = (y - 360);                                        // z = y - 360

    if ((z <= 180) && (z >= 0))                               // if z is less than 180 and not a negative value then turn left
    { // otherwise turn right
      motor1.setSpeed(190);
      motor3.setSpeed(190);
      motor1.run(BACKWARD);
      motor3.run(FORWARD);
    }
    else
    {
      motor1.setSpeed(190);
      motor3.setSpeed(190);
      motor1.run(FORWARD);
      motor3.run(BACKWARD);

    }
  }
}

void countLeft()
{
  enc_l ++;
}

void countRight()
{
  enc_r ++;
}

and this is what is on the setup function
const int enc_l_pin = 18;
const int enc_r_pin = 19;

void setup()
    {
      Serial.begin(115200);                                            // Serial 0 is for communication with the computer
      Serial3.begin(9600);                                             // Serial 1 is for Bluetooth communication - DO NOT MODIFY - JY-MCU HC-06 v1.40

      Wire.begin();                                                    // Join I2C bus used for the HMC5883L compass
      compass.begin();                                                 // initialize the compass (HMC5883L)
      compass.setRange(HMC5883L_RANGE_1_3GA);                          // Set measurement range
      compass.setMeasurementMode(HMC5883L_CONTINOUS);                  // Set measurement mode
      compass.setDataRate(HMC5883L_DATARATE_30HZ);                     // Set data rate
      compass.setSamples(HMC5883L_SAMPLES_8);                          // Set number of samples averaged
      compass.setOffset(118, 473);                                      // Set calibration offset

      // Buzzer
      pinMode(Buzzer_pin, OUTPUT);

      // Set up pins
      pinMode(enc_l_pin, INPUT);
      pinMode(enc_r_pin, INPUT);


      // Set up interrupts
      attachInterrupt(digitalPinToInterrupt(enc_l_pin), countLeft, CHANGE);
      attachInterrupt(digitalPinToInterrupt(enc_r_pin), countRight, CHANGE);



user42015: I think you have 2 problems:

The used Hall sensor is an analog device, not a digital one. This means it will not output either Vcc or 0V, but instead an analog (continuous) voltage depending on the magnetic field. With zero magnetic field, it will output about half the supply voltage (in this case 2.5V, since Vcc is 5V for you). For analog signals pullups or pulldowns do not make sense. Digital pins have a hysteris, which means, that they will detect a LOW between 0V and 1.67V and a HIGH between 3.33V and 5V (see this answer). This is also called a Schmitt trigger. I assume, that you just want to measure, that the magnet comes near the sensor (so only one polarity matters). This means, that the voltage will stay - let's say - above 2.5V (depending on polarity) and only going from 2.5V to 5V and back. In this condition the pin state will stay high, since it is set high, but never reaches voltage low enough for setting it to low. No interrupt will be triggered. Depending on what you want and the next problem, you can instead use a comparator (which is a special peripheral of the microcontroller) to trigger the incrementation, when a specified threshold voltage is reached (this also mean it would trigger due to small changes around the threshold), or you can buy or build an external Schmitt trigger, where you can change the threshold voltages for LOW and HIGH changes.
Motors send out quite a bunch of electromagnetic noise, which can distort analog Signals nearby. Most likely the noise from the motors is high enough to falsely trigger a state change at the pin. Maybe you should look at the analog signal with an oscilloscope, which can show you, how much noise do you really have in this situation. There are many ways to reduce noise on an analog signal. One is to add a low pass filter to cancel out the mostly higher frequency noise. This only works, if the frequency of your signal is considerably lower (so that you can trim the low pass filter to let your signal pass).


From the picture I cannot see, how the magnets and the sensors are moving in the car. Be sure to measure the different voltages in the different states (magnet near sensor, magnet for away). If the sensor is too sensitive or your magnet too strong, you might end up with an even smaller voltage range, than the 2.5V, that you already have.

52245: <p><a href="https://i.stack.imgur.com/jcEE7.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/jcEE7.jpg" alt="enter image description here"></a>I am using a 4wd robotic car to measure straight distances. I have attached two encoders on the front two wheels to measure the distance and I am using the back two wheels to adjust the car and keep it driving straight by using a compass as a reference. The Problem is that when my program is executing the section that drives the back wheels this somehow triggers the interrupt and increments the number of ticks. What is causing this issue?</p>

<pre><code>volatile unsigned long enc_l = 0;
volatile unsigned long enc_r = 0;

void driveStraight(float drive_distance, int motor_power)
{
  Serial.print("\n");
  Serial.println("num_tick_l \t num_tick_r \t diff_l \t diff_r \t enc_1_prev \t enc_r_prev \t Power_l \t Power_r \t Power_a \t Power_b ");

  unsigned long num_ticks_l;
  unsigned long num_ticks_r;

  // Set initial motor power
  int power_l = motor_power;
  int power_r = motor_power;

  // Used to determine which way to turn to adjust
  unsigned long diff_l;
  unsigned long diff_r;

  // Reset encoder counts
  enc_l = 0;
  enc_r = 0;

  // Remember previous encoder counts
  unsigned long enc_l_prev = enc_l;
  unsigned long enc_r_prev = enc_r;

  // Calculate targer number of ticks
  float num_rev = (drive_distance * 10) / wheel_c;   // Convert to mm
  unsigned long target_count =  29; //num_rev * counts_per_rev;


  /*
    // Debug
    Serial.print("Driving for ");
    Serial.print(drive_distance);
    Serial.print(" cm(");
    Serial.print(target_count);
    Serial.print(" ticks) at ");
    Serial.print(motor_power);
    Serial.println(" Motor Power");
  */

  //Drive until on of the encoders reaches desired count
  while ((enc_l &lt; target_count) &amp;&amp; (enc_r &lt; target_count))
  {

    bluetooth();                                // if new bluetooth value received break from loop
    if (blueToothVal == 5) {
      break;                                    // If a 'Stop' Bluetooth command is received then break from the Loop
    }

    // Sample number of encoder ticks
    num_ticks_l = enc_l;
    num_ticks_r = enc_r;

    // Sample out current number of ticks
    Serial.print(num_ticks_l);
    Serial.print("  \t\t");
    Serial.print(num_ticks_r);

    // Drive
    drive(power_l, power_r);

    // Number of ticks counted since last time
    const int StraightDriveOffset = 1;                    // Increase this or even make it a negatie number to tweak the

    diff_l = num_ticks_l - enc_l_prev;                    // + StraightDriveOffset;
    diff_r = num_ticks_r - enc_r_prev;


    Serial.print("  \t\t");
    Serial.print(diff_l);
    Serial.print(" \t \t");
    Serial.print(diff_r);


    // Store current ticks counter for next time
    enc_l_prev = num_ticks_l;
    enc_r_prev = num_ticks_r;


    Serial.print("   \t \t");
    Serial.print(enc_l_prev);
    Serial.print(" \t \t");
    Serial.print(enc_r_prev);


    // If left is faster, slow it down and speed up right
    if ( diff_l &gt; diff_r) {
      power_l -= motor_offset;
      power_r += motor_offset;
    }

    // If right is faster, slow it down and speed up right
    if ( diff_l &lt; diff_r) {
      power_l += motor_offset;
      power_r -= motor_offset;
    }

    // Debugging
    Serial.print(" \t\t");
    Serial.print(power_l);
    Serial.print(" \t\t");
    Serial.println(power_r);


    // Brif pause to let motors respond
    delay(20);
  }

  StopCar();
  //Buzzer();
}

void drive(int power_a, int power_b)
{
  getCompass();                                                     // Update Compass Heading
  bluetooth();                                                      // Check to see if any Bluetooth commands have been sent

  if (blueToothVal == 5) {
    break; // If a Stop Bluetooth command ('5') is received then break from the Loop
  }

  // Constrain power to between -255 and 255
  power_a = constrain(power_a, -255, 255);
  power_b = constrain(power_b, -255, 255);

  if ( abs(desired_heading - compass_heading) &lt;= compass_dev )      // If the Desired Heading and the Compass Heading are within the compass deviation, X degrees of each other then Go Forward
    // otherwise find the shortest turn radius and turn left or right
  {
    // Left motor direction
    if ( power_a &lt; 0)
    {
      motor2.setSpeed(abs(power_a));       // Motor is the front left wheel
      motor2.run(BACKWARD);

    }
    else
    {
      motor2.setSpeed(abs(power_a));       // Motor is the front left wheel
      motor2.run(FORWARD);

    }

    // Right Motor direction
    if ( power_b &lt; 0)
    {
      motor4.setSpeed(abs(power_b));       // Motor is the front left wheel
      motor4.run(BACKWARD);

    }
    else
    {
      motor4.setSpeed(abs(power_b));       // Motor is the front left wheel
      motor4.run(FORWARD);

    }

  }

  else
  {
    int x = (desired_heading - 359);                          // x = the GPS desired heading - 360
    int y = (compass_heading - (x));                          // y = the Compass heading - x
    int z = (y - 360);                                        // z = y - 360

    if ((z &lt;= 180) &amp;&amp; (z &gt;= 0))                               // if z is less than 180 and not a negative value then turn left
    { // otherwise turn right
      motor1.setSpeed(190);
      motor3.setSpeed(190);
      motor1.run(BACKWARD);
      motor3.run(FORWARD);
    }
    else
    {
      motor1.setSpeed(190);
      motor3.setSpeed(190);
      motor1.run(FORWARD);
      motor3.run(BACKWARD);

    }
  }
}

void countLeft()
{
  enc_l ++;
}

void countRight()
{
  enc_r ++;
}
</code></pre>

<p>and this is what is on the setup function</p>

<pre><code>const int enc_l_pin = 18;
const int enc_r_pin = 19;

void setup()
    {
      Serial.begin(115200);                                            // Serial 0 is for communication with the computer
      Serial3.begin(9600);                                             // Serial 1 is for Bluetooth communication - DO NOT MODIFY - JY-MCU HC-06 v1.40

      Wire.begin();                                                    // Join I2C bus used for the HMC5883L compass
      compass.begin();                                                 // initialize the compass (HMC5883L)
      compass.setRange(HMC5883L_RANGE_1_3GA);                          // Set measurement range
      compass.setMeasurementMode(HMC5883L_CONTINOUS);                  // Set measurement mode
      compass.setDataRate(HMC5883L_DATARATE_30HZ);                     // Set data rate
      compass.setSamples(HMC5883L_SAMPLES_8);                          // Set number of samples averaged
      compass.setOffset(118, 473);                                      // Set calibration offset

      // Buzzer
      pinMode(Buzzer_pin, OUTPUT);

      // Set up pins
      pinMode(enc_l_pin, INPUT);
      pinMode(enc_r_pin, INPUT);


      // Set up interrupts
      attachInterrupt(digitalPinToInterrupt(enc_l_pin), countLeft, CHANGE);
      attachInterrupt(digitalPinToInterrupt(enc_r_pin), countRight, CHANGE);
</code></pre>

<p><a href="https://i.stack.imgur.com/utxSN.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/utxSN.png" alt="enter image description here"></a></p>
 42015: <p>I think you have 2 problems:</p>

<ol>
<li><p>The used Hall sensor is an analog device, not a digital one. This means it will not output either Vcc or 0V, but instead an analog (continuous) voltage depending on the magnetic field. With zero magnetic field, it will output about half the supply voltage (in this case 2.5V, since Vcc is 5V for you). For analog signals pullups or pulldowns do not make sense. Digital pins have a hysteris, which means, that they will detect a LOW between 0V and 1.67V and a HIGH between 3.33V and 5V (see <a href="https://arduino.stackexchange.com/questions/45665/how-does-arduino-digital-input-pin-measure-its-input-voltage">this answer</a>). This is also called a Schmitt trigger. I assume, that you just want to measure, that the magnet comes near the sensor (so only one polarity matters). This means, that the voltage will stay - let's say - above 2.5V (depending on polarity) and only going from 2.5V to 5V and back. In this condition the pin state will stay high, since it is set high, but never reaches voltage low enough for setting it to low. No interrupt will be triggered. Depending on what you want and the next problem, you can instead use a comparator (which is a special peripheral of the microcontroller) to trigger the incrementation, when a specified threshold voltage is reached (this also mean it would trigger due to small changes around the threshold), or you can buy or build an external Schmitt trigger, where you can change the threshold voltages for LOW and HIGH changes.</p></li>
<li><p>Motors send out quite a bunch of electromagnetic noise, which can distort analog Signals nearby. Most likely the noise from the motors is high enough to falsely trigger a state change at the pin. Maybe you should look at the analog signal with an oscilloscope, which can show you, how much noise do you really have in this situation. There are many ways to reduce noise on an analog signal. One is to add a low pass filter to cancel out the mostly higher frequency noise. This only works, if the frequency of your signal is considerably lower (so that you can trim the low pass filter to let your signal pass).</p></li>
</ol>

<hr>

<p>From the picture I cannot see, how the magnets and the sensors are moving in the car. Be sure to measure the different voltages in the different states (magnet near sensor, magnet for away). If the sensor is too sensitive or your magnet too strong, you might end up with an even smaller voltage range, than the 2.5V, that you already have.</p>
