|
@@ -4,6 +4,7 @@
|
|
|
#include "os/co_task.h"
|
|
#include "os/co_task.h"
|
|
|
#include "os/timer.h"
|
|
#include "os/timer.h"
|
|
|
#include "libs/utils.h"
|
|
#include "libs/utils.h"
|
|
|
|
|
+#include "libs/logger.h"
|
|
|
#include "math/fast_math.h"
|
|
#include "math/fast_math.h"
|
|
|
#include "hall_sensor.h"
|
|
#include "hall_sensor.h"
|
|
|
#include "foc/foc_api.h"
|
|
#include "foc/foc_api.h"
|
|
@@ -11,7 +12,8 @@
|
|
|
#include "bsp/timer_count32.h"
|
|
#include "bsp/timer_count32.h"
|
|
|
|
|
|
|
|
#define HALL_READ_TIMES 3
|
|
#define HALL_READ_TIMES 3
|
|
|
-static void _hall_timeout_handler(timer_t *timer);
|
|
|
|
|
|
|
+static void _hall_detect_task(void *args);
|
|
|
|
|
+
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
* 测量HALL_PLACE_OFFSET通用方式就是ST推荐的通过外力带动电机,
|
|
* 测量HALL_PLACE_OFFSET通用方式就是ST推荐的通过外力带动电机,
|
|
@@ -21,7 +23,7 @@ static void _hall_timeout_handler(timer_t *timer);
|
|
|
* 从0开始增加,每增加1度观察电机电流(看直流电源),
|
|
* 从0开始增加,每增加1度观察电机电流(看直流电源),
|
|
|
* 找到一个电机平稳转动并且电流最小的角度作为HALL_PLACE_OFFSET
|
|
* 找到一个电机平稳转动并且电流最小的角度作为HALL_PLACE_OFFSET
|
|
|
*/
|
|
*/
|
|
|
-#define HALL_PLACE_OFFSET 210.0f
|
|
|
|
|
|
|
+#define HALL_PLACE_OFFSET 210
|
|
|
/*
|
|
/*
|
|
|
100
|
|
100
|
|
|
101
|
|
101
|
|
@@ -35,7 +37,6 @@ static void _hall_timeout_handler(timer_t *timer);
|
|
|
static u16 _hall_table[] = {0xFFFF, 121/*1*/, 240/*2*/, 190/*3*/, 13/*4*/, 58/*5*/, 306/*6*/, 0xFFFF};
|
|
static u16 _hall_table[] = {0xFFFF, 121/*1*/, 240/*2*/, 190/*3*/, 13/*4*/, 58/*5*/, 306/*6*/, 0xFFFF};
|
|
|
static hall_t _hall;
|
|
static hall_t _hall;
|
|
|
static hall_sample_t h_samples;
|
|
static hall_sample_t h_samples;
|
|
|
-static timer_t _hall_detect_timer = TIMER_INIT(_hall_detect_timer, _hall_timeout_handler);
|
|
|
|
|
measure_time_t g_meas_hall = {.exec_max_time = 6,};
|
|
measure_time_t g_meas_hall = {.exec_max_time = 6,};
|
|
|
|
|
|
|
|
#define read_hall(h,t) {h = get_hall_stat(HALL_READ_TIMES); t = _hall_table[h];}
|
|
#define read_hall(h,t) {h = get_hall_stat(HALL_READ_TIMES); t = _hall_table[h];}
|
|
@@ -45,23 +46,21 @@ static float __inline _delta_seconds(u32 prev) {
|
|
|
return (float)timer_count32_delta_us(prev, NULL)/1000000.0f;
|
|
return (float)timer_count32_delta_us(prev, NULL)/1000000.0f;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static void __inline _hall_put_sample(float angle, u32 ticks) {
|
|
|
|
|
|
|
+static void __inline _hall_put_sample(u32 ticks) {
|
|
|
hall_sample_t *s = &h_samples;
|
|
hall_sample_t *s = &h_samples;
|
|
|
s->index += 1;
|
|
s->index += 1;
|
|
|
if (s->index >= SAMPLE_MAX_COUNT) {
|
|
if (s->index >= SAMPLE_MAX_COUNT) {
|
|
|
s->full = true;
|
|
s->full = true;
|
|
|
s->index = 0;
|
|
s->index = 0;
|
|
|
}
|
|
}
|
|
|
- s->angle[s->index] = angle;
|
|
|
|
|
s->ticks[s->index] = ticks;
|
|
s->ticks[s->index] = ticks;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static float __inline _hall_avg_speed(void){
|
|
static float __inline _hall_avg_speed(void){
|
|
|
hall_sample_t *s = &h_samples;
|
|
hall_sample_t *s = &h_samples;
|
|
|
- float t_angle = 0.0f;
|
|
|
|
|
|
|
+ float t_angle = (float)(PHASE_60_DEGREE * SAMPLE_MAX_COUNT);
|
|
|
u32 t_ticks = 0;
|
|
u32 t_ticks = 0;
|
|
|
for (int i = 0; i < SAMPLE_MAX_COUNT; i++) {
|
|
for (int i = 0; i < SAMPLE_MAX_COUNT; i++) {
|
|
|
- t_angle += s->angle[i];
|
|
|
|
|
t_ticks += s->ticks[i];
|
|
t_ticks += s->ticks[i];
|
|
|
}
|
|
}
|
|
|
if (t_ticks == 0.0f) {
|
|
if (t_ticks == 0.0f) {
|
|
@@ -75,15 +74,29 @@ void hall_sensor_init(void) {
|
|
|
memset(&_hall, 0, sizeof(_hall));
|
|
memset(&_hall, 0, sizeof(_hall));
|
|
|
read_hall(_hall.state, _hall.theta);
|
|
read_hall(_hall.state, _hall.theta);
|
|
|
_hall.phase_offset = HALL_PLACE_OFFSET;//mc_config_get()->hall_offset;
|
|
_hall.phase_offset = HALL_PLACE_OFFSET;//mc_config_get()->hall_offset;
|
|
|
|
|
+ co_task_create(_hall_detect_task, NULL, 512);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void _hall_timeout_handler(timer_t *timer){
|
|
|
|
|
|
|
+void hall_sensor_clear(void) {
|
|
|
|
|
+ memset(&_hall, 0, sizeof(_hall));
|
|
|
|
|
+ read_hall(_hall.state, _hall.theta);
|
|
|
|
|
+ _hall.phase_offset = HALL_PLACE_OFFSET;//mc_config_get()->hall_offset;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- _hall.angle_speed = _hall.angle_speed_avg = 0;
|
|
|
|
|
- _hall.rpm = 0;
|
|
|
|
|
- h_samples.index = 0;
|
|
|
|
|
|
|
+static void _hall_detect_task(void *args) {
|
|
|
|
|
+ while(1) {
|
|
|
|
|
+ if (_hall.working) {
|
|
|
|
|
+ u32 ticks_now = timer_count32_get();
|
|
|
|
|
+ u32 delta_us = timer_count32_getus(ticks_now, _hall.ticks);
|
|
|
|
|
+ if (delta_us >= (1200*1000)) {
|
|
|
|
|
+ hall_sensor_clear();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ co_task_delay(100);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
u16 *hall_phase_angle(void) {
|
|
u16 *hall_phase_angle(void) {
|
|
|
return _hall_table;
|
|
return _hall_table;
|
|
|
}
|
|
}
|
|
@@ -96,7 +109,7 @@ float hall_sensor_get_theta(void){
|
|
|
read_hall(_hall.state, _hall.theta);
|
|
read_hall(_hall.state, _hall.theta);
|
|
|
return _hall.theta;
|
|
return _hall.theta;
|
|
|
}
|
|
}
|
|
|
- _hall.est_theta = _delta_seconds(_hall.ticks) * _hall.angle_speed + _hall.theta;
|
|
|
|
|
|
|
+ _hall.est_theta = _delta_seconds(_hall.ticks) * _hall.angle_speed * _hall.direction + _hall.theta;
|
|
|
float est_delta = _hall.est_theta - _hall.theta;
|
|
float est_delta = _hall.est_theta - _hall.theta;
|
|
|
if (est_delta > PHASE_60_DEGREE) {
|
|
if (est_delta > PHASE_60_DEGREE) {
|
|
|
_hall.est_theta = _hall.theta + PHASE_60_DEGREE;
|
|
_hall.est_theta = _hall.theta + PHASE_60_DEGREE;
|
|
@@ -126,8 +139,8 @@ float hall_sensor_avg_speed(void) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int hall_offset_increase(int inc) {
|
|
int hall_offset_increase(int inc) {
|
|
|
- if (_hall.phase_offset + inc >= 360.0f) {
|
|
|
|
|
- _hall.phase_offset = _hall.phase_offset + inc - 360.0f;
|
|
|
|
|
|
|
+ if (_hall.phase_offset + inc >= 360) {
|
|
|
|
|
+ _hall.phase_offset = _hall.phase_offset + inc - 360;
|
|
|
}else {
|
|
}else {
|
|
|
_hall.phase_offset += inc;
|
|
_hall.phase_offset += inc;
|
|
|
}
|
|
}
|
|
@@ -199,24 +212,8 @@ int hall_sensor_calibrate(float voltage, u16 *hall_table){
|
|
|
return fails == 2;
|
|
return fails == 2;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-void hall_sensor_handler(void) {
|
|
|
|
|
-
|
|
|
|
|
- time_measure_start(&g_meas_hall);
|
|
|
|
|
- u8 state_now = get_hall_stat(HALL_READ_TIMES);
|
|
|
|
|
- float theta_now = _hall_table[state_now];
|
|
|
|
|
- u8 state_prev = _hall.state;
|
|
|
|
|
-
|
|
|
|
|
- if (!_hall.working) {
|
|
|
|
|
- if(theta_now != 0xFFFF) {
|
|
|
|
|
- _hall.working = true;
|
|
|
|
|
- _hall.state = state_now;
|
|
|
|
|
- _hall.theta = theta_now;
|
|
|
|
|
- _hall.ticks = timer_count32_get();
|
|
|
|
|
- }
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+static s32 _hall_position(u8 state_now, u8 state_prev) {
|
|
|
|
|
+ s32 theta_now = 0xFFFFFFFF;
|
|
|
switch (state_now) {
|
|
switch (state_now) {
|
|
|
case STATE_1:
|
|
case STATE_1:
|
|
|
if (state_prev == STATE_5) {
|
|
if (state_prev == STATE_5) {
|
|
@@ -273,38 +270,63 @@ void hall_sensor_handler(void) {
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
default:
|
|
default:
|
|
|
- return;
|
|
|
|
|
|
|
+ return 0xFFFFFFFF;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if (theta_now >= 360.0f) {
|
|
|
|
|
- theta_now -= 360.0f;
|
|
|
|
|
|
|
+ if (theta_now >= 360) {
|
|
|
|
|
+ theta_now -= 360;
|
|
|
}
|
|
}
|
|
|
|
|
+ return theta_now;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void hall_sensor_handler(void) {
|
|
|
|
|
|
|
|
- float delta_time = _delta_seconds(_hall.ticks);
|
|
|
|
|
- if (delta_time == 0.0f) { //may be errors ???
|
|
|
|
|
|
|
+ time_measure_start(&g_meas_hall);
|
|
|
|
|
+ u8 state_now = get_hall_stat(HALL_READ_TIMES);
|
|
|
|
|
+ u8 state_prev = _hall.state;
|
|
|
|
|
+ u32 ticks_now = timer_count32_get();
|
|
|
|
|
+
|
|
|
|
|
+ _hall.state = get_hall_stat(HALL_READ_TIMES);
|
|
|
|
|
+ if (!_hall.working) {
|
|
|
|
|
+ if(_hall_table[state_now] != 0xFFFF) {
|
|
|
|
|
+ _hall.working = true;
|
|
|
|
|
+ _hall.state = state_now;
|
|
|
|
|
+ _hall.theta = _hall_table[state_now];
|
|
|
|
|
+ _hall.ticks = ticks_now;
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ s32 theta_now = _hall_position(_hall.state, state_prev);
|
|
|
|
|
+ if (theta_now == 0xFFFFFFFF) {
|
|
|
|
|
+ _hall.state = state_prev;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- time_measure_end(&g_meas_hall);
|
|
|
|
|
- float delta_theta = (_hall.direction == POSITIVE)?60.0f : -60.0f;
|
|
|
|
|
- _hall_put_sample(delta_theta, timer_count32_delta_us(_hall.ticks, NULL));
|
|
|
|
|
|
|
|
|
|
|
|
+ u32 delta_us = timer_count32_getus(ticks_now, _hall.ticks);
|
|
|
|
|
+ if (delta_us == 0) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
os_disable_irq();
|
|
os_disable_irq();
|
|
|
- _hall.angle_speed = delta_theta / delta_time;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ float delta_time = us_2_s(delta_us);
|
|
|
|
|
+
|
|
|
|
|
+ _hall_put_sample(delta_us);
|
|
|
|
|
+
|
|
|
|
|
+ _hall.angle_speed = (float)PHASE_60_DEGREE / delta_time;
|
|
|
|
|
|
|
|
if (!h_samples.full) {
|
|
if (!h_samples.full) {
|
|
|
_hall.angle_speed_avg = _hall.angle_speed;
|
|
_hall.angle_speed_avg = _hall.angle_speed;
|
|
|
}else {
|
|
}else {
|
|
|
_hall.angle_speed_avg = _hall_avg_speed();
|
|
_hall.angle_speed_avg = _hall_avg_speed();
|
|
|
}
|
|
}
|
|
|
- _hall.ticks = timer_count32_get();
|
|
|
|
|
|
|
+
|
|
|
_hall.theta = theta_now;
|
|
_hall.theta = theta_now;
|
|
|
_hall.state = state_now;
|
|
_hall.state = state_now;
|
|
|
|
|
+ _hall.ticks = ticks_now;
|
|
|
os_enable_irq();
|
|
os_enable_irq();
|
|
|
|
|
|
|
|
_hall.rpm = _hall.angle_speed / 360.0f * 60.0f;
|
|
_hall.rpm = _hall.angle_speed / 360.0f * 60.0f;
|
|
|
-
|
|
|
|
|
- timer_post(&_hall_detect_timer, 1500);
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ time_measure_end(&g_meas_hall);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|