diff --git a/include/imu_9dof_dma.h b/include/imu_9dof_dma.h index 3ece2d8ceb7f310dccbf9edecc6010a18fe5c852..8163d5341d33605b433b0cf5c608e8ac3fbff6fc 100644 --- a/include/imu_9dof_dma.h +++ b/include/imu_9dof_dma.h @@ -4,47 +4,43 @@ #include "stm32f4xx.h" // accelerometer configuration data -#define RATE_3200HZ 0x0F -#define RATE_1600HZ 0x0E -#define RATE_800HZ 0x0D -#define RATE_400HZ 0x0C -#define RATE_200HZ 0x0B -#define RATE_100HZ 0x0A -#define RATE_50HZ 0x09 -#define RATE_25HZ 0x08 -#define RATE_12_5HZ 0x07 -#define RATE_6_25HZ 0x06 - -#define ENABLE_LINK 0x20 -#define ENABLE_AUTOSLEEP 0x10 -#define ENABLE_MEASURE 0x08 -#define ENABLE_SLEEP 0x04 -#define SLEEP_8HZ 0x00 -#define SLEEP_4HZ 0x01 -#define SLEEP_2HZ 0x02 -#define SLEEP_1HZ 0x03 - -#define ENABLE_FUL_RES 0x08 -#define JUSTIFY_LEFT 0x04 -#define JUSTIFY_RIGHT 0x00 -#define RANGE_2G 0x00 -#define RANGE_4G 0x01 -#define RANGE_8G 0x02 -#define RANGE_16G 0x03 +#define ACCEL_RATE_3200HZ 0x0F +#define ACCEL_RATE_1600HZ 0x0E +#define ACCEL_RATE_800HZ 0x0D +#define ACCEL_RATE_400HZ 0x0C +#define ACCEL_RATE_200HZ 0x0B +#define ACCEL_RATE_100HZ 0x0A +#define ACCEL_RATE_50HZ 0x09 +#define ACCEL_RATE_25HZ 0x08 +#define ACCEL_RATE_12_5HZ 0x07 +#define ACCEL_RATE_6_25HZ 0x06 + +#define ACCEL_ENABLE_LINK 0x20 +#define ACCEL_ENABLE_AUTOSLEEP 0x10 +#define ACCEL_ENABLE_MEASURE 0x08 +#define ACCEL_ENABLE_SLEEP 0x04 +#define ACCEL_SLEEP_8HZ 0x00 +#define ACCEL_SLEEP_4HZ 0x01 +#define ACCEL_SLEEP_2HZ 0x02 +#define ACCEL_SLEEP_1HZ 0x03 + +#define ACCEL_ENABLE_FULL_RES 0x08 +#define ACCEL_JUSTIFY_LEFT 0x04 +#define ACCEL_JUSTIFY_RIGHT 0x00 +#define ACCEL_RANGE_2G 0x00 +#define ACCEL_RANGE_4G 0x01 +#define ACCEL_RANGE_8G 0x02 +#define ACCEL_RANGE_16G 0x03 + +#define ACCEL_FIFO_BYPASS 0x00 +#define ACCEL_FIFO_BUFFER 0x40 +#define ACCEL_FIFO_STREAM 0x80 +#define ACCEL_FIFO_TRIGGER 0xC0 // general IMU public functions void imu_init(void); -// Accelerometer public functions -uint8_t imu_accel_detect(void); -void imu_accel_set_offset(uint8_t off_x, uint8_t off_y, uint8_t off_z); -void imu_accel_set_data_rate(uint8_t rate_hz); -void imu_accel_set_measure_mode(void); -void imu_accel_set_sleep_mode(void); -void imu_accel_set_sleep_rate(uint8_t rate_hz); -void imu_accel_set_range(uint8_t range); -void imu_accel_justify_left(void); -void imu_accel_justify_right(void); -void imu_accel_config(void); +void imu_start(void); +void imu_stop(void); // gyroscope public functions uint8_t imu_gyro_detect(void); diff --git a/include/motion_manager.h b/include/motion_manager.h index fe7f6b66956d787442927b93ea8e5c9ec3105268..17afdbbb9a40267040c204fa250fd15cc8d54dc4 100644 --- a/include/motion_manager.h +++ b/include/motion_manager.h @@ -16,8 +16,8 @@ typedef struct{ uint16_t model; uint16_t encoder_resolution; uint8_t gear_ratio; - int16_t max_angle; - int16_t center_angle; + uint16_t max_angle; + uint16_t center_angle; uint16_t max_speed; int16_t current_angle; uint16_t current_value; diff --git a/include/ram.h b/include/ram.h index 4524dded57dac296c278dcba6a95ab8e6b6e0092..188dd50047df6072a559b2634d7bfa501163553d 100644 --- a/include/ram.h +++ b/include/ram.h @@ -40,7 +40,77 @@ typedef enum { BIOLOID_MM_MODULE_EN12 = 0x2A, BIOLOID_MM_MODULE_EN13 = 0x2B, BIOLOID_MM_MODULE_EN14 = 0x2C, - BIOLOID_MM_MODULE_EN15 = 0x2D + BIOLOID_MM_MODULE_EN15 = 0x2D, + BIOLOID_MM_SERVO0_CUR_POS_L = 0x2E, + BIOLOID_MM_SERVO0_CUR_POS_H = 0x2F, + BIOLOID_MM_SERVO1_CUR_POS_L = 0x30, + BIOLOID_MM_SERVO1_CUR_POS_H = 0x31, + BIOLOID_MM_SERVO2_CUR_POS_L = 0x32, + BIOLOID_MM_SERVO2_CUR_POS_H = 0x33, + BIOLOID_MM_SERVO3_CUR_POS_L = 0x34, + BIOLOID_MM_SERVO3_CUR_POS_H = 0x35, + BIOLOID_MM_SERVO4_CUR_POS_L = 0x36, + BIOLOID_MM_SERVO4_CUR_POS_H = 0x37, + BIOLOID_MM_SERVO5_CUR_POS_L = 0x38, + BIOLOID_MM_SERVO5_CUR_POS_H = 0x39, + BIOLOID_MM_SERVO6_CUR_POS_L = 0x3A, + BIOLOID_MM_SERVO6_CUR_POS_H = 0x3B, + BIOLOID_MM_SERVO7_CUR_POS_L = 0x3C, + BIOLOID_MM_SERVO7_CUR_POS_H = 0x3D, + BIOLOID_MM_SERVO8_CUR_POS_L = 0x3E, + BIOLOID_MM_SERVO8_CUR_POS_H = 0x3F, + BIOLOID_MM_SERVO9_CUR_POS_L = 0x40, + BIOLOID_MM_SERVO9_CUR_POS_H = 0x41, + BIOLOID_MM_SERVO10_CUR_POS_L = 0x42, + BIOLOID_MM_SERVO10_CUR_POS_H = 0x43, + BIOLOID_MM_SERVO11_CUR_POS_L = 0x44, + BIOLOID_MM_SERVO11_CUR_POS_H = 0x45, + BIOLOID_MM_SERVO12_CUR_POS_L = 0x46, + BIOLOID_MM_SERVO12_CUR_POS_H = 0x47, + BIOLOID_MM_SERVO13_CUR_POS_L = 0x48, + BIOLOID_MM_SERVO13_CUR_POS_H = 0x49, + BIOLOID_MM_SERVO14_CUR_POS_L = 0x4A, + BIOLOID_MM_SERVO14_CUR_POS_H = 0x4B, + BIOLOID_MM_SERVO15_CUR_POS_L = 0x4C, + BIOLOID_MM_SERVO15_CUR_POS_H = 0x4D, + BIOLOID_MM_SERVO16_CUR_POS_L = 0x4E, + BIOLOID_MM_SERVO16_CUR_POS_H = 0x4F, + BIOLOID_MM_SERVO17_CUR_POS_L = 0x50, + BIOLOID_MM_SERVO17_CUR_POS_H = 0x51, + BIOLOID_MM_SERVO18_CUR_POS_L = 0x52, + BIOLOID_MM_SERVO18_CUR_POS_H = 0x53, + BIOLOID_MM_SERVO19_CUR_POS_L = 0x54, + BIOLOID_MM_SERVO19_CUR_POS_H = 0x55, + BIOLOID_MM_SERVO20_CUR_POS_L = 0x56, + BIOLOID_MM_SERVO20_CUR_POS_H = 0x57, + BIOLOID_MM_SERVO21_CUR_POS_L = 0x58, + BIOLOID_MM_SERVO21_CUR_POS_H = 0x59, + BIOLOID_MM_SERVO22_CUR_POS_L = 0x5A, + BIOLOID_MM_SERVO22_CUR_POS_H = 0x5B, + BIOLOID_MM_SERVO23_CUR_POS_L = 0x5C, + BIOLOID_MM_SERVO23_CUR_POS_H = 0x5D, + BIOLOID_MM_SERVO24_CUR_POS_L = 0x5E, + BIOLOID_MM_SERVO24_CUR_POS_H = 0x5F, + BIOLOID_MM_SERVO25_CUR_POS_L = 0x60, + BIOLOID_MM_SERVO25_CUR_POS_H = 0x61, + BIOLOID_MM_SERVO26_CUR_POS_L = 0x62, + BIOLOID_MM_SERVO26_CUR_POS_H = 0x63, + BIOLOID_MM_SERVO27_CUR_POS_L = 0x64, + BIOLOID_MM_SERVO27_CUR_POS_H = 0x65, + BIOLOID_MM_SERVO28_CUR_POS_L = 0x66, + BIOLOID_MM_SERVO28_CUR_POS_H = 0x67, + BIOLOID_MM_SERVO29_CUR_POS_L = 0x68, + BIOLOID_MM_SERVO29_CUR_POS_H = 0x69, + BIOLOID_MM_SERVO30_CUR_POS_L = 0x6A, + BIOLOID_MM_SERVO30_CUR_POS_H = 0x6B, + BIOLOID_IMU_STATUS = 0x6C, + BIOLOID_IMU_CONTROL = 0x6D, + BIOLOID_IMU_ACCEL_X_L = 0x6E, + BIOLOID_IMU_ACCEL_X_H = 0x6F, + BIOLOID_IMU_ACCEL_Y_L = 0x7A, + BIOLOID_IMU_ACCEL_Y_H = 0x7B, + BIOLOID_IMU_ACCEL_Z_L = 0x7C, + BIOLOID_IMU_ACCEL_Z_H = 0x7D } bioloid_registers; #define RAM_SIZE 256 diff --git a/src/bioloid_stm32.c b/src/bioloid_stm32.c index 8b735cdad9de35a729c49f6c02328882c1161309..a69bf5f3fb4bfa0f91a7c3514d7dbc7b48ccca8c 100644 --- a/src/bioloid_stm32.c +++ b/src/bioloid_stm32.c @@ -74,6 +74,20 @@ uint8_t write_operation(uint8_t address,uint8_t length, uint8_t *data) } else break; } + if(ram_in_range(BIOLOID_IMU_CONTROL,BIOLOID_IMU_CONTROL,address,length)) + { + if(data[address-BIOLOID_IMU_CONTROL]&0x01) + imu_start(); + else + imu_stop(); + } + if(ram_in_range(BIOLOID_MM_CONTROL,BIOLOID_MM_CONTROL,address,length)) + { + if(data[address-BIOLOID_MM_CONTROL]&0x01) + manager_enable(); + else + manager_disable(); + } // write eeprom for(i=address,j=0;i<LAST_EEPROM_OFFSET && i<(address+length);i++,j++) EE_WriteVariable(i,data[j]); @@ -112,7 +126,7 @@ int32_t main(void) EE_ReadVariable(RETURN_LEVEL_OFFSET,&eeprom_data); dyn_slave_set_return_level((uint8_t)eeprom_data); /* initialize the IMU */ -// imu_init(); + imu_init(); // initialize the Analog to digital converter // adc_init(); // initialize motion manager diff --git a/src/imu_9dof_dma.c b/src/imu_9dof_dma.c index 2d595a2941485d813543706e241e6646274a487f..5099fb129579d5e3f38ca383feb9e8b7872df831 100644 --- a/src/imu_9dof_dma.c +++ b/src/imu_9dof_dma.c @@ -1,4 +1,5 @@ #include "imu_9dof_dma.h" +#include "ram.h" #define I2C_IMU_DMA DMA1 #define I2C_IMU_DMA_CHANNEL DMA_Channel_3 @@ -41,26 +42,63 @@ #define I2C_IMU_EV_IRQHandler I2C3_EV_IRQHandler #define I2C_IMU_ER_IRQHandler I2C3_ER_IRQHandler +#define IMU_TIMER TIM4 +#define IMU_TIMER_IRQn TIM4_IRQn +#define IMU_TIMER_IRQHandler TIM4_IRQHandler +#define IMU_TIMER_CLK RCC_APB1Periph_TIM4 + +// accelerometer registers +#define ACCEL_THRESH_TAP 0x1D +#define ACCEL_OFSX 0x1E +#define ACCEL_OFSY 0x1F +#define ACCEL_OFSZ 0x20 +#define ACCEL_DUR 0x21 +#define ACCEL_LATENT 0x22 +#define ACCEL_WINDOW 0x23 +#define ACCEL_THRESH_ACT 0x24 +#define ACCEL_THRESH_INACT 0x25 +#define ACCEL_TIME_INACT 0x26 +#define ACCEL_ACT_INACT_CTL 0x27 +#define ACCEL_THRESH_FF 0x28 +#define ACCEL_TIME_FF 0x29 +#define ACCEL_TAP_AXES 0x2A +#define ACCEL_ACT_TAP_STATUS 0x2B +#define ACCEL_BW_RATE 0x2C +#define ACCEL_POWER_CTL 0x2D +#define ACCEL_INT_ENABLE 0x2E +#define ACCEL_INT_MAP 0x2F +#define ACCEL_INT_SOURCE 0x30 +#define ACCEL_DATA_FORMAT 0x31 + + typedef enum {I2C_OP_DONE,I2C_WR_OP,I2C_RD_OP_CMD,I2C_RD_OP_DATA} i2c_op_t; +typedef enum {IMU_GET_ACCEL,IMU_GET_GYRO,IMU_GET_COMPASS} imu_state_t; // private variables // I2C private variables volatile uint8_t i2c_error; volatile i2c_op_t i2c_op; -uint8_t i2c_conf[32]; -uint8_t i2c_data[32]; uint8_t i2c_rd_addr; uint8_t i2c_wr_addr; +uint8_t i2c_data_out[32]; // accelerometer data and configuration const uint8_t accel_id_reg=0x00; const uint8_t accel_id=0xE5; const uint8_t accel_id_len=0x01; const uint8_t accel_conf_reg=0x1D; -const uint8_t accel_conf_len=0x16; +const uint8_t accel_conf_len=0x15; const uint8_t accel_data_reg=0x32; const uint8_t accel_data_len=0x06; +const uint8_t accel_fifo_reg=0x38; +const uint8_t accel_fifo_len=0x01; +const uint8_t accel_status_reg=0x39; +const uint8_t accel_status_len=0x01; const uint8_t accel_rd_addr=0xA6; const uint8_t accel_wr_addr=0xA7; +uint8_t i2c_accel_conf[21]; +uint8_t i2c_accel_fifo_conf; +uint8_t i2c_accel_data[6]; +uint8_t i2c_accel_status; // gyroscope data and configuration const uint8_t gyro_id_reg=0x00; const uint8_t gyro_id=0x68; @@ -71,6 +109,8 @@ const uint8_t gyro_data_reg=0x1B; const uint8_t gyro_data_len=0x08; const uint8_t gyro_rd_addr=0xD0; const uint8_t gyro_wr_addr=0xD1; +uint8_t i2c_gyro_conf[4]; +uint8_t i2c_gyro_data[8]; // compass data adn configuration const uint8_t compass_id_reg=0x0A; const uint8_t compass_id[3]={'H','4','3'}; @@ -81,11 +121,193 @@ const uint8_t compass_data_reg=0x03; const uint8_t compass_data_len=0x06; const uint8_t compass_rd_addr=0x3D; const uint8_t compass_wr_addr=0x3C; +uint8_t i2c_compass_conf[4]; +uint8_t i2c_compass_data[6]; // dma initialization structures; DMA_InitTypeDef IMU_DMA_TX_InitStructure; DMA_InitTypeDef IMU_DMA_RX_InitStructure; +// private functions +void imu_wait_op_done(void) +{ + while(i2c_op!=I2C_OP_DONE); +} + +uint8_t imu_is_op_done(void) +{ + if(i2c_op==I2C_OP_DONE) + return 0x01; + else + return 0x00; +} + +// private accelerometer functions +void imu_accel_get_config(void) +{ + i2c_op=I2C_RD_OP_CMD; + IMU_DMA_RX_InitStructure.DMA_BufferSize=accel_conf_len; + IMU_DMA_RX_InitStructure.DMA_Memory0BaseAddr=(uint32_t)i2c_accel_conf; + DMA_Init(I2C_IMU_DMA_STREAM_RX,&IMU_DMA_RX_InitStructure); + IMU_DMA_TX_InitStructure.DMA_BufferSize=1; + IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr=(uint32_t)&accel_conf_reg; + DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); + i2c_rd_addr=accel_rd_addr; + i2c_wr_addr=accel_wr_addr; + I2C_GenerateSTART(I2C_IMU, ENABLE); + imu_wait_op_done(); +} + +void imu_accel_start(void) +{ + // enter measure mode + i2c_accel_conf[ACCEL_POWER_CTL-ACCEL_THRESH_TAP]|=ACCEL_ENABLE_MEASURE; + i2c_data_out[0]=ACCEL_POWER_CTL; + i2c_data_out[1]=i2c_accel_conf[ACCEL_POWER_CTL-ACCEL_THRESH_TAP]; + // write the fifo configuration + i2c_op=I2C_WR_OP; + IMU_DMA_TX_InitStructure.DMA_BufferSize=2; + IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_data_out; + DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); + i2c_rd_addr=accel_rd_addr; + i2c_wr_addr=accel_wr_addr; + I2C_GenerateSTART(I2C_IMU, ENABLE); + imu_wait_op_done(); +} + +void imu_accel_stop(void) +{ + // enter measure mode + i2c_accel_conf[ACCEL_POWER_CTL-ACCEL_THRESH_TAP]&=~ACCEL_ENABLE_MEASURE; + i2c_data_out[0]=ACCEL_POWER_CTL; + i2c_data_out[1]=i2c_accel_conf[ACCEL_POWER_CTL-ACCEL_THRESH_TAP]; + // write the fifo configuration + i2c_op=I2C_WR_OP; + IMU_DMA_TX_InitStructure.DMA_BufferSize=2; + IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_data_out; + DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); + i2c_rd_addr=accel_rd_addr; + i2c_wr_addr=accel_wr_addr; + I2C_GenerateSTART(I2C_IMU, ENABLE); + imu_wait_op_done(); +} + +void imu_accel_get_data(void) +{ + i2c_op=I2C_RD_OP_CMD; + IMU_DMA_RX_InitStructure.DMA_BufferSize=accel_data_len; + IMU_DMA_RX_InitStructure.DMA_Memory0BaseAddr=(uint32_t)i2c_accel_data; + DMA_Init(I2C_IMU_DMA_STREAM_RX,&IMU_DMA_RX_InitStructure); + IMU_DMA_TX_InitStructure.DMA_BufferSize=1; + IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr=(uint32_t)&accel_data_reg; + DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); + i2c_rd_addr=accel_rd_addr; + i2c_wr_addr=accel_wr_addr; + I2C_GenerateSTART(I2C_IMU, ENABLE); +} + +void imu_accel_set_config(void) +{ + uint8_t i; + + // set the configuration + i2c_accel_conf[ACCEL_BW_RATE-ACCEL_THRESH_TAP]|=ACCEL_RATE_100HZ; + i2c_accel_conf[ACCEL_DATA_FORMAT-ACCEL_THRESH_TAP]&=0xF0; + i2c_accel_conf[ACCEL_DATA_FORMAT-ACCEL_THRESH_TAP]|=ACCEL_RANGE_8G;// +/-8g range + i2c_accel_conf[ACCEL_DATA_FORMAT-ACCEL_THRESH_TAP]|=ACCEL_JUSTIFY_RIGHT;// justify right + i2c_accel_conf[ACCEL_DATA_FORMAT-ACCEL_THRESH_TAP]|=ACCEL_ENABLE_FULL_RES;// enable full resolution according to the range + // write the configuration + for(i=0;i<accel_conf_len;i++) + i2c_data_out[i+1]=i2c_accel_conf[i]; + i2c_data_out[0]=accel_conf_reg; + i2c_op=I2C_WR_OP; + IMU_DMA_TX_InitStructure.DMA_BufferSize=accel_conf_len+1; + IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_data_out; + DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); + i2c_rd_addr=accel_rd_addr; + i2c_wr_addr=accel_wr_addr; + I2C_GenerateSTART(I2C_IMU, ENABLE); + imu_wait_op_done(); + + // set the fifo configuration + i2c_accel_fifo_conf=ACCEL_FIFO_STREAM; + i2c_data_out[0]=accel_fifo_reg; + i2c_data_out[1]=i2c_accel_fifo_conf; + // write the fifo configuration + i2c_op=I2C_WR_OP; + IMU_DMA_TX_InitStructure.DMA_BufferSize=accel_fifo_len+1; + IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_data_out; + DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); + i2c_rd_addr=accel_rd_addr; + i2c_wr_addr=accel_wr_addr; + I2C_GenerateSTART(I2C_IMU, ENABLE); + imu_wait_op_done(); +} + +uint8_t imu_accel_detect(void) +{ + i2c_accel_data[0]=0x00; + i2c_op=I2C_RD_OP_CMD; + IMU_DMA_RX_InitStructure.DMA_BufferSize=accel_id_len; + IMU_DMA_RX_InitStructure.DMA_Memory0BaseAddr=(uint32_t)i2c_accel_data; + DMA_Init(I2C_IMU_DMA_STREAM_RX,&IMU_DMA_RX_InitStructure); + IMU_DMA_TX_InitStructure.DMA_BufferSize=1; + IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr=(uint32_t)&accel_id_reg; + DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); + i2c_rd_addr=accel_rd_addr; + i2c_wr_addr=accel_wr_addr; + I2C_GenerateSTART(I2C_IMU, ENABLE); + imu_wait_op_done(); + if(i2c_accel_data[0]==accel_id) + { + imu_accel_get_config(); + imu_accel_set_config(); + return 0x01; + } + else + return 0x00; +} + +void imu_accel_process_data(void) +{ + uint8_t i; + int16_t value; + + for(i=0;i<3;i++) + { + value=((int16_t)(i2c_accel_data[i*2]+(i2c_accel_data[i*2+1]<<8)))<<2; + ram_data[BIOLOID_IMU_ACCEL_X_L+i*2]=value&0xFF; + ram_data[BIOLOID_IMU_ACCEL_X_H+i*2]=(value>>8); + } +} + // interrupt handlers +void IMU_TIMER_IRQHandler(void) +{ + static imu_state_t state=IMU_GET_COMPASS; + uint16_t capture; + + if(TIM_GetITStatus(IMU_TIMER, TIM_IT_CC1)!=RESET) + { + TIM_ClearITPendingBit(IMU_TIMER,TIM_IT_CC1); + capture = TIM_GetCapture1(IMU_TIMER); + TIM_SetCompare1(IMU_TIMER, capture + 1000); + if(imu_is_op_done()) + { + switch(state) + { + case IMU_GET_ACCEL: imu_accel_get_data(); + state=IMU_GET_GYRO; + break; + case IMU_GET_GYRO: imu_accel_process_data(); + state=IMU_GET_COMPASS; + break; + case IMU_GET_COMPASS: state=IMU_GET_ACCEL; + break; + } + } + } +} + void I2C_IMU_EV_IRQHandler(void) { switch (I2C_GetLastEvent(I2C_IMU)) @@ -117,6 +339,14 @@ void I2C_IMU_EV_IRQHandler(void) DMA_Cmd(I2C_IMU_DMA_STREAM_RX, ENABLE); break; + case I2C_EVENT_MASTER_BYTE_TRANSMITTED: + if(i2c_op==I2C_WR_OP) + { + i2c_op=I2C_OP_DONE; + I2C_GenerateSTOP(I2C_IMU, ENABLE); + } + break; + default: break; } @@ -149,11 +379,6 @@ void I2C_IMU_TX_DMA_IRQHandler(void) I2C_GenerateSTART(I2C_IMU, ENABLE); i2c_op=I2C_RD_OP_DATA; } - else - { - I2C_GenerateSTOP(I2C_IMU, ENABLE); - i2c_op=I2C_OP_DONE; - } } void I2C_IMU_RX_DMA_IRQHandler(void) @@ -165,115 +390,23 @@ void I2C_IMU_RX_DMA_IRQHandler(void) i2c_op=I2C_OP_DONE; } -// private functions -void imu_wait_op_done(void) -{ - while(i2c_op!=I2C_OP_DONE); -} - -uint8_t imu_is_op_done(void) -{ - if(i2c_op==I2C_OP_DONE) - return 0x01; - else - return 0x00; -} - -// accelerometer public functions -uint8_t imu_accel_detect(void) -{ - i2c_op=I2C_RD_OP_CMD; - IMU_DMA_RX_InitStructure.DMA_BufferSize=accel_id_len; - IMU_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_data; - DMA_Init(I2C_IMU_DMA_STREAM_RX,&IMU_DMA_RX_InitStructure); - IMU_DMA_TX_InitStructure.DMA_BufferSize=1; - IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_conf; - DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); - i2c_conf[0]=accel_id_reg; - i2c_data[0]=0x00; - i2c_rd_addr=accel_rd_addr; - i2c_wr_addr=accel_wr_addr; - I2C_GenerateSTART(I2C_IMU, ENABLE); - - imu_wait_op_done(); - if(i2c_data[0]==accel_id) - return 0x01; - else - return 0x00; -} - -void imu_accel_set_offset(uint8_t off_x, uint8_t off_y, uint8_t off_z) -{ - -} - -void imu_accel_set_data_rate(uint8_t rate_hz) -{ - -} - -void imu_accel_set_measure_mode(void) -{ - -} - -void imu_accel_set_sleep_mode(void) -{ - -} - -void imu_accel_set_sleep_rate(uint8_t rate_hz) -{ - -} - -void imu_accel_set_range(uint8_t range) -{ - -} - -void imu_accel_justify_left(void) -{ - -} - -void imu_accel_justify_right(void) -{ - -} - -void imu_accel_config(void) -{ - i2c_op=I2C_WR_OP; - IMU_DMA_TX_InitStructure.DMA_BufferSize=accel_conf_len+1; - IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_conf; - DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); - i2c_conf[0]=accel_conf_reg; - i2c_conf[15]=0x0A; - i2c_conf[20]=0x02; - i2c_rd_addr=accel_rd_addr; - i2c_wr_addr=accel_wr_addr; - I2C_GenerateSTART(I2C_IMU, ENABLE); -} - // gyroscope public functions uint8_t imu_gyro_detect(void) { i2c_op=I2C_RD_OP_CMD; IMU_DMA_RX_InitStructure.DMA_BufferSize=gyro_id_len; - IMU_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_data; + IMU_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_gyro_data; DMA_Init(I2C_IMU_DMA_STREAM_RX,&IMU_DMA_RX_InitStructure); IMU_DMA_TX_InitStructure.DMA_BufferSize=1; - IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_conf; + IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&gyro_id_reg; DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); - i2c_conf[0]=gyro_id_reg; - i2c_data[0]=0x00; + i2c_gyro_data[0]=0x00; i2c_rd_addr=gyro_rd_addr; i2c_wr_addr=gyro_wr_addr; I2C_GenerateSTART(I2C_IMU, ENABLE); imu_wait_op_done(); - if((i2c_data[0]&0x7E)==gyro_id) + if((i2c_gyro_data[0]&0x7E)==gyro_id) return 0x01; else return 0x00; @@ -284,21 +417,20 @@ uint8_t imu_compass_detect(void) { i2c_op=I2C_RD_OP_CMD; IMU_DMA_RX_InitStructure.DMA_BufferSize=compass_id_len; - IMU_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_data; + IMU_DMA_RX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_compass_data; DMA_Init(I2C_IMU_DMA_STREAM_RX,&IMU_DMA_RX_InitStructure); IMU_DMA_TX_InitStructure.DMA_BufferSize=1; - IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)i2c_conf; + IMU_DMA_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&compass_id_reg; DMA_Init(I2C_IMU_DMA_STREAM_TX,&IMU_DMA_TX_InitStructure); - i2c_conf[0]=compass_id_reg; - i2c_data[0]=0x00; - i2c_data[1]=0x00; - i2c_data[2]=0x00; + i2c_compass_data[0]=0x00; + i2c_compass_data[1]=0x00; + i2c_compass_data[2]=0x00; i2c_rd_addr=compass_rd_addr; i2c_wr_addr=compass_wr_addr; I2C_GenerateSTART(I2C_IMU, ENABLE); imu_wait_op_done(); - if(i2c_data[0]==compass_id[0] && i2c_data[1]==compass_id[1] && i2c_data[2]==compass_id[2]) + if(i2c_compass_data[0]==compass_id[0] && i2c_compass_data[1]==compass_id[1] && i2c_compass_data[2]==compass_id[2]) return 0x01; else return 0x00; @@ -308,7 +440,8 @@ uint8_t imu_compass_detect(void) void imu_init(void) { uint8_t i; - + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; I2C_InitTypeDef I2C_InitStructure; @@ -322,6 +455,8 @@ void imu_init(void) RCC_AHB1PeriphClockCmd(I2C_IMU_SCL_GPIO_CLK, ENABLE); /* Enable the DMA clock */ RCC_AHB1PeriphClockCmd(DMA_IMU_CLK, ENABLE); + /* Enable the IMU timer clock */ + RCC_APB1PeriphClockCmd(IMU_TIMER_CLK,ENABLE); /* GPIO Configuration */ /*Configure I2C SCL pin */ @@ -369,10 +504,7 @@ void imu_init(void) i2c_error=0x00; i2c_op=I2C_OP_DONE; for(i=0;i<32;i++) - { - i2c_data[i]=0x00; - i2c_conf[i]=0x00; - } + i2c_data_out[i]=0x00; /* configure DMA TX */ DMA_DeInit(I2C_IMU_DMA_STREAM_TX); IMU_DMA_TX_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; @@ -420,4 +552,65 @@ void imu_init(void) NVIC_Init(&NVIC_InitStructure); DMA_ITConfig(I2C_IMU_DMA_STREAM_RX,DMA_IT_TC,ENABLE); DMA_ITConfig(I2C_IMU_DMA_STREAM_RX,DMA_IT_HT | DMA_IT_TE | DMA_IT_FE | DMA_IT_DME,DISABLE); + + // configure the timer + // initialize the timer interrupts + NVIC_InitStructure.NVIC_IRQChannel = IMU_TIMER_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + /* motion timer configuration */ + TIM_TimeBaseStructure.TIM_Period = 0xFFFF; + TIM_TimeBaseStructure.TIM_Prescaler = 82; + TIM_TimeBaseStructure.TIM_ClockDivision = 0; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit(IMU_TIMER,&TIM_TimeBaseStructure); + TIM_SetClockDivision(IMU_TIMER,TIM_CKD_DIV1); + + TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; + TIM_OCInitStructure.TIM_Pulse = 1000;// 1ms period + TIM_OC1Init(IMU_TIMER, &TIM_OCInitStructure); + TIM_OC1PreloadConfig(IMU_TIMER, TIM_OCPreload_Disable); + + /* detect the three sensors in the imu */ + if(imu_accel_detect()) + ram_set_bit(BIOLOID_IMU_STATUS,1); + else + ram_clear_bit(BIOLOID_IMU_STATUS,1); + if(imu_gyro_detect()) + ram_set_bit(BIOLOID_IMU_STATUS,2); + else + ram_clear_bit(BIOLOID_IMU_STATUS,2); + if(imu_compass_detect()) + ram_set_bit(BIOLOID_IMU_STATUS,3); + else + ram_clear_bit(BIOLOID_IMU_STATUS,3); +} + +void imu_start(void) +{ + // start the accelerometer + imu_accel_start(); + + // start the timer to get the imu data + TIM_Cmd(IMU_TIMER, ENABLE); + TIM_ITConfig(IMU_TIMER, TIM_IT_CC1, ENABLE); + + ram_set_bit(BIOLOID_IMU_STATUS,0); +} + +void imu_stop(void) +{ + // stop the timer to get the imu data + TIM_Cmd(IMU_TIMER, DISABLE); + TIM_ITConfig(IMU_TIMER, TIM_IT_CC1, DISABLE); + + // stop the accelerometer + imu_accel_stop(); + + ram_clear_bit(BIOLOID_IMU_STATUS,0); } diff --git a/src/motion_manager.c b/src/motion_manager.c index e79cbc0456ed37241bb6710464c68a22fceb0904..c7dc63d94f1ae580ce8b2ad454eb0da7e333d85a 100644 --- a/src/motion_manager.c +++ b/src/motion_manager.c @@ -12,7 +12,6 @@ // private variables __IO uint16_t manager_motion_period; uint8_t manager_num_servos; -uint8_t manager_enabled; TServoInfo manager_servos[MANAGER_MAX_NUM_SERVOS]; // private functions @@ -40,7 +39,7 @@ inline uint16_t manager_angle_to_value(uint8_t servo_id,int16_t angle) inline int16_t manager_value_to_angle(uint8_t servo_id,uint16_t value) { - return (value*manager_servos[servo_id].max_angle)/manager_servos[servo_id].encoder_resolution-manager_servos[servo_id].center_angle; + return (((value*manager_servos[servo_id].max_angle)/manager_servos[servo_id].encoder_resolution)-manager_servos[servo_id].center_angle); } inline uint16_t manager_speed_to_value(uint8_t servo_id,uint16_t speed) @@ -55,6 +54,29 @@ inline uint16_t manager_value_to_speed(uint8_t servo_id,uint16_t value) return (value*2)/3; } +void manager_get_current_position(void) +{ + uint8_t i; + + for(i=0;i<MANAGER_MAX_NUM_SERVOS;i++) + { + if(manager_servos[i].model!=0x0000)// servo is present + { + if(manager_servos[i].enabled)// servo is enabled + { + // the current position is fixed by one of the motion modules + } + else// servo is disabled + { + dyn_master_read_word(manager_servos[i].id,P_PRESENT_POSITION_L,&manager_servos[i].current_value); + manager_servos[i].current_angle=manager_value_to_angle(i,manager_servos[i].current_value); + ram_data[BIOLOID_MM_SERVO0_CUR_POS_L+i*2]=(manager_servos[i].current_angle&0xFF); + ram_data[BIOLOID_MM_SERVO0_CUR_POS_H+i*2]=(manager_servos[i].current_angle>>8); + } + } + } +} + // interrupt handlers void MOTION_TIMER_IRQHandler(void) { @@ -75,6 +97,7 @@ void MOTION_TIMER_IRQHandler(void) // manager_balance(); // send the motion commands to the servos // manager_send_motion_command(); + manager_get_current_position(); } } @@ -103,62 +126,62 @@ void manager_init(uint16_t period_us) { case SERVO_AX12A: manager_servos[i].encoder_resolution=1023; manager_servos[i].gear_ratio=254; - manager_servos[i].max_angle=3000; - manager_servos[i].center_angle=1500; + manager_servos[i].max_angle=300<<7; + manager_servos[i].center_angle=150<<7; manager_servos[i].max_speed=354; break; case SERVO_AX12W: manager_servos[i].encoder_resolution=1023; manager_servos[i].gear_ratio=32; - manager_servos[i].max_angle=3000; - manager_servos[i].center_angle=1500; + manager_servos[i].max_angle=300<<7; + manager_servos[i].center_angle=150<<7; manager_servos[i].max_speed=2830; break; case SERVO_AX18A: manager_servos[i].encoder_resolution=1023; manager_servos[i].gear_ratio=254; - manager_servos[i].max_angle=3000; - manager_servos[i].center_angle=1500; + manager_servos[i].max_angle=300<<7; + manager_servos[i].center_angle=150<<7; manager_servos[i].max_speed=582; break; case SERVO_MX28: manager_servos[i].encoder_resolution=4095; manager_servos[i].gear_ratio=193; - manager_servos[i].max_angle=3600; - manager_servos[i].center_angle=1800; + manager_servos[i].max_angle=360<<7; + manager_servos[i].center_angle=180<<7; manager_servos[i].max_speed=330; break; case SERVO_RX24F: manager_servos[i].encoder_resolution=1023; manager_servos[i].gear_ratio=193; - manager_servos[i].max_angle=3000; - manager_servos[i].center_angle=1500; + manager_servos[i].max_angle=300<<7; + manager_servos[i].center_angle=150<<7; manager_servos[i].max_speed=756; break; case SERVO_RX28: manager_servos[i].encoder_resolution=1023; manager_servos[i].gear_ratio=193; - manager_servos[i].max_angle=3000; - manager_servos[i].center_angle=1500; + manager_servos[i].max_angle=300<<7; + manager_servos[i].center_angle=150<<7; manager_servos[i].max_speed=402; break; case SERVO_RX64: manager_servos[i].encoder_resolution=1023; manager_servos[i].gear_ratio=200; - manager_servos[i].max_angle=3000; - manager_servos[i].center_angle=1500; + manager_servos[i].max_angle=300<<7; + manager_servos[i].center_angle=150<<7; manager_servos[i].max_speed=294; break; case SERVO_MX64: manager_servos[i].encoder_resolution=4095; manager_servos[i].gear_ratio=200; - manager_servos[i].max_angle=3600; - manager_servos[i].center_angle=1800; + manager_servos[i].max_angle=360<<7; + manager_servos[i].center_angle=180<<7; manager_servos[i].max_speed=378; break; case SERVO_EX106: manager_servos[i].encoder_resolution=1023; manager_servos[i].gear_ratio=184; - manager_servos[i].max_angle=2500; - manager_servos[i].center_angle=1250; + manager_servos[i].max_angle=250<<7; + manager_servos[i].center_angle=125<<7; manager_servos[i].max_speed=414; break; case SERVO_MX106: manager_servos[i].encoder_resolution=4095; manager_servos[i].gear_ratio=225; - manager_servos[i].max_angle=3600; - manager_servos[i].center_angle=1800; + manager_servos[i].max_angle=360<<7; + manager_servos[i].center_angle=180<<7; manager_servos[i].max_speed=270; break; default: break; @@ -170,6 +193,8 @@ void manager_init(uint16_t period_us) // get the servo's current position dyn_master_read_word(manager_servos[i].id,P_PRESENT_POSITION_L,&manager_servos[i].current_value); manager_servos[i].current_angle=manager_value_to_angle(i,manager_servos[i].current_value); + ram_data[BIOLOID_MM_SERVO0_CUR_POS_L+i*2]=(manager_servos[i].current_angle&0xFF); + ram_data[BIOLOID_MM_SERVO0_CUR_POS_H+i*2]=(manager_servos[i].current_angle>>8); manager_num_servos++; } else @@ -202,7 +227,6 @@ void manager_init(uint16_t period_us) TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(MOTION_TIMER,&TIM_TimeBaseStructure); - TIM_Cmd(MOTION_TIMER, ENABLE); TIM_SetClockDivision(MOTION_TIMER,TIM_CKD_DIV1); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; @@ -212,9 +236,8 @@ void manager_init(uint16_t period_us) TIM_OCInitStructure.TIM_Pulse = manager_motion_period; TIM_OC1Init(MOTION_TIMER, &TIM_OCInitStructure); TIM_OC1PreloadConfig(MOTION_TIMER, TIM_OCPreload_Disable); - TIM_ITConfig(MOTION_TIMER, TIM_IT_CC1, ENABLE); - manager_enabled=0x00; + ram_clear_bit(BIOLOID_MM_STATUS,0); } uint16_t manager_get_period(void) @@ -231,19 +254,19 @@ inline void manager_enable(void) { TIM_Cmd(MOTION_TIMER, ENABLE); TIM_ITConfig(MOTION_TIMER, TIM_IT_CC1, ENABLE); - manager_enabled=0x01; + ram_set_bit(BIOLOID_MM_STATUS,0); } inline void manager_disable(void) { TIM_Cmd(MOTION_TIMER, DISABLE); TIM_ITConfig(MOTION_TIMER, TIM_IT_CC1, DISABLE); - manager_enabled=0x00; + ram_clear_bit(BIOLOID_MM_STATUS,0); } inline uint8_t manager_is_enabled(void) { - return manager_enabled; + return ram_data[BIOLOID_MM_STATUS]&0x01; } inline uint8_t manager_get_num_servos(void)