HID(Human Interface Device)のコントローラとしてジョイスティックはアナログ値や独自のボタン操作には便利そうな気がします。

そこで,Raspberry Pi Pico W を2台使い,1台をジョイステイックのコントローラ,もう1台をホストにしていろいろと試しています。

Raspberry Pi Pico W で Bluetoothのジョイステイックを試作中



今回はアナログ値でRCサーボをコントロールし,ボタン操作も試してみました。

なお,使用言語はArduinoでボードマネージャはarduino-picoです。bluetoothやjoystick関連もarduino-picoのライブラリを使っています(^^)。






コントローラの配置です。

Raspberry Pi Picoは直のアナログ入力はA0,A1,A2しかありませんので,今回はXYZの3軸のアナログ入力としました。

ボタンは5個として,GPIO15から19のPinにデジタル入力されます。






ホスト側の配置です。

RCサーボはGPIO0から2のPinにつなぎ,arduino-picoのサーボライブラリで動かしてみました。

またLEDは一応コントローラのボタンに対応した各色をGPIO15から19に接続しています。





Bluetooth経由で動作させてみた動画です。
なんか操作がギクシャクしていますが(^^;;;;;;;。






以上のように何とかかんとか動いたのですが,,,問題点が残っています。

1.ボタンが8個しか設定できない
 本来32bitで32個のボタンが設定できるはずなのですが,,最上位の8bitの部分しか値が反映されていません。

 どうもレポートの構成かデータを変換させる部分を触ってしまったのでしょうか,,原因不明です(- -)。


2,Bluetooth接続が切れてしまう事がある
 しばらく放っておくと切れている事が多いですねぇ,,。
根本的に何かあるのか,,接続切断時に自動的に再接続するような対策が必要なのか,,考えどころです。


という事で,試作中でばたばたしたプログラムですが一応メモしておきます。
何か問題点を教えていただければ幸いなのですが,,。


コントローラ側のプログラムです


/*****  Bluetooth_Joystic check Program *****/
//  This program is an excertpt from the example code
// (Benjamin Aigner, 2022 <beni@asterics-foundation.org>
// Public domain / CC 0 */)
// and modified for 3 analog inputs and 8 buttons.


#include <JoystickBLE.h>

// Send data
void joy( int x, int y, int z, int rz, int16_t hat, uint32_t buttons ) {
 JoystickBLE.useManualSend(true);
   JoystickBLE.X(x);
   JoystickBLE.Y(y);
   JoystickBLE.Z(z);
   JoystickBLE.Zrotate(rz);
   JoystickBLE.button(buttons, true);
   delay(100);
   JoystickBLE.hat(hat);
 JoystickBLE.send_now();
   JoystickBLE.button(buttons, false);
   delay(10);
 JoystickBLE.useManualSend(false);
}


void setup() {
//  Serial.begin(115200);
//  Serial.println("Use BOOTSEL to start the Joystick demo.");
 JoystickBLE.begin();
}


void loop() {
 int valx = analogRead(26);    // Read analog data
 int valy = analogRead(27);    
 int valz = analogRead(28);   

 uint32_t buttons=0;

 for (int i = 15; i < 23; i++){  // Read digital data Pin15-22
   int valb = digitalRead(i);    
   if (valb == 0){
     buttons = i-14;             // button on (1-8)
     break;
   }
 }

//  Send data , joy( int x, int y, int z, int rz, int16_t hat, uint32_t buttons)
 joy(valx,valy,valz,0,0, buttons);   // default 10bit mode (0= i < 1024)

} // loop end





ホスト側のプログラムです


/*****  Bluetooth_Joystic check Program for HID_Master *****/
//  This program is an excertpt from the "KeyboardPiano example"

//  Released to the public domain in 2024 by Earle F. Philhower, III
//  and modified for 3 servos and 8 buttons.

// Servo Pin0,1,2
// Button_LED Pin15-22


#include <BluetoothHIDMaster.h>

#include <Servo.h>
Servo myservo1;
Servo myservo2;
Servo myservo3;

BluetoothHIDMaster hid;

// Joystick can get reports of 4 analog axes, 1 d-pad bitfield, and up to 32 buttons
// Axes and hats that aren't reported by the joystick are read as 0
void joy(void *cbdata, int x, int y, int z, int rz,   uint8_t hat, uint32_t buttons) {
 (void) cbdata;
 const char *hats[16] = { "U", "UR", "R", "DR", "D", "DL", "L", "UL", "", "", "", "", "", "", "", "." };
 Serial.printf("Joystick: (%4d, %4d) (%4d, %4d), Hat: %-2s, Buttons:", x, y, z, rz, hats[hat & 15]);
 for (int i = 0; i < 32; i++) {
   Serial.printf(" %c", (buttons & 1 << i) ? '*' : '.');
 }
 Serial.println(buttons >> 24);

 // Servo_Move map(value, fromLow, fromHigh, toLow, toHigh)
 int sval=map(x, -32767, 32767, 0, 180);
 myservo1.write(sval);
 sval=map(y, -32767, 32767, 0, 180);
 myservo2.write(sval);
 sval=map(z, -32767, 32767, 0, 180);
 myservo3.write(sval);

 // Button_LED
 for(int i = 24; i < 32; i++){
   digitalWrite(i-9, bitRead(buttons,i));
 }

}// joy end


void setup() {
 Serial.begin();   // Serial Monitor

 myservo1.attach(0,544,2400);  // Init. servo1
 myservo1.write(90);
 myservo2.attach(1,544,2400);  // Init. servo2
 myservo2.write(90);
 myservo3.attach(2,544,2400);  // Init. servo3
 myservo3.write(90);

 for (int i = 15; i < 23; i++){
   pinMode(i, OUTPUT);  // LED Pin15-22
 }

 Serial.printf("Starting HID master, put your device in pairing mode now.\n");

 hid.onJoystick(joy);
 hid.begin(true);
 hid.connectBLE();

}// setup end


void loop() {
 if (BOOTSEL) {        // Restart
   while (BOOTSEL) {
     delay(1);
   }
   hid.disconnect();
   hid.clearPairing();
   Serial.printf("Restarting HID master, put your device in pairing mode now.\n");
   hid.connectBLE();
 }
}