Comparing the data for a gear motor in the code and oscilloscope

I am using this code to collect the data from the hall sensor and oscilloscope to compare if I am missing some data.
I have assign 1412 revolutions for the gear motor, this is for clockwise and counterclockwise.

While I start reading the data from the oscilloscope for counter wise the cycles are 1490 and for the clockwise, it is 1451.

How can I get more accurate data to compare the data im getting through the serial monitor and oscilloscope

//Define pin setup
#define motor_in1 7
#define motor_in2 8
#define motor_enA 9
#define sensorPin 2

volatile int half_revolutions = 0;
int revolutions_per_pos;

int pos = 0;

void setup() {
  // Set pin mode
  pinMode(motor_enA, OUTPUT);
  pinMode(motor_in1, OUTPUT);
  pinMode(motor_in2, OUTPUT);

  Serial.begin(115200);

  // Hallsensor connected to the interrupt pin (Pin 2 on Arduino Uno)
  attachInterrupt(digitalPinToInterrupt(sensorPin), magnet_detect, RISING);// attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

}

void loop() {
  // Run full cycle to each position and back to 0


  revolutions_per_pos = 706;
  move_amount(1);
  pos = 1;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-1);
  pos = 0;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(2);
  pos = 2;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-2);
  pos = 0;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(3);
  pos = 3;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-3);
  pos = 0;
  Serial.print(pos);
  delay(2000);


  revolutions_per_pos = 706;
  move_amount(1);
  pos = 4;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-1);
  pos = 0;
  Serial.print(pos);
  delay(2000);


  revolutions_per_pos = 706;
  move_amount(2);
  pos = 5;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-2);
  pos = 0;
  Serial.print(pos);
  delay(2000);



  revolutions_per_pos = 706;
  move_amount(-3);
  pos = 6;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(3);
  pos = 0;
  Serial.print(pos);
  delay(2000);

}

void magnet_detect() {
  half_revolutions++;
}

void move_amount(int no_pos) {
  half_revolutions = 0;
  if (no_pos < 0) {
    // Set rotation direction
    digitalWrite(motor_in1, HIGH);
    digitalWrite(motor_in2, LOW);
    no_pos *= -1;
  }
  else {
    // Set rotation direction
    digitalWrite(motor_in1, LOW);
    digitalWrite(motor_in2, HIGH);
  }

  while (half_revolutions < (no_pos * (2 * revolutions_per_pos))) {
    Serial.println(half_revolutions);
    analogWrite(motor_enA, 100);
  }
  analogWrite(motor_enA, 0);
}

I am using this code to collect the data from the hall sensor and oscilloscope to compare if I am missing some data.
I have assign 1412 revolutions for the gear motor, this is for clockwise and counterclockwise.

While I start reading the data from the oscilloscope for counter wise the cycles are 1490 and for the clockwise, it is 1451.

How can I get more accurate data from the gear motor and hall sensor to compare it oscilloscope

//Define pin setup
#define motor_in1 7
#define motor_in2 8
#define motor_enA 9
#define sensorPin 2

volatile int half_revolutions = 0;
int revolutions_per_pos;

int pos = 0;

void setup() {
  // Set pin mode
  pinMode(motor_enA, OUTPUT);
  pinMode(motor_in1, OUTPUT);
  pinMode(motor_in2, OUTPUT);

  Serial.begin(115200);

  // Hallsensor connected to the interrupt pin (Pin 2 on Arduino Uno)
  attachInterrupt(digitalPinToInterrupt(sensorPin), magnet_detect, RISING);// attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

}

void loop() {
  // Run full cycle to each position and back to 0


  revolutions_per_pos = 706;
  move_amount(1);
  pos = 1;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-1);
  pos = 0;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(2);
  pos = 2;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-2);
  pos = 0;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(3);
  pos = 3;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-3);
  pos = 0;
  Serial.print(pos);
  delay(2000);


  revolutions_per_pos = 706;
  move_amount(1);
  pos = 4;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-1);
  pos = 0;
  Serial.print(pos);
  delay(2000);


  revolutions_per_pos = 706;
  move_amount(2);
  pos = 5;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-2);
  pos = 0;
  Serial.print(pos);
  delay(2000);



  revolutions_per_pos = 706;
  move_amount(-3);
  pos = 6;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(3);
  pos = 0;
  Serial.print(pos);
  delay(2000);

}

void magnet_detect() {
  half_revolutions++;
}

void move_amount(int no_pos) {
  half_revolutions = 0;
  if (no_pos < 0) {
    // Set rotation direction
    digitalWrite(motor_in1, HIGH);
    digitalWrite(motor_in2, LOW);
    no_pos *= -1;
  }
  else {
    // Set rotation direction
    digitalWrite(motor_in1, LOW);
    digitalWrite(motor_in2, HIGH);
  }

  while (half_revolutions < (no_pos * (2 * revolutions_per_pos))) {
    Serial.println(half_revolutions);
    analogWrite(motor_enA, 100);
  }
  analogWrite(motor_enA, 0);
}

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

Perhaps the motor coasts a bit after you remove power?

where ever you play with half_revolutions outside the ISR, you should ensure this is in a critical section (protected against Interrupts) as an interrupt during the loop could set you off - especially as your variable is on 2 bytes.

So I would not trust blindly the data printed by your program

The motor is in continuously test so I don't remove the power.

How can I fix this issue then would you please explain it further. It is true during the loop it can set it off.

Would you help me how to fix it in the coding as I am not good at programming

Hi,
Ah... you are trying to make the ANALOG and DIGITAL worlds agree with each other. A daunting task.

Tell us more (photo?) of your setup. How is the magnetic sensor arranged? Hmm.. Is the oscilloscope able to count pulses?? Sorry, I don't understand the details...

Please Pardon my presumption, but I wanted to try to understand the code. Also, please use CODE tags to show your work, and use Auto Format.

CODE:

//Define pin setup
#define motor_in1 7
#define motor_in2 8
#define motor_enA 9
#define sensorPin 2

volatile int half_revolutions = 0;
int revolutions_per_pos;

int pos = 0;

void setup()
{
  // Set pin mode
  pinMode(motor_enA, OUTPUT);
  pinMode(motor_in1, OUTPUT);
  pinMode(motor_in2, OUTPUT);

  Serial.begin(115200);

  // Hallsensor connected to the interrupt pin (Pin 2 on Arduino Uno)
  attachInterrupt(digitalPinToInterrupt(sensorPin), magnet_detect, RISING);//   attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

}// END SETUP


void loop()
{
  // Run full cycle to each position and back to 0


  revolutions_per_pos = 706;
  move_amount(1);
  pos = 1;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-1);
  pos = 0;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(2);
  pos = 2;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-2);
  pos = 0;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(3);
  pos = 3;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-3);
  pos = 0;
  Serial.print(pos);
  delay(2000);


  revolutions_per_pos = 706;
  move_amount(1);
  pos = 4;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-1);
  pos = 0;
  Serial.print(pos);
  delay(2000);


  revolutions_per_pos = 706;
  move_amount(2);
  pos = 5;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(-2);
  pos = 0;
  Serial.print(pos);
  delay(2000);



  revolutions_per_pos = 706;
  move_amount(-3);
  pos = 6;
  Serial.print(pos);
  delay(2000);

  revolutions_per_pos = 706;
  move_amount(3);
  pos = 0;
  Serial.print(pos);
  delay(2000);

} // END OF LOOP

//--------( USER WRITTEN FUNCTIONS )--------------------

void magnet_detect()
{
  half_revolutions++;
}



void move_amount(int no_pos)
{
  half_revolutions = 0;
  if (no_pos < 0)
  {
    // Set rotation direction
    digitalWrite(motor_in1, HIGH);
    digitalWrite(motor_in2, LOW);
    no_pos *= -1;
  }
  else
  {
    // Set rotation direction
    digitalWrite(motor_in1, LOW);
    digitalWrite(motor_in2, HIGH);
  }

  while (half_revolutions < (no_pos * (2 * revolutions_per_pos)))
  {
    Serial.println(half_revolutions);
    analogWrite(motor_enA, 100);
  }
  analogWrite(motor_enA, 0);
}

when you do maths or take decision based on half_revolutions, do those on a local temporary copy that you obtain in a protected section using cli() and sei() (or noInterrupts() and interrupts() which are basically the same thing in plain english).

noInterrupts();
int hr_local_copy = half_revolutions;
interrupts();
// use hr_local_copy for what you want to do, this way it does not change from under you

also depending how fast your motor goes, an int might not be the best variable to hold the data.

I have added the lines, but it's giving me an error, Would you please check the whole code!

Cheers mate

//Define pin setup
#define motor_in1 7
#define motor_in2 8
#define motor_enA 9
#define sensorPin 2

volatile int half_revolutions = 0;
int revolutions_per_pos;

int pos = 0;

void setup() {
 // Set pin mode
 pinMode(motor_enA, OUTPUT);
 pinMode(motor_in1, OUTPUT);
 pinMode(motor_in2, OUTPUT);

noInterrupts();
int hr_local_copy = half_revolutions;
interrupts();
// use hr_local_copy for what you want to do, this way it does not change from under yo

 Serial.begin(115200);

 // Hallsensor connected to the interrupt pin (Pin 2 on Arduino Uno)
 attachInterrupt(digitalPinToInterrupt(sensorPin), magnet_detect, RISING);// attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

}

void loop() {
 // Run full cycle to each position and back to 0



 revolutions_per_pos = 706;
 move_amount(1);
 pos = 1;
 Serial.print(pos);
 delay(2000);

 revolutions_per_pos = 706;
 move_amount(-1);
 pos = 0;
 Serial.print(pos);
 delay(2000);

 revolutions_per_pos = 706;
 move_amount(2);
 pos = 2;
 Serial.print(pos);
 delay(2000);

 revolutions_per_pos = 706;
 move_amount(-2);
 pos = 0;
 Serial.print(pos);
 delay(2000);

 revolutions_per_pos = 706;
 move_amount(3);
 pos = 3;
 Serial.print(pos);
 delay(2000);

 revolutions_per_pos = 706;
 move_amount(-3);
 pos = 0;
 Serial.print(pos);
 delay(2000);


 revolutions_per_pos = 706;
 move_amount(1);
 pos = 4;
 Serial.print(pos);
 delay(2000);

 revolutions_per_pos = 706;
 move_amount(-1);
 pos = 0;
 Serial.print(pos);
 delay(2000);


 revolutions_per_pos = 706;
 move_amount(2);
 pos = 5;
 Serial.print(pos);
 delay(2000);

 revolutions_per_pos = 706;
 move_amount(-2);
 pos = 0;
 Serial.print(pos);
 delay(2000);



 revolutions_per_pos = 706;
 move_amount(-3);
 pos = 6;
 Serial.print(pos);
 delay(2000);

 revolutions_per_pos = 706;
 move_amount(3);
 pos = 0;
 Serial.print(pos);
 delay(2000);

}

void magnet_detect() {
 half_revolutions++;
}

void move_amount(int no_pos) {
 half_revolutions = 0;
 if (no_pos < 0) {
   // Set rotation direction
   digitalWrite(motor_in1, HIGH);
   digitalWrite(motor_in2, LOW);
   no_pos *= -1;
 }
 else {
   // Set rotation direction
   digitalWrite(motor_in1, LOW);
   digitalWrite(motor_in2, HIGH);
 }

 while (half_revolutions < (no_pos * (2 * revolutions_per_pos))) {
   Serial.println(half_revolutions);
   analogWrite(motor_enA, 100);
 }
 analogWrite(motor_enA, 0);
}

If the speed can affect the data what will be the best option to get the data. How accurate the data will be from the hall sensor and then can see the same data on the oscilloscope

I am trying to compare the data I received from the hall sensor to an oscilloscope. I have attached the file in which we can see the data from the oscilloscope.

New Microsoft Word Document.zip (370 KB)

noInterrupts();
int hr_local_copy = half_revolutions;
interrupts();

needs to go in the loop or functions where you use the half_revolutions value - not the setup

it's about capturing a value that will stay stable whilst half_revolutions might evolve without you knowing

It's giving me error would you please add these lines in the coding.

It is not uncommon for DC motors to run slightly faster in one direction vs the other, say you set analogWrite(254), your motor might run 2000 RPM CW and 2060 CCW, a 3% difference. You might try to equalize by setting the faster direction 3% slower:

if(dir == CW)
  analogWrite(speed); 
else
  analogWrite(speed * 0.97);

would you help me to add this to the coding, I don't know how to add this part to it.

something like this may be?

//Define pin setup
#define motor_in1 7
#define motor_in2 8
#define motor_enA 9
#define sensorPin 2

volatile unsigned int half_revolutions = 0;
const unsigned int revolutions_per_pos = 706u;

void magnet_detect() {
  half_revolutions++;
}

void setup() {
  // Set pin mode
  pinMode(motor_enA, OUTPUT);
  pinMode(motor_in1, OUTPUT);
  pinMode(motor_in2, OUTPUT);

  Serial.begin(115200);

  // Hallsensor connected to the interrupt pin (Pin 2 on Arduino Uno)
  attachInterrupt(digitalPinToInterrupt(sensorPin), magnet_detect, RISING);// attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

}

void loop() {
  // Run full cycle to each position and back to 0
  move_amount(1);
  Serial.println(1);
  delay(2000);

  move_amount(-1);
  Serial.println(0);
  delay(2000);

  move_amount(2);
  Serial.println(2);
  delay(2000);

  move_amount(-2);
  Serial.println(0);
  delay(2000);

  move_amount(3);
  Serial.println(3);
  delay(2000);

  move_amount(-3);
  Serial.println(0);
  delay(2000);

  move_amount(1);
  Serial.println(4);
  delay(2000);

  move_amount(-1);
  Serial.println(0);
  delay(2000);

  move_amount(2);
  Serial.println(5);
  delay(2000);

  move_amount(-2);
  Serial.println(0);
  delay(2000);

  move_amount(-3);
  Serial.println(6);
  delay(2000);

  move_amount(3);
  Serial.println(0);
  delay(2000);
}


void move_amount(int no_pos)
{
  unsigned int hr_local_copy;
  unsigned int count;

  // Set rotation direction
  if (no_pos < 0) {
    digitalWrite(motor_in1, HIGH);
    digitalWrite(motor_in2, LOW);
    no_pos = -no_pos;
  } else {
    // Set rotation direction
    digitalWrite(motor_in1, LOW);
    digitalWrite(motor_in2, HIGH);
  }

  count = no_pos * 2 * revolutions_per_pos;

  noInterrupts();
  half_revolutions = 0;
  hr_local_copy = 0;
  interrupts();

  // start motor
  analogWrite(motor_enA, 100);

  while (hr_local_copy < count) {
    Serial.println(hr_local_copy);
    noInterrupts();
    hr_local_copy = half_revolutions;
    interrupts();
  }

  // stop motor (but it might keep spinning)
  analogWrite(motor_enA, 0);

  noInterrupts();
  hr_local_copy = half_revolutions;
  Serial.println(hr_local_copy);
  interrupts();
}

Thank you so much. would you please help me to add a few more lines to it! to the same code.

if(dir == CW)
analogWrite(speed);
else
analogWrite(speed * 0.97);

where do you want this being added?

to control the speed for the Clockwise, that it should be 3% less than Anti-clock wise

Hi,

The fun part is a little later, when you use the sensor output to CONTROL the DC motor so it goes exactly as you want. But you have the right basics, including good instrumentation.

In this type of experiment, think about having your CODE use a digital output to mark specific events in the code, and also look at that digital pin with your oscilloscope. I have done things (with a multichannel logic analyzer) with several code timing points along with signals from the hardware being tested. If there is a known occasional error you are looking for, many logic analyzers can trigger on a specific pattern. Some high end scopes also have a word recognizer add-on.

Some of us are in love with Test Equipment :slight_smile: