Actualmente estoy trabajando con la interfaz de un motor paso a paso (bipolar de 4 pines) y proporcionándole la señal de entrada adecuada, de manera que acelere y decelere correctamente. Recientemente también a través de una nota de aplicación por atmel (enlace), que aborda este problema y también proporciona el código para programando un temporizador para hacerlo, que está disponible en github (github) .. (Perfecto) Como ya tengo el controlador, no necesito darle una señal de 4 pines (A +, A-, B-, B +) sino solo una señal modulada por impulsos, con un aumento y una disminución de la frecuencia para una cantidad determinada de pasos .
Cambié la rutina ISR, ya que parecía ser donde parecía que se generaba la señal de paso, y la cambié para cambiar el estado de step_pin cada vez que ocurría una interrupción, recreando así una señal PWM. El problema es que la señal no se parece a eso, y si elimino Serial.print()
, la señal se convierte en una señal con forma de diente de sierra.
ISR(TIMER1_COMPA_vect) { //Mantieneelsiguienteperiododedemora. unsignedintnew_step_delay;
//Rememberthelaststepdelayusedwhenaccelrating.staticintlast_accel_delay;//Countingstepswhenmoving.staticunsignedintstep_count=0;//Keeptrackofremainderfromnew_step-delaycalculationtoincraseaccurancystaticunsignedintrest=0;OCR1A=profile.step_delay;Serial.print('\n');Serial.print("step_delay: ");
Serial.println(profile.step_delay);
Serial.print('\n');
switch (profile.run_state)
{
case STOP:
step_count = 0;
rest = 0;
TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer, No clock source
break;
case ACCEL:
digitalWrite(step_pin,!digitalRead(step_pin));
//delay(1);
//digitalWrite(step_pin,LOW);
step_count++;
profile.accel_count++;
new_step_delay = profile.step_delay - (((2 * (long)profile.step_delay) + rest) / (4 * profile.accel_count + 1));
rest = ((2 * (long)profile.step_delay) + rest) % (4 * profile.accel_count + 1);
// Chech if we should start decelration.
if (step_count >= profile.decel_start)
{
profile.accel_count = profile.decel_val;
profile.run_state = DECEL;
}
// Chech if we hitted max speed.
else if (new_step_delay <= profile.min_time_delay)
{
last_accel_delay = new_step_delay;
new_step_delay = profile.min_time_delay;
rest = 0;
profile.run_state = RUN;
}
break;
case RUN:
digitalWrite(step_pin,!digitalRead(step_pin));
//delay(1);
//digitalWrite(step_pin,LOW);
step_count++;
new_step_delay = profile.min_time_delay;
// Chech if we should start decelration.
if (step_count >= profile.decel_start)
{
profile.accel_count = profile.decel_val;
// Start decelration with same delay as accel ended with.
new_step_delay = last_accel_delay;
profile.run_state = DECEL;
}
break;
case DECEL:
digitalWrite(step_pin,!digitalRead(step_pin));
step_count++;
profile.accel_count++;
new_step_delay = profile.step_delay - (((2 * (long)profile.step_delay) + rest)/(4 * profile.accel_count + 1));
rest = ((2 * (long)profile.step_delay)+rest)%(4 * profile.accel_count + 1);
// Check if we at last step
if(profile.accel_count >= 0)
{
profile.run_state = STOP;
}
break;
}
profile.step_delay = new_step_delay;
}
La rutina ISR está aquí ..
ISR(TIMER1_COMPA_vect)
{
// Holds next delay period.
unsigned int new_step_delay;
// Remember the last step delay used when accelrating.
static int last_accel_delay;
// Counting steps when moving.
static unsigned int step_count = 0;
// Keep track of remainder from new_step-delay calculation to incrase accurancy
static unsigned int rest = 0;
OCR1A = profile.step_delay;
Serial.print('\n');
Serial.print("step_delay: ");
Serial.println(profile.step_delay);
Serial.print('\n');
switch (profile.run_state)
{
case STOP:
step_count = 0;
rest = 0;
TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer, No clock source
break;
case ACCEL:
digitalWrite(step_pin,!digitalRead(step_pin));
//delay(1);
//digitalWrite(step_pin,LOW);
step_count++;
profile.accel_count++;
new_step_delay = profile.step_delay - (((2 * (long)profile.step_delay) + rest) / (4 * profile.accel_count + 1));
rest = ((2 * (long)profile.step_delay) + rest) % (4 * profile.accel_count + 1);
// Chech if we should start decelration.
if (step_count >= profile.decel_start)
{
profile.accel_count = profile.decel_val;
profile.run_state = DECEL;
}
// Chech if we hitted max speed.
else if (new_step_delay <= profile.min_time_delay)
{
last_accel_delay = new_step_delay;
new_step_delay = profile.min_time_delay;
rest = 0;
profile.run_state = RUN;
}
break;
case RUN:
digitalWrite(step_pin,!digitalRead(step_pin));
//delay(1);
//digitalWrite(step_pin,LOW);
step_count++;
new_step_delay = profile.min_time_delay;
// Chech if we should start decelration.
if (step_count >= profile.decel_start)
{
profile.accel_count = profile.decel_val;
// Start decelration with same delay as accel ended with.
new_step_delay = last_accel_delay;
profile.run_state = DECEL;
}
break;
case DECEL:
digitalWrite(step_pin,!digitalRead(step_pin));
step_count++;
profile.accel_count++;
new_step_delay = profile.step_delay - (((2 * (long)profile.step_delay) + rest)/(4 * profile.accel_count + 1));
rest = ((2 * (long)profile.step_delay)+rest)%(4 * profile.accel_count + 1);
// Check if we at last step
if(profile.accel_count >= 0)
{
profile.run_state = STOP;
}
break;
}
profile.step_delay = new_step_delay;
}
main
#include "speed_profile.h"
void setup() {
// put your setup code here, to run once:
cli();
Serial.begin(230400);
output_pin_setup();
timer1_setup();
sei();
}
void loop()
{
// put your main code here, to run repeatedly:
Serial.print("start");
Serial.print('\n');
int motor_steps = 10000;
// Accelration to use.
int motor_acceleration = 10;
// Deceleration to use.
int motor_deceleration = 10;
// Speed to use.
int motor_speed = 500;
compute_speed_profile(motor_steps, motor_acceleration, motor_deceleration, motor_speed);
Serial.print("NewRound");
Serial.print('\n');
}
output_pin_setup ();
void output_pin_setup()
{
pinMode(en_pin,OUTPUT);
pinMode(dir_pin,OUTPUT);
pinMode(step_pin,OUTPUT);
}
El resto si el código es el mismo que antes, y está disponible en github.
Sé que estoy haciendo algo mal aquí? pero ¿cómo creo la señal deseada?
Aquí está el esquema de la configuración:
Editar - Configurar output_pins () Yo uso la función setup_output_pins () Para configurar los pines de salida, he leído en algún lugar que no era una buena idea, ya que el arduino necesita algo de tiempo para establecerse o algo así.