为什么 arduino 忽略函数调用?
Why is the arduino ignoring a function call?
我目前运行我的arduino上有这个程序..
main.ino
#include "speed_profile.h"
void setup() {
// put your setup code here, to run once:
output_pin_setup();
cli();
timer1_setup();
sei();
}
void loop()
{
//int motor_steps = 23400;//-9600; //23400 - 100%
// Accelration to use.
//int motor_acceleration = 500;//500;
// Deceleration to use.
//int motor_deceleration = 500;//500;
// Speed to use.
//int motor_speed = 1000; // 1000
init_tipper_position();
compute_speed_profile(23400, 500, 500, 1000);
}
并且出于某种原因没有执行 init_tipper_position
,看起来像这样。
void init_tipper_position()
{
digitalWrite(en_pin, HIGH);
delay(1);
digitalWrite(dir_pin, LOW);
delay(1);
while((PINB & (0 << 2)))
{
digitalWrite(step_pin, HIGH);
delayMicroseconds(100);
digitalWrite(step_pin, LOW);
delayMicroseconds(100);
}
digitalWrite(en_pin, LOW);
}
我知道由于以下原因肯定会跳过。
1) 我正在使用的硬件没有任何反应。它应该
移动一个移动直到传感器被激活,但这并没有发生。
如果enable pin为高,是不是电机就不能动了,
在这种情况下是可能的
我有一个逻辑分析仪,
我可以确定输出范围,这表明启用不高。
那么为什么程序会跳过那部分功能。
应该注意的是,如果我从 main 中删除该函数,该函数将起作用。
代码中用到的所有函数都可以在.cpp文件中看到。 profile 只是一个跟踪一些变量的结构。
.cpp
#include "speed_profile.h"
volatile speed_profile profile;
ros::NodeHandle_<ArduinoHardware, 1, 2, 125, 125> nh;
//ros::NodeHandle nh;
std_msgs::Int8 status_step_count;
std_msgs::Int8 status_tipper_availability;
ros::Publisher chatter_status("tipper_status", &status_step_count);
ros::Publisher chatter_availabilty("tipper_availability", &status_tipper_availability);
volatile bool global_state = false;
int received_data = 0;
void call_back_control( const std_msgs::Empty & msg)
{
global_state = true;
received_data = (10 *23400.0)/100.0; // Converts input to motor_steps.
}
ros::Subscriber<std_msgs::Empty> sub_control("tipper_control", &call_back_control );
void output_pin_setup()
{
pinMode(en_pin, OUTPUT);
pinMode(dir_pin, OUTPUT);
pinMode(step_pin, OUTPUT);
pinMode(slot_sensor_pin,INPUT_PULLUP);
nh.initNode();
nh.advertise(chatter_status);
nh.advertise(chatter_availabilty);
nh.subscribe(sub_control);
//nh.subscribe(sub_command);
profile.current_step_position = 0;
delay(10);
nh.getHardware()->setBaud(57600);
}
void init_tipper_position()
{
digitalWrite(en_pin, HIGH);
delay(1);
digitalWrite(dir_pin, LOW);
delay(1);
while((PINB & (0 << 2)))
{
digitalWrite(step_pin, HIGH);
delayMicroseconds(100);
digitalWrite(step_pin, LOW);
delayMicroseconds(100);
}
digitalWrite(en_pin, LOW);
}
void timer1_setup()
{
// Tells what part of speed ramp we are in.
profile.run_state = STOP;
// Timer/Counter 1 in mode 4 CTC (Not running).
TCCR1B = (1 << WGM12);
// Timer/Counter 1 Output Compare A Match Interrupt enable.
TIMSK1 = (1 << OCIE1A);
}
void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed)
{
while (global_state == false)
{
//do nothing
status_step_count.data = ((float)(profile.current_step_position / 23400.0)) * 100.0; //map(profile.current_step_position,0,23400,0,100); // could be expensive -- Nice flowing is only available with float
status_tipper_availability.data = 1;
chatter_status.publish( &status_step_count);
chatter_availabilty.publish(&status_tipper_availability);
nh.spinOnce();
}
digitalWrite(en_pin, HIGH);
delay(1);
signed int move_steps;
if(received_data > profile.current_step_position) // Compares whether received percentage (converted to motor_steps) is greater or smaller than current_step_position.
{
profile.dir = CCW;
//motor_steps = -motor_steps;
move_steps = profile.current_step_position - received_data;
digitalWrite(dir_pin, HIGH);
}
else
{
profile.dir = CW;
move_steps = profile.current_step_position - received_data;
digitalWrite(dir_pin, LOW);
}
delay(1);
computation_of_speed_profile(move_steps, motor_accel, motor_decel, motor_speed); // Computes constants for profile..
OCR1A = 10;
// Set Timer/Counter to divide clock by 8
TCCR1B |= ((0 << CS12) | (1 << CS11) | (0 << CS10));
while (global_state == true)
{
status_step_count.data = ((float)(profile.current_step_position / 23400.0)) * 100.0; //map(profile.current_step_position,0,23400,0,100);
status_tipper_availability.data = 0;
chatter_availabilty.publish(&status_tipper_availability);
chatter_status.publish( &status_step_count);
nh.spinOnce();
//delay(100);
}
}
ISR(TIMER1_COMPA_vect)
{
// Holds next delay period.
unsigned int new_first_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.first_step_delay;
switch (profile.run_state)
{
case STOP:
step_count = 0;
global_state = false;
rest = 0;
TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer, No clock source
break;
case ACCEL:
PORTB ^= _BV(PB3); // Toggles the step_pin
step_count++;
if (profile.dir == CCW)
{
profile.current_step_position++;
}
else
{
profile.current_step_position--;
}
profile.accel_count++;
new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest) / (4 * profile.accel_count + 1));
rest = ((2 * (long)profile.first_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_length;
profile.run_state = DECEL;
}
// Chech if we hitted max speed.
else if (new_first_step_delay <= profile.min_time_delay)
{
last_accel_delay = new_first_step_delay;
new_first_step_delay = profile.min_time_delay;
rest = 0;
profile.run_state = RUN;
}
break;
case RUN:
PORTB ^= _BV(PB3); // Toggles the step_pin
step_count++;
if (profile.dir == CCW)
{
profile.current_step_position++;
}
else
{
profile.current_step_position--;
}
new_first_step_delay = profile.min_time_delay;
// Chech if we should start decelration.
if (step_count >= profile.decel_start)
{
profile.accel_count = profile.decel_length;
// Start decelration with same delay as accel ended with.
new_first_step_delay = last_accel_delay;
profile.run_state = DECEL;
}
break;
case DECEL:
PORTB ^= _BV(PB3); // Toggles the step_pin
step_count++;
if (profile.dir == CCW)
{
profile.current_step_position++;
}
else
{
profile.current_step_position--;
}
profile.accel_count++;
new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest) / (4 * profile.accel_count + 1));
rest = ((2 * (long)profile.first_step_delay) + rest) % (4 * profile.accel_count + 1);
// Check if we at last step
if (profile.accel_count >= 0)
{
digitalWrite(en_pin, !digitalRead(en_pin));
profile.run_state = STOP;
}
break;
}
profile.first_step_delay = new_first_step_delay;
}
.h 文件
/*
* Contains the class concerning with calculating the proper speed profile
* for accelerating and decelerating the stepper motor.
*
*/
#ifndef speed_profile_h
#define speed_profile_h
#include <Arduino.h>
#include <ros.h>
#include <std_msgs/Int8.h>
#include <std_msgs/Empty.h>
// Timer/Counter 1 running on 3,686MHz / 8 = 460,75kHz (2,17uS). (T1-FREQ 460750)
//#define T1_FREQ 460750
#define T1_FREQ 1382400
//! Number of (full)steps per round on stepper motor in use.
#define FSPR 1600
// Maths constants. To simplify maths when calculating in compute_speed_profile().
#define ALPHA (2*3.14159/FSPR) // 2*pi/spr
#define A_T_x100 ((long)(ALPHA*T1_FREQ*100)) // (ALPHA / T1_FREQ)*100
#define T1_FREQ_148 ((int)((T1_FREQ*0.676)/100)) // divided by 100 and scaled by 0.676
#define A_SQ (long)(ALPHA*2*10000000000) // ALPHA*2*10000000000
#define A_x20000 (int)(ALPHA*20000) // ALPHA*20000
// Speed ramp states
#define STOP 0
#define ACCEL 1
#define DECEL 2
#define RUN 3
// Pin numbering
#define en_pin 13
#define dir_pin 12
#define step_pin 11
#define slot_sensor_pin 10
// Motor direction
#define CW 0
#define CCW 1
typedef struct
{
unsigned char run_state : 3; // Determining the state of the speed profile
unsigned char dir: 1; // Determining the direction the motor has to move - Start being CCW
unsigned int first_step_delay; // Period time for the next timer_delay, determines the acceleration rate.
unsigned int decel_start; // Determines at which step the deceleration should begin.
signed int decel_length; // Set the deceleration length
signed int min_time_delay; //minium time required time_delay for achieving the wanted speed.
signed int accel_count; // counter used when computing step_delay for acceleration/decelleration.
volatile signed int current_step_position; // contains the current step_position
}speed_profile;
void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed);
void computation_of_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed);
void init_tipper_position();
void timer1_setup(void);
void output_pin_setup(void);
#endif
while((PINB & (0 << 2)))
这绝不是真的。 0 移动任何数量总是零。任何带有零的anded 始终为零,即false
,因此永远不会进入循环。
我目前运行我的arduino上有这个程序..
main.ino
#include "speed_profile.h"
void setup() {
// put your setup code here, to run once:
output_pin_setup();
cli();
timer1_setup();
sei();
}
void loop()
{
//int motor_steps = 23400;//-9600; //23400 - 100%
// Accelration to use.
//int motor_acceleration = 500;//500;
// Deceleration to use.
//int motor_deceleration = 500;//500;
// Speed to use.
//int motor_speed = 1000; // 1000
init_tipper_position();
compute_speed_profile(23400, 500, 500, 1000);
}
并且出于某种原因没有执行 init_tipper_position
,看起来像这样。
void init_tipper_position()
{
digitalWrite(en_pin, HIGH);
delay(1);
digitalWrite(dir_pin, LOW);
delay(1);
while((PINB & (0 << 2)))
{
digitalWrite(step_pin, HIGH);
delayMicroseconds(100);
digitalWrite(step_pin, LOW);
delayMicroseconds(100);
}
digitalWrite(en_pin, LOW);
}
我知道由于以下原因肯定会跳过。
1) 我正在使用的硬件没有任何反应。它应该 移动一个移动直到传感器被激活,但这并没有发生。
如果enable pin为高,是不是电机就不能动了, 在这种情况下是可能的
我有一个逻辑分析仪, 我可以确定输出范围,这表明启用不高。
那么为什么程序会跳过那部分功能。 应该注意的是,如果我从 main 中删除该函数,该函数将起作用。
代码中用到的所有函数都可以在.cpp文件中看到。 profile 只是一个跟踪一些变量的结构。
.cpp
#include "speed_profile.h"
volatile speed_profile profile;
ros::NodeHandle_<ArduinoHardware, 1, 2, 125, 125> nh;
//ros::NodeHandle nh;
std_msgs::Int8 status_step_count;
std_msgs::Int8 status_tipper_availability;
ros::Publisher chatter_status("tipper_status", &status_step_count);
ros::Publisher chatter_availabilty("tipper_availability", &status_tipper_availability);
volatile bool global_state = false;
int received_data = 0;
void call_back_control( const std_msgs::Empty & msg)
{
global_state = true;
received_data = (10 *23400.0)/100.0; // Converts input to motor_steps.
}
ros::Subscriber<std_msgs::Empty> sub_control("tipper_control", &call_back_control );
void output_pin_setup()
{
pinMode(en_pin, OUTPUT);
pinMode(dir_pin, OUTPUT);
pinMode(step_pin, OUTPUT);
pinMode(slot_sensor_pin,INPUT_PULLUP);
nh.initNode();
nh.advertise(chatter_status);
nh.advertise(chatter_availabilty);
nh.subscribe(sub_control);
//nh.subscribe(sub_command);
profile.current_step_position = 0;
delay(10);
nh.getHardware()->setBaud(57600);
}
void init_tipper_position()
{
digitalWrite(en_pin, HIGH);
delay(1);
digitalWrite(dir_pin, LOW);
delay(1);
while((PINB & (0 << 2)))
{
digitalWrite(step_pin, HIGH);
delayMicroseconds(100);
digitalWrite(step_pin, LOW);
delayMicroseconds(100);
}
digitalWrite(en_pin, LOW);
}
void timer1_setup()
{
// Tells what part of speed ramp we are in.
profile.run_state = STOP;
// Timer/Counter 1 in mode 4 CTC (Not running).
TCCR1B = (1 << WGM12);
// Timer/Counter 1 Output Compare A Match Interrupt enable.
TIMSK1 = (1 << OCIE1A);
}
void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed)
{
while (global_state == false)
{
//do nothing
status_step_count.data = ((float)(profile.current_step_position / 23400.0)) * 100.0; //map(profile.current_step_position,0,23400,0,100); // could be expensive -- Nice flowing is only available with float
status_tipper_availability.data = 1;
chatter_status.publish( &status_step_count);
chatter_availabilty.publish(&status_tipper_availability);
nh.spinOnce();
}
digitalWrite(en_pin, HIGH);
delay(1);
signed int move_steps;
if(received_data > profile.current_step_position) // Compares whether received percentage (converted to motor_steps) is greater or smaller than current_step_position.
{
profile.dir = CCW;
//motor_steps = -motor_steps;
move_steps = profile.current_step_position - received_data;
digitalWrite(dir_pin, HIGH);
}
else
{
profile.dir = CW;
move_steps = profile.current_step_position - received_data;
digitalWrite(dir_pin, LOW);
}
delay(1);
computation_of_speed_profile(move_steps, motor_accel, motor_decel, motor_speed); // Computes constants for profile..
OCR1A = 10;
// Set Timer/Counter to divide clock by 8
TCCR1B |= ((0 << CS12) | (1 << CS11) | (0 << CS10));
while (global_state == true)
{
status_step_count.data = ((float)(profile.current_step_position / 23400.0)) * 100.0; //map(profile.current_step_position,0,23400,0,100);
status_tipper_availability.data = 0;
chatter_availabilty.publish(&status_tipper_availability);
chatter_status.publish( &status_step_count);
nh.spinOnce();
//delay(100);
}
}
ISR(TIMER1_COMPA_vect)
{
// Holds next delay period.
unsigned int new_first_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.first_step_delay;
switch (profile.run_state)
{
case STOP:
step_count = 0;
global_state = false;
rest = 0;
TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer, No clock source
break;
case ACCEL:
PORTB ^= _BV(PB3); // Toggles the step_pin
step_count++;
if (profile.dir == CCW)
{
profile.current_step_position++;
}
else
{
profile.current_step_position--;
}
profile.accel_count++;
new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest) / (4 * profile.accel_count + 1));
rest = ((2 * (long)profile.first_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_length;
profile.run_state = DECEL;
}
// Chech if we hitted max speed.
else if (new_first_step_delay <= profile.min_time_delay)
{
last_accel_delay = new_first_step_delay;
new_first_step_delay = profile.min_time_delay;
rest = 0;
profile.run_state = RUN;
}
break;
case RUN:
PORTB ^= _BV(PB3); // Toggles the step_pin
step_count++;
if (profile.dir == CCW)
{
profile.current_step_position++;
}
else
{
profile.current_step_position--;
}
new_first_step_delay = profile.min_time_delay;
// Chech if we should start decelration.
if (step_count >= profile.decel_start)
{
profile.accel_count = profile.decel_length;
// Start decelration with same delay as accel ended with.
new_first_step_delay = last_accel_delay;
profile.run_state = DECEL;
}
break;
case DECEL:
PORTB ^= _BV(PB3); // Toggles the step_pin
step_count++;
if (profile.dir == CCW)
{
profile.current_step_position++;
}
else
{
profile.current_step_position--;
}
profile.accel_count++;
new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest) / (4 * profile.accel_count + 1));
rest = ((2 * (long)profile.first_step_delay) + rest) % (4 * profile.accel_count + 1);
// Check if we at last step
if (profile.accel_count >= 0)
{
digitalWrite(en_pin, !digitalRead(en_pin));
profile.run_state = STOP;
}
break;
}
profile.first_step_delay = new_first_step_delay;
}
.h 文件
/*
* Contains the class concerning with calculating the proper speed profile
* for accelerating and decelerating the stepper motor.
*
*/
#ifndef speed_profile_h
#define speed_profile_h
#include <Arduino.h>
#include <ros.h>
#include <std_msgs/Int8.h>
#include <std_msgs/Empty.h>
// Timer/Counter 1 running on 3,686MHz / 8 = 460,75kHz (2,17uS). (T1-FREQ 460750)
//#define T1_FREQ 460750
#define T1_FREQ 1382400
//! Number of (full)steps per round on stepper motor in use.
#define FSPR 1600
// Maths constants. To simplify maths when calculating in compute_speed_profile().
#define ALPHA (2*3.14159/FSPR) // 2*pi/spr
#define A_T_x100 ((long)(ALPHA*T1_FREQ*100)) // (ALPHA / T1_FREQ)*100
#define T1_FREQ_148 ((int)((T1_FREQ*0.676)/100)) // divided by 100 and scaled by 0.676
#define A_SQ (long)(ALPHA*2*10000000000) // ALPHA*2*10000000000
#define A_x20000 (int)(ALPHA*20000) // ALPHA*20000
// Speed ramp states
#define STOP 0
#define ACCEL 1
#define DECEL 2
#define RUN 3
// Pin numbering
#define en_pin 13
#define dir_pin 12
#define step_pin 11
#define slot_sensor_pin 10
// Motor direction
#define CW 0
#define CCW 1
typedef struct
{
unsigned char run_state : 3; // Determining the state of the speed profile
unsigned char dir: 1; // Determining the direction the motor has to move - Start being CCW
unsigned int first_step_delay; // Period time for the next timer_delay, determines the acceleration rate.
unsigned int decel_start; // Determines at which step the deceleration should begin.
signed int decel_length; // Set the deceleration length
signed int min_time_delay; //minium time required time_delay for achieving the wanted speed.
signed int accel_count; // counter used when computing step_delay for acceleration/decelleration.
volatile signed int current_step_position; // contains the current step_position
}speed_profile;
void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed);
void computation_of_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed);
void init_tipper_position();
void timer1_setup(void);
void output_pin_setup(void);
#endif
while((PINB & (0 << 2)))
这绝不是真的。 0 移动任何数量总是零。任何带有零的anded 始终为零,即false
,因此永远不会进入循环。