這篇文章介紹Raspberry Pi Pico W使用BTstack bluetooth HID功能,製作一組HID Bluetooth Mouse。使用模擬設備為HW-504 joystick 模組。
HW-504為一個x-y方向2D的電位計,因此在Pi Pico W使用GPIO pin 26(ADC NUM 0)接VRx腳位,GPIO pin 27(ADC NUM 1)接VRy腳位,SW開關壓下時為接地,本實驗使用的模組未接上拉電位,因此要先接一個上拉電阻。
BTstack example 有一個hid_mouse_demo.c程式碼,本次實驗直接使用,因為在檔案中很多宣告為static,所以在主程式中#include "hid_mouse_demo.c"當作程式的一部分。
根據 HID Descriptor, input report含有三個bytes,第一個byte 最小三個位元分別為代表滑鼠按鈕,值為0與1,第2個byte為x軸移動速度,值為-127~127,第個byte為y軸移動速度,值為-127~127。
主程式如下說明:
hid_device_request_can_send_now(hid_cid);
展示影片:
程式碼如下:
hid_mouse_demo.c需作下列三項修正。
- picow_bt_mouse_joystick.c
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "hardware/gpio.h"
#include "stdlib.h"
#include "pico/cyw43_arch.h"
#include "hid_mouse_demo.c"
#define ADC_X_PIN 26
#define ADC_X_NUM 0
#define ADC_Y_PIN 27
#define ADC_Y_NUM 1
#define ADC_VREF 3.3
#define ADC_RANGE (1<<12) // pi pico 12 bits ADC
#define BUTTON_PIN 16
#define STEP 256 // min 16, 2048/256=8, mouse moving speed 0~8
uint32_t adc_x_center=0;
uint32_t adc_y_center=0;
int main()
{
stdio_init_all();
if (cyw43_arch_init()) {
printf("cyw43 arch init error\n");
return 0;
}
btstack_main(0, NULL);
gpio_init(BUTTON_PIN);
gpio_set_dir(BUTTON_PIN, false);
adc_init(); // init and assign ADC pin
adc_gpio_init(ADC_X_PIN);
adc_gpio_init(ADC_Y_PIN);
for (int i=0; i < 100; i++) { // average 100 samples as mouse static position
adc_select_input(ADC_X_NUM);
adc_x_center += adc_read();
adc_select_input(ADC_Y_NUM);
adc_y_center += adc_read();
}
adc_x_center /=100;
adc_y_center /=100;
printf("x:%d, y:%d\n", adc_x_center, adc_y_center);
uint adc_raw=ADC_RANGE/2;
uint adc_x=ADC_RANGE/2;
uint adc_y=ADC_RANGE/2;
bool button_pressed=false;
bool mouse_moving=false;
while(1) {
if (abs(adc_x-adc_x_center) < 10 && abs(adc_y-adc_y_center) < 10)
{
mouse_moving=false;
dx=dy=0;
}
if (!gpio_get(BUTTON_PIN)) {
if(!button_pressed) {
button_pressed = true;
printf("button pressed\n");
buttons |= 1;
dx=dy=0;
mouse_moving = false;
}
} else {
button_pressed = false;
buttons = 0;
adc_select_input(ADC_X_NUM);
adc_raw = adc_read();
if(abs(adc_raw-adc_x_center) > 10) {
adc_x=adc_raw;
dx = (adc_raw - ADC_RANGE/2)/STEP;
mouse_moving=true;
}
adc_select_input(ADC_Y_NUM);
adc_raw = adc_read();
if(abs(adc_raw-adc_y_center) > 10) {
adc_y=adc_raw;
dy = (adc_raw - ADC_RANGE/2)/STEP;
mouse_moving=true;
}
}
if (dx || dy || buttons) {
hid_device_request_can_send_now_event(hid_cid);
}
sleep_ms(10);
}
return 0;
}
- CMakeLists.txt
# Generated Cmake Pico project file
cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
set(PICO_SDK_PATH "/home/duser/pico/pico-sdk")
set(PICO_BOARD pico_w CACHE STRING "Board type")
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0")
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()
project(picow_bt_mouse_joystick C CXX ASM)
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
# Add executable. Default name is the project name, version 0.1
add_executable(picow_bt_mouse_joystick picow_bt_mouse_joystick.c )
pico_set_program_name(picow_bt_mouse_joystick "picow_bt_mouse_joystick")
pico_set_program_version(picow_bt_mouse_joystick "0.1")
pico_enable_stdio_uart(picow_bt_mouse_joystick 1)
pico_enable_stdio_usb(picow_bt_mouse_joystick 0)
# Add the standard library to the build
target_link_libraries(picow_bt_mouse_joystick
pico_stdlib
hardware_adc
pico_util
pico_cyw43_arch_none
pico_btstack_cyw43
pico_btstack_classic)
# Add the standard include files to the build
target_include_directories(picow_bt_mouse_joystick PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
)
pico_add_extra_outputs(picow_bt_mouse_joystick)
沒有留言:
張貼留言