Optical motor speed measure rising time

Hi everyone. I connected an "Infrared Optical Optocoupler Module" sensor with a perforated disk to a stepper. I created this code to calculate the speed of the stepper motor by reading the number of times the IR signal passes through the slots of the encoder wheel. I used "attachinterrupt" and it works pretty well. specifically I give a constant speed to the stepper motor and then separately use this code to count the speed:


#include <AccelStepper.h>
#define PIN_DIR    25
#define PIN_STEP   33 

volatile int count = 0;
unsigned long t1;
float vel;

AccelStepper stepper(1, PIN_STEP, PIN_DIR);
  
void pulse() {
  count++;  
}

void setup() {
  stepper.setMaxSpeed(5000);
   
   stepper.setSpeed(4400);	
   
  Serial.begin(115200);

  pinMode(22, INPUT); 
  attachInterrupt(digitalPinToInterrupt(22), pulse, RISING);
}
// 500-2= 10*100
void loop() {

     stepper.runSpeed();

  if ((millis() - t1) > 10) {
    vel = (float)count * 1.0;

    Serial.print("vel: ");
    Serial.print(vel);
    Serial.print(" Time: ");
    Serial.println(millis()); 
    
    count = 0;
    t1 = millis(); 
  }
}

now I would instead need to create an array where to insert a number of samples in micros() to obtain the number of Rising (and possibly also Falling) recorded by the sensor, and catalog them with the delta-T between an ascending and falling. so as to calculate the variation of the delta-T between each variation of the signal and see how long it takes the engine from when it is stopped to when it reaches the reference speed. Do you have any suggestions on how I can modify this code?

why do you need to measure the rise time? why not measure speed and the time it takes the speed to reach your target?

because the engine is too fast to reach speed, also it is for an experiment on the sensor requested by my professor. he asked me to measure the number of delta T which varies until it is almost constant at steady state. I was wondering if anyone can do this using AttachInterrupt.

so if you need to measure the rise time. don't you need to capture the time just before it starts to rise and the time it completes rising?

to do this, wouldn't you need to use an analog input to sample the input? however, i doubt the analog input is fast enough to do this.

the point is not how long the rising lasts, but the time distance between one rising and another recorded by the IR sensor. as input I actually have a cycle that every second commands the stepper motor to speed 0 and after one second speed 200. in the transition from 0 to 200 I want to see when the number of steps settles to normal. then calculating in number of steps.

schematically the signal variation in the IR would be like this as long as the recorded rising must be constant over time (in terms of pulses per second).

sorry, i misunderstood what you meant by delta-T. seems that you just want to measure the time between events.

no doubt you can count the # of events. and from each event (after the first) you can calculate the speed -- rpm = 60 / (t * N), where N is the # of events per rotation

but it sounds you don't just need to the # of events until it reaches the target speed, but need to monitor the speed to determine when it is stable, presumably varies by < some thresh

So basically you want to record the rate of acceleration that is being generated by the AccelStepper library?

yes, I would also later like to understand how to adjust the acceleration to be given to the engine to go from zero to a speed value of 200 more or less quickly.

I was also wondering if this draft code is correct:

// Dichiarazione delle variabili
volatile unsigned long lastChangeTime = 0;
volatile unsigned long changeDuration = 0;
volatile bool isFirstChange = true;

// Definizione della funzione di interrupt
void onChange() {
  unsigned long currentTime = micros();
  
  if (!isFirstChange) {
    changeDuration = currentTime - lastChangeTime;
  }
  lastChangeTime = currentTime;
  isFirstChange = false;
}

void setup() {
  pinMode(22, INPUT);
  attachInterrupt(digitalPinToInterrupt(22), onChange, CHANGE);
  Serial.begin(115200); // Inizializzazione della comunicazione seriale
}

void loop() {
  // Se è stato registrato un nuovo cambiamento, stampa la durata del precedente intervallo
  if (changeDuration > 0) {
    Serial.print("Change duration: ");
    Serial.print(changeDuration);
    Serial.println(" microseconds");
    changeDuration = 0; // Resetta la durata del cambiamento
  }
  // Altre operazioni nel loop se necessario
}

the problem is that I tried to do two tests going from 0 to 400 and from 0 to 4000 as speed, the delta ts that I record seem identical, it is almost useless. advice?

test motor:


`15:33:52.172 -> Velocita impostata a: 4000

15:33:52.172 -> Change duration: 20542543 microseconds

15:33:52.172 -> Change duration: 6439 microseconds

15:33:52.172 -> Change duration: 3706 microseconds

15:33:52.172 -> Change duration: 6211 microseconds

15:33:52.172 -> Change duration: 3811 microseconds

15:33:52.172 -> Change duration: 6227 microseconds

15:33:52.218 -> Change duration: 3858 microseconds

15:33:52.218 -> Change duration: 6231 microseconds

15:33:52.218 -> Change duration: 3866 microseconds

15:33:53.378 -> Velocita impostata a: 0

15:34:28.452 -> Velocita impostata a: 400
15:34:28.494 -> Change duration: 35125126 microseconds
15:34:28.494 -> Change duration: 37098 microseconds
15:34:28.577 -> Change duration: 60829 microseconds
15:34:28.623 -> Change duration: 37374 microseconds
15:34:28.656 -> Change duration: 60786 microseconds
15:34:28.689 -> Change duration: 37005 microseconds
15:34:28.780 -> Change duration: 60640 microseconds
15:34:28.827 -> Change duration: 38769 microseconds
15:34:28.873 -> Change duration: 60355 microseconds
15:34:28.920 -> Change duration: 37698 microseconds
15:34:28.967 -> Change duration: 60564 microseconds
15:34:29.014 -> Change duration: 39222 microseconds
15:34:29.046 -> Change duration: 60624 microseconds
15:34:29.375 -> Velocita impostata a: 0`

if the acceleration is the same for both speeds, at least the beginning values will be the same and it's the later ones that will be different

it's not making sense that the values are steadily decreasing. one reason may be there is not a single increment in count for each print.

Does not provide acceleration, you have not specified acceleration in your program.

Look here:
https://hackaday.io/project/183279-accelstepper-the-missing-manual

consider capturing the data and then printing it
looks like 350 long samples can fit on an UNO
don't know # of events / rev.

(please post data)

#include <AccelStepper.h>

#define PIN_DIR    25
#define PIN_STEP   33
AccelStepper stepper(1, PIN_STEP, PIN_DIR);

volatile int count = 0;

//  600 rpm =  10 rev/sec => 100 msec/rev
// 6000 rpm = 100 rev/sec =>  10 msec/rev
const int BufSize = 350;
unsigned long buf [BufSize];

void pulse() {
    if (count < BufSize)
        buf [count++] = micros();
}

void loop() {
    stepper.runSpeed();

    if (count == BufSize)  {
        for (int n = 0; n < count; n++) {
            Serial.print (n);
            Serial.print (" ");
            Serial.println (buf [n]);
        }
        count++;    // no longer == BufSize
    }
}

void setup() {
    stepper.setMaxSpeed(5000);
    stepper.setSpeed(4400);

    Serial.begin(115200);

    pinMode(22, INPUT);
    attachInterrupt(digitalPinToInterrupt(22), pulse, RISING);
}

I'll try this tomorrow afternoon, thanks, let's hope for the best :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.