本项目为一款蓝牙跳蛋的设计,主控芯片为BL602,通过PWM控制震动马达的转速实现不同的震动强度变化,通过蓝牙连接设备,APP下发蓝牙指令实现设备的控制。
项目地址:
蓝牙初始化:
void do_ble_init(void){
// Initialize BLE controller
LOGI(TAG, //代码效果参考:http://hnjlyzjd.com/xl/wz_24241.html
"do_ble_init ");ble_controller_init(configMAX_PRIORITIES - 1);
//Initialize BLE Host stack
hci_driver_init();
bt_enable(bt_ready_cb);
bt_set_name("LVS-Lush122-XT");
bt_gatt_service_register((struct bt_gatt_service )&dis);
notify_attrs = &ble_attrs【1】;
bt_conn_cb_register(&conn_callbacks);
ble_start_advertise();
}
蓝牙接收到的数据处理:
//蓝牙处理函数
static void ble_reve_cb(struct bt_conn conn, const char buf, u16_t len){
char cmd【30】 = "";
char data【15】 = "";
char ret_str【20】 = "OK";
//LOGI(TAG, "ble_reve_buf: %s", buf);
//do_ble_notify(conn, ret_str, strlen(ret_str));
char dp = strchr(buf,';');
if(dp == NULL){
return;
}else{
dp = '\0';
}
LOGI(TAG, "ble_reve_buf: %s", buf);
char p = strchr(buf,':');
if(p != NULL){
strncpy(cmd, buf, p-buf);
strncpy(data, p+1, len-(int)(p-buf)-2);
}else{
strcpy(cmd, buf);
cmd【len-1】 = '\0';
}
LOGI(TAG, "cmd: %s data: %s", cmd, data);
if(CDM_CMP(cmd, "Status")){
LOGI(TAG, "get Status");
do_ble_notify(conn, ret_str, strlen(ret_str));
}
else if(CDM_CMP(cmd, "Vibrate")){ //蓝牙在线模式控制
LOGI(TAG, "set Vibrate");
vibrate = atoi(data);
Preset=0;
current_Preset=0;
//do_ble_notify(conn, ret_str, strlen(ret_str));
}
else if(CDM_CMP(cmd, "Preset")){ //9种预设模式选择
LOGI(TAG, "set Vibrate");
Preset = atoi(data);
}
else if(CDM_CMP(cmd, "Battery")){ //获取电量
int32_t percent=get_battery(); //电池百分比
if(percent==100) {ret_str【0】='1';ret_str【1】='0';ret_str【2】='0';}
else{
int8_t shiwei= percent/10; int8_t gewei= percent%10;
ret_str【0】='0';
ret_str【1】=shiwei+'0';
ret_str【2】=gewei+'0';
}
ret_str【3】=';';
do_ble_notify(conn, ret_str, strlen(ret_str));//设备蓝牙回复当前电量
}
else if(CDM_CMP(cmd,"Light")){ //灯光闪烁开关
if(data【0】=='o'&&data【1】=='n'){
light_flag=true;
if(ble_connect) bl_gpio_output_set(LED_STATUS, 0);
}
if(data【0】=='o'&&data【1】=='f'&&data【2】=='f'){
light_flag=false;
}
}
else if(CDM_CMP(cmd,"PowerOff")){ //关闭设备
sleep_start();
}
else if(CDM_CMP(cmd,"OTA")){ //蓝牙发送 OTA; 进入OTA
LOGI(TAG, "OTA");
ota_flag=true;
flash_storage_init();
wifi_init(wifi_event_handler);
vTaskDelay(500 / portTICK_RATE_MS);
wifi_setup_sta();
ota_time= hal_timer_now_s(); //记录OTA开始的时间
char ota_ret【20】="OTA_START";
do_ble_notify(conn, ota_ret, strlen(ota_ret));
}
else if(CDM_CMP(cmd,"WIFI")){ //蓝牙配网指令: "WIFI:账号,密码;"
LOGI(TAG, "SET WIFI ");
user_ssid_t wifi_info = flash_get_user_ssid_config();
memset(wifi_info->ssid, 0, sizeof(wifi_info->ssid));
memset(wifi_info->password, 0, sizeof(wifi_info->password));
flash_ssid_config_write();
char p = strchr(data,',');
if(p != NULL){
strncpy(wifi_info->ssid, data, p-data);
strncpy(wifi_info->password, p+1, len-(int)(p-data)-2);
flash_ssid_config_write();
char ret【20】="SET_WIFI";
do_ble_notify(conn, ret, strlen(ret));
do_ble_notify(conn, wifi_info->ssid, strlen(wifi_info->ssid));
do_ble_notify(conn, wifi_info->password, strlen(wifi_info->password));
LOGI(TAG,"saved SSID: %s, passwd: %s", wifi_info->ssid, wifi_info->password);
}
}
vTaskDelay(100 / portTICK_RATE_MS);
//do_ble_notify(conn, ret_str, strlen(ret_str));
}
对蓝牙下发的指令进行解析,根据解析后的指令经行震动马达和灯光的控制:
void mada_task(void arg){ //mada模式
uint32_t duty = 0;
int i=0;
while(1){
if(!ble_connect&&(charge_status == DISCHARGE)){ //四档离线模式
if(Grade==0) motor_g_set_vibrate(0);
if(Grade==1) motor_g_set_vibrate(8);
if(Grade==2) motor_g_set_vibrate(12);
if(Grade==3) motor_g_set_vibrate(16);
if(Grade==4) motor_g_set_vibrate(20);
}
else if(ble_connect&&(charge_status == DISCHARGE)&&Preset==0){ //蓝牙在线模式
motor_g_set_vibrate(vibrate);
if(vibrate==0)led_status_flash(0);
}
else if(ble_connect&&(charge_status == DISCHARGE)&&Preset!=0){
memcpy(currentPreMod,presetMod【Preset-1】,8);
for(i=0;i[span style="color: rgba(128, 0, 128, 1)">8;i++){
duty =currentPreMod【i】100;
motor_g_set_duty(duty);
current_Preset=currentPreMod【i】;
if(light_flag){led_status_flash(115-current_Preset);} //9种预设模式灯光,在此实现跟马达同时变化
vTaskDelay(300 / portTICK_RATE_MS);
LOGI(TAG, "presetMod:%d",currentPreMod【i】);
}
}
else {motor_g_set_vibrate(0);Grade=0;vibrate=0;}
vTaskDelay(100/portTICK_RATE_MS);
}
}
9种预设模式变化频率,可以在此调整每个模式下的震动频率变化
const uint8_t presetMod【9】【8】 =
{
{ 100, 20, 100, 20, 100, 20, 100, 20 }, //Mod1
{ 50, 100, 50, 100, 50, 100, 50, 100 }, //Mod2
{ 40, 60, 80, 100, 100, 80, 60, 40 }, //Mod3
{ 100, 25, 100, 25, 100, 25, 100, 25 }, //Mod4
{ 75, 100, 75, 100, 75, 100, 75, 100 }, //Mod5
{ 20, 100, 60, 100, 60, 100, 30, 60 }, //Mod6
{ 75, 30, 20, 30, 100, 30, 25, 60 }, //Mod7
{ 100, 100, 100, 100, 100, 100, 100, 100 }, //Mod8
{ 38, 100, 80, 47, 28, 20, 28, 44 }, //Mod9
};
自动低功耗休眠任务:
void sleep_task(void *arg){ //大于1200S无震动,进入休眠模式
static int times=0;
while(1){
//LOGI(TAG, "start sleep");
if(Grade==0&&vibrate==0&&(charge_status == DISCHARGE)&&Preset==0) times++;
else times=0;
if(ota_flag) //代码效果参考:http://hnjlyzjd.com/hw/wz_24239.html
times =0;//LOGI(TAG, "times:%d",times);
while(times>1200) {
hal_hbn_init(&key_weakup_pin, 1);
hal_hbn_enter(0);}
while(ota_flag&&(hal_timer_now_s()-ota_time>300)){
hal_hbn_init(&key_weakup_pin, 1);
hal_hbn_enter(0);
}
vTaskDelay(1000 /<span style="color: rgba(0, 0,