-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat:add motor and encoder based on can-bus and add a kinematics #39
base: master
Are you sure you want to change the base?
Changes from all commits
17b3791
116bffa
ee53479
54112bc
fc8e020
b1478c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* | ||
* Copyright (c) 2019, RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Change Logs: | ||
* Date Author Notes | ||
* 2019-11-14 Soil_L The first version | ||
*/ | ||
#include "can_encoder.h" | ||
|
||
#define DBG_SECTION_NAME "can_encoder" | ||
#define DBG_LEVEL DBG_LOG | ||
#include <rtdbg.h> | ||
|
||
rt_sem_t rx_sem_g; | ||
|
||
rt_err_t encoder_isr(rt_device_t dev, rt_size_t size) | ||
{ | ||
rt_sem_release(rx_sem_g); | ||
return RT_EOK; | ||
} | ||
|
||
static rt_err_t can_encoder_enable(void *enc) | ||
{ | ||
can_encoder_t enc_sub = (can_encoder_t)enc; | ||
|
||
volatile rt_err_t res; | ||
|
||
//Avoid repeated opening | ||
if(!(enc_sub->can_dev->flag & RT_DEVICE_FLAG_ACTIVATED)) | ||
{ | ||
res = rt_device_open(enc_sub->can_dev,RT_DEVICE_FLAG_INT_RX|RT_DEVICE_FLAG_INT_TX); | ||
res = rt_device_control(enc_sub->can_dev,RT_CAN_CMD_SET_BAUD,(void *)enc_sub->Baud); | ||
res = rt_device_control(enc_sub->can_dev,RT_CAN_CMD_SET_FILTER,&enc_sub->cfg); | ||
} | ||
res = rt_device_set_rx_indicate(enc_sub->can_dev,encoder_isr); | ||
|
||
return RT_EOK; | ||
} | ||
|
||
static rt_err_t can_encoder_disable(void *enc) | ||
{ | ||
return RT_EOK; | ||
} | ||
|
||
static rt_err_t can_encoder_destroy(void *enc) | ||
{ | ||
can_encoder_t enc_sub = (can_encoder_t)enc; | ||
|
||
volatile rt_err_t res; | ||
res = rt_device_close(enc_sub->can_dev); | ||
rt_sem_delete(*(enc_sub->rx_sem)); | ||
rt_free(enc_sub); | ||
|
||
return RT_EOK; | ||
} | ||
|
||
can_encoder_t can_encoder_create(char *can,struct rt_can_filter_config cfg,rt_uint32_t Baud,rt_sem_t* rx_sem) | ||
{ | ||
can_encoder_t new_encoder = (can_encoder_t)encoder_create(sizeof(struct can_encoder),0); | ||
if(new_encoder == RT_NULL) | ||
{ | ||
return RT_NULL; | ||
} | ||
|
||
new_encoder->can_dev = (rt_device_t)rt_device_find(can); | ||
if (new_encoder->can_dev == RT_NULL) | ||
{ | ||
rt_free(new_encoder); | ||
LOG_E("Falied to find device on %s", can); | ||
return RT_NULL; | ||
} | ||
|
||
new_encoder->cfg = cfg; | ||
new_encoder->enc.enable = can_encoder_enable; | ||
new_encoder->enc.disable = can_encoder_disable; | ||
new_encoder->enc.destroy = can_encoder_destroy; | ||
new_encoder->Baud = Baud; | ||
new_encoder->rx_sem = rx_sem; | ||
rx_sem_g = *rx_sem; | ||
return new_encoder; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright (c) 2019, RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Change Logs: | ||
* Date Author Notes | ||
* 2019-11-14 Soil_L The first version | ||
*/ | ||
#ifndef _CAN_ENCODER_ | ||
#define _CAN_ENCODER_ | ||
|
||
#include "encoder.h" | ||
|
||
struct can_encoder | ||
{ | ||
struct encoder enc; | ||
rt_device_t can_dev; | ||
struct rt_can_filter_config cfg; | ||
rt_uint32_t Baud; | ||
rt_sem_t *rx_sem; | ||
rt_uint32_t rpm; | ||
}; | ||
typedef struct can_encoder *can_encoder_t; | ||
|
||
can_encoder_t can_encoder_create(char *can,struct rt_can_filter_config cfg,rt_uint32_t Baud,rt_sem_t* rx_sem); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. xxx_encoder_create 是面向用户的 rx_sem 是否真的必须? 合理? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 建议这样, 如果通用的不能完整(或很好地)整出来, 那就先直接上专用的,比如直接就针对 C620 电调, 给用户的接口也可以更易用 |
||
|
||
#endif //CAN_ENCODER_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
* Change Logs: | ||
* Date Author Notes | ||
* 2019-08-26 sogwms The first version | ||
* 2019-11-14 Soil_L motified for the need of can encoder | ||
*/ | ||
|
||
#include <rtdevice.h> | ||
|
@@ -96,10 +97,16 @@ rt_int16_t encoder_measure_cps(encoder_t enc) | |
rt_int16_t encoder_measure_rpm(encoder_t enc) | ||
{ | ||
RT_ASSERT(enc != RT_NULL); | ||
|
||
// return resolution per minute | ||
rt_int16_t res_rpm = encoder_measure_cps(enc) * 60 / enc->pulse_revol; | ||
|
||
rt_int16_t res_rpm; | ||
if(enc->sample_time == 0) | ||
{ | ||
res_rpm = enc->pulse_count; | ||
} | ||
else | ||
{ | ||
// return resolution per minute | ||
res_rpm = encoder_measure_cps(enc) * 60 / enc->pulse_revol; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 为什么要做这个修改? 对can电机获取编码器信息有帮助吗? 对于像大疆can电机 encoder_measure_cps 才是障碍吧, 抽象程度不够 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 因为对于利用计数脉冲的编码器来说有采样周期,而对于利用通信协议传输数据的编码器来说没有采样周期。所以在这里有一个判断,如果sample_time>0则有采样周期,计算res_rpm的方法不变,如果sample_time<=0则表示没有采样周期,res_rpm由pulse_count直接得到。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 可行 |
||
return res_rpm; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
* Change Logs: | ||
* Date Author Notes | ||
* 2019-07-17 Wu Han The first version | ||
* 2019-11-14 Soil_L add four wheel omnidirectional | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 建议分开提交 motor 和 kinematic |
||
*/ | ||
|
||
#ifndef __KINEMATICS_H__ | ||
|
@@ -17,7 +18,8 @@ enum base { | |
TWO_WD = 0, | ||
FOUR_WD, | ||
ACKERMANN, | ||
MECANUM | ||
MECANUM, | ||
FOUR_WD_ALLDIR | ||
}; | ||
|
||
// rad/min | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/* | ||
* Copyright (c) 2019, RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Change Logs: | ||
* Date Author Notes | ||
* 2019-11-14 Soil_L The first version | ||
*/ | ||
#include "can_motor.h" | ||
|
||
#define DBG_SECTION_NAME "can_motor" | ||
#define DBG_LEVEL DBG_LOG | ||
#include <rtdbg.h> | ||
|
||
|
||
static rt_err_t can_motor_enable(void *mot) | ||
{ | ||
can_motor_t mot_sub = (can_motor_t)mot; | ||
|
||
//Avoid repeated opening | ||
if(!(mot_sub->can_dev->flag & RT_DEVICE_FLAG_ACTIVATED)) | ||
{ | ||
rt_err_t res = rt_device_open(mot_sub->can_dev,RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX ); | ||
res = rt_device_control(mot_sub->can_dev,RT_CAN_CMD_SET_BAUD,(void *)mot_sub->Baud); | ||
res = rt_device_control(mot_sub->can_dev,RT_CAN_CMD_SET_FILTER,&mot_sub->cfg); | ||
} | ||
return RT_EOK; | ||
} | ||
|
||
static rt_err_t can_motor_disable(void *mot) | ||
{ | ||
can_motor_t mot_sub = (can_motor_t)mot; | ||
|
||
rt_err_t res = rt_device_close(mot_sub->can_dev); | ||
|
||
return RT_EOK; | ||
} | ||
|
||
static rt_err_t can_motor_reset(void *mot) | ||
{ | ||
return RT_EOK; | ||
} | ||
|
||
static rt_err_t can_motor_set_speed(void *mot, rt_int16_t thousands) | ||
{ | ||
can_motor_t mot_sub = (can_motor_t)mot; | ||
|
||
if(mot_sub->min_num > thousands) | ||
{ | ||
thousands = mot_sub->min_num; | ||
} | ||
else if(mot_sub->max_num < thousands) | ||
{ | ||
thousands = mot_sub->max_num; | ||
} | ||
Comment on lines
+45
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 额, 此处的 thousands 默认即暗示设定范围为 -1000 ~ 1000, 将此映射到实际可设置范围即可。 可参考其他已有 motor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里的thousands是什么含义?我的理解是控制器计算完之后给电机执行的输出 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 是的,但值的范围是确定的。 打个比方, 电机是小弟,上面的大哥给它设定值让它运转。 小弟和大哥都公认 设定值的范围是 -1000~+1000. 小弟(电机)多种多样(最大转速等)。 但都知道 +-1000 对应自己的最大转速, 0是停止 |
||
|
||
mot_sub->msg->data[(mot_sub->mot_id -1)*2] = thousands>>8; | ||
mot_sub->msg->data[(mot_sub->mot_id -1)*2+1] = thousands; | ||
rt_size_t size = rt_device_write(mot_sub->can_dev, 0, mot_sub->msg, sizeof(*(mot_sub->msg)) ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这是只针对大疆can电机的协议吗,是的话文件名等应该更具体一点 比如 dji_can_motor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 想的是对所有用can通信的电机和编码器。测试的时候用的是大疆M3508电机(C620电调) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 不是很了解 can 电机 不知 大疆系的can电机协议是否都相同(似)可统一,非大疆的can电机有没有,协议怎样。 可以的话还是建议在能保证完整性的前提下提高适用层次。 建议针 c602 或 大疆系? |
||
|
||
return RT_EOK; | ||
} | ||
|
||
|
||
can_motor_t can_motor_create(char *can,struct rt_can_filter_config cfg,rt_uint32_t Baud,rt_can_msg_t msg,rt_int16_t max_num,rt_int16_t min_num,rt_uint8_t mot_id) | ||
{ | ||
RT_ASSERT(max_num>min_num) | ||
|
||
can_motor_t new_motor = (can_motor_t)motor_create(sizeof(struct can_motor)); | ||
if (new_motor == RT_NULL) | ||
{ | ||
return RT_NULL; | ||
} | ||
|
||
new_motor->can_dev = (rt_device_t)rt_device_find(can); | ||
if (new_motor->can_dev == RT_NULL) | ||
{ | ||
rt_free(new_motor); | ||
LOG_E("Falied to find device on %s", can); | ||
return RT_NULL; | ||
} | ||
|
||
new_motor->cfg = cfg; | ||
new_motor->Baud = Baud; | ||
new_motor->msg = msg; | ||
new_motor->max_num = max_num; | ||
new_motor->min_num = min_num; | ||
new_motor->mot_id = mot_id; | ||
new_motor->mot.enable = can_motor_enable; | ||
new_motor->mot.set_speed = can_motor_set_speed; | ||
new_motor->mot.reset = can_motor_reset; | ||
new_motor->mot.disable = can_motor_disable; | ||
|
||
return new_motor; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (c) 2019, RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Change Logs: | ||
* Date Author Notes | ||
* 2019-11-14 Soil_L The first version | ||
*/ | ||
#ifndef _CAN_MOTOR_H_ | ||
#define _CAN_MOTOR_H_ | ||
|
||
#include "motor.h" | ||
|
||
struct can_motor | ||
{ | ||
struct motor mot; | ||
rt_device_t can_dev; | ||
struct rt_can_filter_config cfg; | ||
rt_uint32_t Baud; | ||
rt_can_msg_t msg; //the pointer of message defined by the users,it decide the number of the can motor in the can net | ||
rt_int16_t max_num; | ||
rt_int16_t min_num; | ||
rt_uint8_t mot_id; //the id of the can motor in the can net | ||
}; | ||
typedef struct can_motor *can_motor_t; | ||
|
||
can_motor_t can_motor_create(char *can,struct rt_can_filter_config cfg,rt_uint32_t Baud,rt_can_msg_t msg,rt_int16_t max_num,rt_int16_t min_num,rt_uint8_t mot_id); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 同样的问题 api是否合适? 需要msg?需要 maximum? 还有想问下这是针对哪种can电机的? 还是通用的? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
#endif // __CAN_MOTOR_H__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
对于多实例的 encoder, 全局 sem 是个bug。完全可以不用这样做
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
本身信号量是一个指针,多个编码器又要用到同一个信号量,所以我传入的是信号量指针,所以这里是指针的指针
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
不管是结构体或结构体指针,它是全局的。 如果确定所有情况下用到的都是同一个信号量,为什么还需要用户创建