本項目為一款藍牙跳蛋的設計,主控芯片為BL602,通過PWM控制震動馬達的轉速實現不同的震動強度變化,通過藍牙連接設備,APP下發藍牙指令實現設備的控制。
項目地址:
https://github.com/SmartArduino/Doiting_BL/tree/master/examples/dolphin
藍牙初始化:
void do_ble_init(void){ // Initialize BLE controller LOGI(TAG, "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<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) 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 / portTICK_RATE_MS); } }
將程序編譯好后燒錄到芯片中,手機下載APP,連接設備藍牙控制震動馬達。
1.掃碼下載APP
2.連接設備
3. APP控制設備,可在APP選擇多種震動模式