Hardware components | ||||||
![]() |
| × | 1 |
The aim was to improve Roberto... our intrepid BLE controlled robot... by both utilizing the bridge connector and three servos and by giving him a brand spanking new shell.
1 / 3
Untitled file
Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).
/*******************************************************
* --- Hexapod Spider A.K.A. "Roberto II" ---
* Main Application. Runs in a nRF51822 (cortex M0 + BLE)
* Author: Daniel Mancuso.
*******************************************************/
#include "nrf_pwm.h"
//Hardware pinout definitions:
#define PWM_CH0 15 //Front Legs
#define PWM_CH1 16 //Side Legs (2 servos)
#define PWM_TIMER_INTERVAL 20 //tick interval (check real lenght)
#define PWM_MIN 132 // 1ms --> -45 degrees
#define PWM_CENTER PWM_MIN + (PWM_MAX-PWM_MIN)/2 // 1.5ms --> 0 degrees
#define PWM_MAX 264 // 2ms --> +45 degrees
#define FRONT_LEGS_LIMIT 37
#define SIDE_LEGS_LIMIT 17
#define MOVING_SPEED 9
//BLE Control Commands for the Hexapod:
#define STOP 0
#define MOVE_FORWARD 1
#define MOVE_BACKWARD 2
#define MOVE_LEFT 3
#define MOVE_RIGHT 4
#define SHAKE 5
sensor_bridge_t sensor_bridge;
struct channel{
uint16_t actual_position;
uint16_t final_position; //should be simetrical
uint16_t max_position;
uint16_t min_position;
uint16_t center_position;
uint8_t direction;
uint8_t speed;
};
typedef struct{
uint8_t movement_cmd;
uint8_t current_frame;
uint8_t frame_end_flag;
uint8_t frame_length;
uint16_t i;
struct channel ch0;
struct channel ch1;
}hexapod_struct;
static hexapod_struct hexapod;
// ---------------------------------------
// --- Initialization ---
// ---------------------------------------
void pwm_init(void){
nrf_pwm_config_t pwm_config = PWM_DEFAULT_CONFIG;
pwm_config.mode = PWM_MODE_SERVOS;
pwm_config.num_channels = 2;
pwm_config.gpio_num[0] = PWM_CH0;
pwm_config.gpio_num[1] = PWM_CH1;
//pwm_config.gpio_num[2] = 10;
// Initialize the PWM library
nrf_pwm_init(&pwm_config);
hexapod.current_frame = 0;
hexapod.frame_end_flag = 0;
hexapod.movement_cmd = 0;
hexapod.ch0.speed = MOVING_SPEED;//5; //here we can adjust speed of center legs servo
hexapod.ch0.min_position = PWM_MIN + FRONT_LEGS_LIMIT;
hexapod.ch0.max_position = PWM_MAX - FRONT_LEGS_LIMIT;
hexapod.ch1.speed = MOVING_SPEED;//14; //here we can adjust speed of side legs servos
hexapod.ch1.min_position = PWM_MIN + SIDE_LEGS_LIMIT;
hexapod.ch1.max_position = PWM_MAX - SIDE_LEGS_LIMIT;
hexapod.ch0.center_position = hexapod.ch0.min_position + (hexapod.ch0.max_position-hexapod.ch0.min_position)/2;
hexapod.ch1.center_position = hexapod.ch1.min_position + (hexapod.ch1.max_position-hexapod.ch1.min_position)/2;
hexapod.frame_length = (hexapod.ch1.max_position - hexapod.ch1.min_position) / hexapod.ch1.speed;
hexapod.ch0.actual_position = hexapod.ch0.center_position;
hexapod.ch1.actual_position = hexapod.ch1.center_position;
nrf_pwm_set_value(0, hexapod.ch0.actual_position);
nrf_pwm_set_value(1, hexapod.ch1.actual_position);
}
/**
** uint8_t Update_servos(void)
**
** Checks if actual_position is inside the limits and set the PWM value.
** input: none
** output: 1 on Excedded limit
** 0 OK
**/
uint8_t Update_servos(void)
{
if ((hexapod.ch0.actual_position > hexapod.ch0.max_position)
|| (hexapod.ch1.actual_position > hexapod.ch1.max_position)
|| (hexapod.ch0.actual_position min
if ((frames[current_f][0] == -1) &&
hexapod.ch0.actual_position >= (hexapod.ch0.min_position + hexapod.ch0.speed))
hexapod.ch0.actual_position -= hexapod.ch0.speed;
//ch0 aproaching center from rigth
if ((frames[current_f][0] == 0) &&
hexapod.ch0.actual_position >= (hexapod.ch0.center_position + hexapod.ch0.speed))
hexapod.ch0.actual_position -= hexapod.ch0.speed;
//ch0 aproaching center from left
if ((frames[current_f][0] == 0) &&
hexapod.ch0.actual_position max
if ((frames[current_f][0] == 1) &&
hexapod.ch0.actual_position min
if ((frames[current_f][1] == -1) &&
hexapod.ch1.actual_position >= (hexapod.ch1.min_position + hexapod.ch1.speed))
hexapod.ch1.actual_position -= hexapod.ch1.speed;
//ch1 aproaching center from rigth
if ((frames[current_f][1] == 0) &&
hexapod.ch1.actual_position >= (hexapod.ch1.center_position + hexapod.ch1.speed))
hexapod.ch1.actual_position -= hexapod.ch1.speed;
//ch1 aproaching center from left
if ((frames[current_f][1] == 0) &&
hexapod.ch1.actual_position max
if ((frames[current_f][1] == 1) &&
hexapod.ch1.actual_position positive angles (move right), 0 -> negative (left)
//Frame: Central Legs angle(CH0): Front/Back Legs angle(CH1):
// 0 0 0
// 1 +45 +45
// 2 +45 -45
// 3 -45 -45
// 4 -45 +45
//note: CenterLegs positive -> anti-clockwise
// Side legs positive -> clockwise
// +1: Max_position
// -1: Min_position
// 0: Center_position
// i: Frame number, j: channel number
const int8_t forward[4][2] = {{-1,1},{-1,-1},{ 1,-1},{ 1,1}};//{{1,-1},{-1,-1},{ -1,1},{ 1,1}};
const int8_t backward[4][2] = {{ 1,1},{ 1,-1},{-1,-1},{-1,1}};
const int8_t left[4][2] = {{-1,-1},{ 0, 1},{-1,-1},{0,1}};
const int8_t right[4][2] = {{ 1, 1},{ 0,-1},{1, 1},{ 0,-1}}; //trying turns limiting position of center legs (CH0)
int16_t shake[] = {1, 10, 20, 28, 20, 10, 0, -10, -20, -5, 10, -15, -5, -12, -7};
static uint8_t shake_i = 0;
switch (hexapod.movement_cmd){
case MOVE_FORWARD:
update_channels_end(forward, hexapod.current_frame);
break;
case MOVE_BACKWARD:
update_channels_end(backward, hexapod.current_frame);
break;
case MOVE_LEFT:
update_channels_end(left, hexapod.current_frame);
break;
case MOVE_RIGHT:
update_channels_end(right, hexapod.current_frame);
break;
case SHAKE:
if (shake_i++ >= (uint8_t)sizeof(shake)) shake_i=0;
hexapod.ch0.actual_position = hexapod.ch0.center_position + shake[shake_i];
hexapod.ch1.actual_position = hexapod.ch1.center_position + shake[shake_i];
Update_servos();
break;
}
if (hexapod.i++ >= hexapod.frame_length){
hexapod.i = 0;
if (hexapod.current_frame++ >= 3)
hexapod.current_frame = 0;
}
}
/////////////////////////////////////////////////////////////////////////
/**@brief Application tick handler.
*
* @param[in] ctx Value that will be passed back to the callback
*
* @retval None.
*/
void app_tick_handler(void * ctx) //void pwm_tick_handler(void * ctx)
{
update_hexapod(ctx);
}
/////////////////////////////////////////////////////////////////////////
void my_characteristic_write_callback(ble_characteristic_info_t* char_info, uint16_t offset, uint16_t len, uint8_t* data)
{
uint32_t pwm_value;
if ((char_info == &characteristic_sensorData_w_info) && (offset == 0) && (len == sizeof(sensor_bridge.data_w.packet)))
{
memcpy((uint8_t*)&sensor_bridge.data_w, data, len);
if (sensor_bridge.data_w.packet[0]
hexapod.movement_cmd = sensor_bridge.data_w.packet[0];
hexapod.current_frame = 0;
hexapod.frame_end_flag = 0;
}
if (sensor_bridge.data_w.packet[1]
/*******************************************************
* --- Hexapod Spider A.K.A. "Roberto II" ---
* Main Application. Runs in a nRF51822 (cortex M0 + BLE)
* Author: Daniel Mancuso.
*******************************************************/
#include "nrf_pwm.h"
//Hardware pinout definitions:
#define PWM_CH0 15 //Front Legs
#define PWM_CH1 16 //Side Legs (2 servos)
#define PWM_TIMER_INTERVAL 20 //tick interval (check real lenght)
#define PWM_MIN 132 // 1ms --> -45 degrees
#define PWM_CENTER PWM_MIN + (PWM_MAX-PWM_MIN)/2 // 1.5ms --> 0 degrees
#define PWM_MAX 264 // 2ms --> +45 degrees
#define FRONT_LEGS_LIMIT 37
#define SIDE_LEGS_LIMIT 17
#define MOVING_SPEED 9
//BLE Control Commands for the Hexapod:
#define STOP 0
#define MOVE_FORWARD 1
#define MOVE_BACKWARD 2
#define MOVE_LEFT 3
#define MOVE_RIGHT 4
#define SHAKE 5
sensor_bridge_t sensor_bridge;
struct channel{
uint16_t actual_position;
uint16_t final_position; //should be simetrical
uint16_t max_position;
uint16_t min_position;
uint16_t center_position;
uint8_t direction;
uint8_t speed;
};
typedef struct{
uint8_t movement_cmd;
uint8_t current_frame;
uint8_t frame_end_flag;
uint8_t frame_length;
uint16_t i;
struct channel ch0;
struct channel ch1;
}hexapod_struct;
static hexapod_struct hexapod;
// ---------------------------------------
// --- Initialization ---
// ---------------------------------------
void pwm_init(void){
nrf_pwm_config_t pwm_config = PWM_DEFAULT_CONFIG;
pwm_config.mode = PWM_MODE_SERVOS;
pwm_config.num_channels = 2;
pwm_config.gpio_num[0] = PWM_CH0;
pwm_config.gpio_num[1] = PWM_CH1;
//pwm_config.gpio_num[2] = 10;
// Initialize the PWM library
nrf_pwm_init(&pwm_config);
hexapod.current_frame = 0;
hexapod.frame_end_flag = 0;
hexapod.movement_cmd = 0;
hexapod.ch0.speed = MOVING_SPEED;//5; //here we can adjust speed of center legs servo
hexapod.ch0.min_position = PWM_MIN + FRONT_LEGS_LIMIT;
hexapod.ch0.max_position = PWM_MAX - FRONT_LEGS_LIMIT;
hexapod.ch1.speed = MOVING_SPEED;//14; //here we can adjust speed of side legs servos
hexapod.ch1.min_position = PWM_MIN + SIDE_LEGS_LIMIT;
hexapod.ch1.max_position = PWM_MAX - SIDE_LEGS_LIMIT;
hexapod.ch0.center_position = hexapod.ch0.min_position + (hexapod.ch0.max_position-hexapod.ch0.min_position)/2;
hexapod.ch1.center_position = hexapod.ch1.min_position + (hexapod.ch1.max_position-hexapod.ch1.min_position)/2;
hexapod.frame_length = (hexapod.ch1.max_position - hexapod.ch1.min_position) / hexapod.ch1.speed;
hexapod.ch0.actual_position = hexapod.ch0.center_position;
hexapod.ch1.actual_position = hexapod.ch1.center_position;
nrf_pwm_set_value(0, hexapod.ch0.actual_position);
nrf_pwm_set_value(1, hexapod.ch1.actual_position);
}
/**
** uint8_t Update_servos(void)
**
** Checks if actual_position is inside the limits and set the PWM value.
** input: none
** output: 1 on Excedded limit
** 0 OK
**/
uint8_t Update_servos(void)
{
if ((hexapod.ch0.actual_position > hexapod.ch0.max_position)
|| (hexapod.ch1.actual_position > hexapod.ch1.max_position)
|| (hexapod.ch0.actual_position min
if ((frames[current_f][0] == -1) &&
hexapod.ch0.actual_position >= (hexapod.ch0.min_position + hexapod.ch0.speed))
hexapod.ch0.actual_position -= hexapod.ch0.speed;
//ch0 aproaching center from rigth
if ((frames[current_f][0] == 0) &&
hexapod.ch0.actual_position >= (hexapod.ch0.center_position + hexapod.ch0.speed))
hexapod.ch0.actual_position -= hexapod.ch0.speed;
//ch0 aproaching center from left
if ((frames[current_f][0] == 0) &&
hexapod.ch0.actual_position max
if ((frames[current_f][0] == 1) &&
hexapod.ch0.actual_position min
if ((frames[current_f][1] == -1) &&
hexapod.ch1.actual_position >= (hexapod.ch1.min_position + hexapod.ch1.speed))
hexapod.ch1.actual_position -= hexapod.ch1.speed;
//ch1 aproaching center from rigth
if ((frames[current_f][1] == 0) &&
hexapod.ch1.actual_position >= (hexapod.ch1.center_position + hexapod.ch1.speed))
hexapod.ch1.actual_position -= hexapod.ch1.speed;
//ch1 aproaching center from left
if ((frames[current_f][1] == 0) &&
hexapod.ch1.actual_position max
if ((frames[current_f][1] == 1) &&
hexapod.ch1.actual_position positive angles (move right), 0 -> negative (left)
//Frame: Central Legs angle(CH0): Front/Back Legs angle(CH1):
// 0 0 0
// 1 +45 +45
// 2 +45 -45
// 3 -45 -45
// 4 -45 +45
//note: CenterLegs positive -> anti-clockwise
// Side legs positive -> clockwise
// +1: Max_position
// -1: Min_position
// 0: Center_position
// i: Frame number, j: channel number
const int8_t forward[4][2] = {{-1,1},{-1,-1},{ 1,-1},{ 1,1}};//{{1,-1},{-1,-1},{ -1,1},{ 1,1}};
const int8_t backward[4][2] = {{ 1,1},{ 1,-1},{-1,-1},{-1,1}};
const int8_t left[4][2] = {{-1,-1},{ 0, 1},{-1,-1},{0,1}};
const int8_t right[4][2] = {{ 1, 1},{ 0,-1},{1, 1},{ 0,-1}}; //trying turns limiting position of center legs (CH0)
int16_t shake[] = {1, 10, 20, 28, 20, 10, 0, -10, -20, -5, 10, -15, -5, -12, -7};
static uint8_t shake_i = 0;
switch (hexapod.movement_cmd){
case MOVE_FORWARD:
update_channels_end(forward, hexapod.current_frame);
break;
case MOVE_BACKWARD:
update_channels_end(backward, hexapod.current_frame);
break;
case MOVE_LEFT:
update_channels_end(left, hexapod.current_frame);
break;
case MOVE_RIGHT:
update_channels_end(right, hexapod.current_frame);
break;
case SHAKE:
if (shake_i++ >= (uint8_t)sizeof(shake)) shake_i=0;
hexapod.ch0.actual_position = hexapod.ch0.center_position + shake[shake_i];
hexapod.ch1.actual_position = hexapod.ch1.center_position + shake[shake_i];
Update_servos();
break;
}
if (hexapod.i++ >= hexapod.frame_length){
hexapod.i = 0;
if (hexapod.current_frame++ >= 3)
hexapod.current_frame = 0;
}
}
/////////////////////////////////////////////////////////////////////////
/**@brief Application tick handler.
*
* @param[in] ctx Value that will be passed back to the callback
*
* @retval None.
*/
void app_tick_handler(void * ctx) //void pwm_tick_handler(void * ctx)
{
update_hexapod(ctx);
}
/////////////////////////////////////////////////////////////////////////
void my_characteristic_write_callback(ble_characteristic_info_t* char_info, uint16_t offset, uint16_t len, uint8_t* data)
{
uint32_t pwm_value;
if ((char_info == &characteristic_sensorData_w_info) && (offset == 0) && (len == sizeof(sensor_bridge.data_w.packet)))
{
memcpy((uint8_t*)&sensor_bridge.data_w, data, len);
if (sensor_bridge.data_w.packet[0]
hexapod.movement_cmd = sensor_bridge.data_w.packet[0];
hexapod.current_frame = 0;
hexapod.frame_end_flag = 0;
}
if (sensor_bridge.data_w.packet[1]
daniel mancuso
2 projects • 34 followers
Electronic Engineer. Embedded systems design, MCUs, IoT, RTOS, enjoy trying out new technologies. Founder - Lead Engineer @ OhmTech.io
Comments