SSブログ

Digisparkで複数のタクトスイッチを扱う [Arduino]

Digisparkは使用できるピンが少ないので工夫が必要。
analogRead()で複数のタクトスイッチを扱う方法が、以下のページです。

I/Oピン一つで読めるキーパッドの設計サービス
https://synapse.kyoto/tool/ResDiv/page001.html

抵抗分圧により複数のボタンの識別をしています。
ライブラリもあるようですが、ブラックボックス化したくないので自作します。
抵抗値の計算もできますが、大まかな値を確認し、自分が持っている抵抗(E6系列中心でまちまち)でもできるよう、エクセルで分圧の計算もしました。

 Vout= Vcc × (R2+R3+…+Rn) / (R1+R2+…+Rn)

閾値は、それぞれの分圧の中間値として、それを10ビット(0~1023)の値に換算しました。
resvoldiv.png
あと、analogRead()は遅いらしいので、すべてのボタンは押されたときの電圧がdigitalRead()のLow判定電圧未満としておき、digitalRead()でLowになったら、あらためてanalogRead()で値を読むということにしました。

digitalRead()のLow判定電圧ですが、

Arduino Unoの入力スレッショルド電圧を測ってみる(閾値電圧) | のぶらぼ
https://nobulabo.com/arduino-uno-threshold-level/

「HIGH⇒LOW(VIL)は2.2V、LOW⇒HIGH(VIH)は2.6V、その差であるヒステリシス電圧は0.4Vであることがわかりました。」
とありました。

ATtiny25/V / 45/V / 85/V のデータシート
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf

186, 187ページの「22.7 Pin Threshold and Hysteresis」の項目をみるとVcc 5Vのとき
HIGH⇒LOW(VIL)は2.25V、LOW⇒HIGH(VIH)は2.5V あたりです。

タクトスイッチが押されたとき(HIGH⇒LOW)を確認したいので、分圧電圧を2.25V未満に抑えることにしました。



押されたボタン(SW1~SW4)の番号の回数分 LEDを点滅させるスケッチです。
// Check multiple buttons with one pin for digispark
//
//   Vcc--R1--+----+-R2-+-R3-+-R4-+      (R1:4.7k, R2:680, R3,R4:1k)
//            |   sw1  sw2  sw3  sw4
//            P2   +----+----+----+----GND
//
const uint16_t Vth[] = {0,  64, 199, 320};  // threshold (intermediate value between voltages -> 10bit)

void setup() {
  pinMode(2, INPUT);                        // P2:Buttons (D2/A1)
  pinMode(1, OUTPUT);                       // P1:Built-in LED (D1)
}

void loop() {
  uint8_t  btn=0;                           // pressed button number (0 if none are pressed)
  uint16_t val;                             // variable to store the value read
  if( !digitalRead(2) ) {                   // Read Button number
    delay(10);                                              // chattering control
    val = analogRead(1);                                    // read the input pin
    for(btn=1; btn<sizeof(Vth)>>1 && val>Vth[btn]; btn++);  // Advance the btn until the Vth is exceeded
    while( !digitalRead(2) );                               // Wait until the button is released 
  }
  for(; btn; btn--) {                       // Blinks the LED for the number of button numbers
    digitalWrite(1, HIGH);
    delay(100);
    digitalWrite(1, LOW);
    delay(200);
  }
}

タグ:Digispark
nice!(0)  コメント(0) 

Digisparkでマウス&キーボード [Arduino]

スーパーファミコンのコントローラーでマウスポインターの操作とマルチメディアキーの操作をしてみる。

調べてみると、同時に使えるライブラリーがあるらしい。

GitHub - adafruitAdafruit-Trinket-USB Arduino libraries allowing Trinket to act as USB devices
https://github.com/adafruit/Adafruit-Trinket-USB/

adatriusblib.png

「Code ▼」をクリックして「Download ZIP」で保存。
その中の「TrinketHidCombo」というフォルダをフォルダごと、スケッチブックの保存場所(環境設定で指定のところ)にある「libraries」というフォルダ内にコピーするだけらしい。

環境設定をいじってなければ、以下のフォルダ。
%userprofile%\Documents\Arduino\libraries

十字キーでマウスのカーソル操作。Y, Bボタンでクリック。
X, Aボタンでの音量の操作もできるようになりました。
ブラウザ等の「戻る」ボタンも欲しいと思って調べてみると、

HID Usages and Descriptions - hut1_3_0.pdf
https://www.usb.org/sites/default/files/hut1_3_0.pdf

これ(↑)の p.130 の 「0x0224 AC(Application Control) Back」っぽい。
でも、pressMultimediaKey()関数の引数が「uint8_t (符号なし8bit整数型)」なので無理。
ただ、「Alt + ←」で代用は可能かも。

スケッチは以下のとおり。
// SFC(SNES) controller to HID            //     _______________+----- GND   (Brown)
//   digispark(USB 16.5MHz) Trinket Lib.  //    |_O_O_O_O_|_O_O_O_)          connector
#define DAT   0                           //      | | | +------------> DATA1 (Red)
#define PS    1                           //      | | +--------------< P/S   (Orange)
#define CLK   2                           //      | +----------------< CLK   (Yellow)
#include "TrinketHidCombo.h"              //      +------------------- VCC   (White)

void setup() {
    pinMode( DAT, INPUT_PULLUP );
    pinMode( PS , OUTPUT );
    pinMode( CLK, OUTPUT );
    digitalWrite( CLK, HIGH );
    TrinketHidCombo.begin();
}

void loop() {
    uint8_t sfc[12];
    digitalWrite( PS , HIGH );
    digitalWrite( PS , LOW  );
    for(uint8_t i=0; i<12; i++) {
        sfc[i] = digitalRead( DAT )^1;
        digitalWrite( CLK, LOW  );
        digitalWrite( CLK, HIGH );
    }   // 0:B, 1:Y, 2:SEL, 3:STA, 4:UP, 5:DOWN, 6:LEFT, 7:RIGHT, 8:A, 9:X, 10:L, 11:R
    TrinketHidCombo.mouseMove(
      ( sfc[ 7] - sfc[ 6] ) <<2 ,  ( sfc[ 5] - sfc[ 4] ) <<2 ,          // cross key:mouse cursor
        sfc[ 0] * MOUSEBTN_RIGHT_MASK + sfc[1] * MOUSEBTN_LEFT_MASK  ); // Y:left, B:right click
    if( sfc[ 8] ) TrinketHidCombo.pressMultimediaKey( MMKEY_VOL_DOWN ); // A:Volume Down
    if( sfc[ 9] ) TrinketHidCombo.pressMultimediaKey( MMKEY_VOL_UP   ); // X:Volume Up
    delay(10);
    TrinketHidCombo.poll();         // do nothing, check if USB needs anything done
    delay(10);
}

・TrinketHidComboのライブラリを使用した。
・コントローラーが外れていてもおかしなことにならないようにした。
  (DATA1のピンをINPUT_PULLUPにした)
・ボタンの状態を、符号なし16bit整数型をやめて配列に入れた。
  (メモリの無駄だけど操作が楽に)
・最後のTrinketHidCombo.poll() (あるいはpressとか)を最低10msecごとに呼び出さないといけないって書いてあった。
タグ:Digispark
nice!(0)  コメント(0) 

Digisparkでスーパーファミコンのコントローラーを使う [Arduino]

前提として、スーパーファミコン型のUSBジョイパッドを買ったほうが簡単で安いというのは無しで。
また、この手の話題はすでにライブラリまで作っている方もみえて、何番煎じかという感じです。

うちの近くのハードオフに、スーパーファミコンのコントローラーの中古があるにはあるのですが、手垢で汚い・傷あり・変色・ボタンスカスカ・110円じゃなくて330円。
ですが、とりあえず1個よさそうなものを選んで購入。
Aliexpressでソケットも購入。

こんな感じで、、
sfc_socket1.jpg
sfc_socket2.jpg
先日つくった改造Digisparkと接続できるパーツを仕上げたのですが、改造Digisparkが死亡したため、以前に購入したmicroUSB版 Digisparkを出してきました。
sfc_socket3.jpg
ブレッドボートでつないで、十字キーを読み取るという以下のスケッチで動作確認できました。
// SFC(SNES) controller to HID            //     _______________+----- GND   (Brown)
//   digispark(USB 16.5MHz) version       //    |_O_O_O_O_|_O_O_O_)          connector
#define DAT   0                           //      | | | +------------> DATA1 (Red)
#define PS    1                           //      | | +--------------< P/S   (Orange)
#define CLK   2                           //      | +----------------< CLK   (Yellow)
#include "DigiKeyboard.h"                 //      +------------------- VCC   (White)

void setup() {
    pinMode( DAT, INPUT );
    pinMode( PS , OUTPUT );
    pinMode( CLK, OUTPUT );
    digitalWrite( CLK, HIGH );
    DigiKeyboard.sendKeyStroke(0);
}

void loop() {
    uint16_t sfc = 0;
    digitalWrite( PS , HIGH );
    digitalWrite( PS , LOW  );
    for(uint8_t i=0; i<12; i++) {
        sfc |= ( digitalRead( DAT )^1 ) << i;
        digitalWrite( CLK, LOW  );
        digitalWrite( CLK, HIGH );
    }
      // 0:B, 1:Y, 2:SEL, 3:STA, 4:UP, 5:DOWN, 6:LEFT, 7:RIGHT, 8:A, 9:X, 10:L, 11:R
    if( sfc & (1<< 4) ) DigiKeyboard.sendKeyStroke( 0x52 );     // UP    -> KEY_ARROW_UP
    if( sfc & (1<< 5) ) DigiKeyboard.sendKeyStroke( 0x51 );     // DOWN  -> KEY_ARROW_DOWN
    if( sfc & (1<< 6) ) DigiKeyboard.sendKeyStroke( 0x50 );     // LEFT  -> KEY_ARROW_LEFT
    if( sfc & (1<< 7) ) DigiKeyboard.sendKeyStroke( 0x4f );     // RIGHT -> KEY_ARROW_RIGHT
    DigiKeyboard.delay(10);
}

メディアキーでボリュームの操作もしたかったんだけど、なぜかできず。
タグ:Digispark
nice!(0)  コメント(0) 

Digispark 死亡。 [Arduino]

ds_dead.jpg

改造Digisparkで遊んでいる最中のこと。
USBに接続したままプログラム書き込み開始しちゃった?間違えた?って感じで、USB抜き差しスイッチをON/OFF繰り返してしまい、タイミングが悪かったようで、ブートローダーがおかしくなった模様。
リセット無効にしたので、ISPでのブートローダーの焼き直しもできず、、死亡です。
タグ:Digispark
nice!(0)  コメント(0) 

Digisparkとブレッドボードと [Arduino]

以前にも(https://hello-world.blog.ss-blog.jp/2016-10-02)、ブレッドボードとの相性について考えてみたのですが、別の解を考えつきました。

外部電源を使用するつもりがないのであれば、、
  ↓
レギュレータが不要
  ↓
USB接続が必須
  ↓
USBと接続時にピンをいじるのはホストPCには良くなさそう
  ↓
P3, P4のピンは使わない
  ↓
P3, P4への回路は不要だから切断
  ↓
空き地に「+5V」と「GND」を入れよう

という算段です。

以下のサイトにプリント基板の図面がありました。

Techunboxed The Digispark is Here [Review]
http://www.techunboxed.com/2013/01/the-digispark-is-here-review.html

digispark3a.png

これを参考に
・レギュレータを外す
・レギュレータ跡地のGND接地部とVINの部分に表面実装タクトスイッチをつける
・裏面からP3, P4へのラインをドリルやリューターで削って切断する
・ピンソケットの足が基板から出ないように切りそろえておく(とげとげをなくしたい)
・ピンソケットをP1, P2, P5で固定する
・VIN(あるいはスイッチのGNDじゃない側、下の5Vスルーホールに注意)とP0を接続する
・P4のすぐ隣の5Vラインの保護膜を薄くけずりP4と接続(P4を+5Vに変更)
・レギュレータのGND接地部とP3を接続(P3をGNDに変更)
・ブートローダを書き換える(micronucleusmicronucleus-1.11-entry_jumper_pb0.hex)
・fuseを書き換える(Highの7bit目の項目の RSTDISBL (External Reset disable) を変更)
・ソケットにピンの内容を表記
ds-socket2.jpg
で完成!
ds-socket1.jpg
見た目重視で、ピンではなくてソケット、直ではなくてL字で作成しました。
裏面にはでっぱりがないので机の上でも安定。

ds-socket3.jpg
ブレッドボードに挿すとき用に、6ピンヘッダ2つを合掌造りの様にしてL字パーツを作りました。

ds-socket4.jpg
タグ:Digispark
nice!(0)  コメント(0) 

Digispark 使用可能ピンを増やす(P5をリセットからGPIOに) [Arduino]

生のATtiny85だと、自由に使えるピンはリセットを除いて5ピン。
fuseの変更でリセットをGPIOに変更することもできるけど、ISPで書き換えできなくなるので危険。

Digispark(のクローン)ではちょっと事情が異なり、USBで使用する2ピンと、P5のリセットピンを除くと3ピンだけ。
でもリセットがなくてもUSBからスケッチの書き換えができるので、危険は承知の上でfuseの書き換えを断行。

fuseの書き換えは、ArduinoISP とか USBasp とかでやります。
だいぶ前に購入した USBasp(珍しい6ピンタイプ)があったので引き出してきました。
isp-6p.jpg
USBに挿すだけだと思ってたら、ドライバが必要でした。忘れてた。
備忘録。

Zadig - USB driver installation made easy
https://zadig.akeo.ie/

で、zadig-2.7.exe をダウンロード。
zadig_win11.png
USBaspを挿して、実行して、USBasp を選択(出てこなければ Options > List All Devices)。
libusb-win32 を選択して、インストールでよさそう。

接続は、以前に購入してそのままだった ピンピッチが1.27mm(50ミル)の SOP/SOIC用の8ピンIC用クリップがあったので USBaspにはまるように配線しました。
isp-6p-cable.jpg
Digispark上のATtiny85に挟むだけなので便利なのですが、少し時間がたつと外れてしまいます。
(まだ基板に載っていない生のICなら外れないみたい。)
fuse書き換えの一瞬だけ動いてくれればOKということで。

書き込みソフトですが、量産するわけでもないので、GUIのものを探しました。

AVRDUDESS – A GUI for AVRDUDE
https://blog.zakkemble.net/avrdudess-a-gui-for-avrdude/

dsp5fuse.png
何回も使用するものでもないので、非インストール版の portable.zip にしました。日本語設定も可能。
USBasp なら、プログラマーは "Any usbasp clonr with correct VID/PID"、ポートは "usb"
ArduinoISP なら、プログラマーは "Arduino"、ポートは "COMx"
でいいと思います。
MCUを選択・検出できればたぶん接続はOK。
ヒューズ & ロックビットを「読込」。"ヒューズの設定"をクリックすると設定内容も分かって便利。
初期値はものによって違うみたいだけど、ぼくの購入したものは、
Low:0xF1, High:0xDF, Extended:FE でした。
このうちのHighを 0xDF → 5F に変更して「書込」。
dsp5fuse2.png
以降は P5がGPIOとして使えるようになりました。(同時にISP書き込み、fuse変更ができなくなる。)
タグ:Digispark ISP
nice!(0)  コメント(0) 

Digispark 5秒待たないHIDデバイス [Arduino]

5秒待たない [CTRL]+[ALT]+[DEL]キーボタンができました。

レギュレータ跡地のGNDパターンの一部にL字の溝を掘りました。(タクトスイッチ足固定用)

ds_cad2-2.jpg

4つ足のタクトスイッチの1つを根本で折って、3点でタクトスイッチを固定しましたが、ぐらつく感じはありません。
2つ足のタクトスイッチなら溝掘りすら要らないです。
あとはVIN(というかスイッチのGNDじゃない側)とP0を接続するだけ。

ds_cad2-1.jpg

ブートローダを ”micronucleusmicronucleus-1.11-entry_jumper_pb0.hex” に書き換えます。
(参照 https://hello-world.blog.ss-blog.jp/2022-05-14
以下のスケッチを書き込みます。書き込む際に、"Plug in device now... (will timeout in 60 seconds)" と出たら、スイッチを押しながらUSBに差し込めばOK。

// Enter [Ctrl] + [Alt] + [Del] keys with one button
//   Digispark @ 16.5MHz, V-USB, micronucleus-1.11-entry-jumper-pb0-upgrade.hex

#include "DigiKeyboard.h"
#define KEY_DELETE      76

void setup() {
    pinMode( 0, INPUT_PULLUP );         // Tactile Switch (Internal pull-up)
    pinMode( 1, OUTPUT );               // Built-in LED
    DigiKeyboard.sendKeyStroke(0);
}

void loop() {
    while(  digitalRead(0) )  DigiKeyboard.update();    // Wait until the switch is pressed
    digitalWrite( 1, HIGH );
    DigiKeyboard.sendKeyStroke(KEY_DELETE, MOD_ALT_LEFT | MOD_CONTROL_LEFT);
    DigiKeyboard.delay(200);                            // chattering control and LED lighting time
    digitalWrite( 1, LOW  );
    while( !digitalRead(0) )  DigiKeyboard.update();    // Wait until the switch is released
    DigiKeyboard.delay(200);                            // chattering control
}

HIDデバイスとして使えるように切り替わったかどうか確認のLED点滅もなくしてスケッチもすっきり。

あとは、3点固定のタクトスイッチの保護のためにも熱収縮チューブでラッピング。
タグ:Digispark HID
nice!(0)  コメント(0) 

Digispark 起動までの5秒待たないBootloader [Arduino]

やっぱり最初の5秒待ちは気になるので、5秒待たないBootloaderにする。
意外とあっさり出来た。

micronucleus_hex.png

●まずはダウンロード

・ブートローダーを以下から

micronucleusmicronucleus-1.11-entry_jumper_pb0.hex at v1.11 · micronucleusmicronucleus · GitHub
https://github.com/micronucleus/micronucleus/blob/v1.11/upgrade/releases/micronucleus-1.11-entry-jumper-pb0-upgrade.hex

すぐダウンロードしだすのかと思ったが、そうではなかった。Rawを右クリックで保存。中身はバイナリーファイルではなくて、テキストファイル。

・書き込みプログラムを以下から

micronucleuscommandlinebuildsx86_64-mingw32 at master · micronucleusmicronucleus · GitHub
https://github.com/micronucleus/micronucleus/tree/master/commandline/builds/x86_64-mingw32/

libusb0.dll、micronucleus.exe ともに必要。
( %UserProfile%\AppData\Local\Arduino15\packages\digistump\tools\micronucleus\ 以下のフォルダ内にあるにはある。)

●新しいブートローダーの書き込み

・Windows11だと、スタートメニューの検索のところに「cmd」と入力。
・コマンドプロンプトが出てきたら、「micronucleus.exe」をドラッグ&ドロップすると、パスがそのまま入る。
・続けて半角スペースを手入力。
・最後に「micronucleus-1.11-entry-jumper-pb0-upgrade.hex」をドラッグ&ドロップして、Enter!

・あとは指示通りにDigisparkをUSBに差し込むだけ。

micronucleus.exeのあとに「 --run 」を入れて、そのあとにhexファイルを入れるように書いてあるサイトもあったけど、なくてもできた。
(micronucleus.exeのヘルプをみると、"--run: Ask bootloader to run the program when finished uploading provided program" とある。)
タグ:Digispark
nice!(0)  コメント(1) 

Digisparkでショートカットボタン[CTRL]+[ALT]+[DEL] [Arduino]

HIDデバイスにもなるDigisparkで[CTRL]+[ALT]+[DEL]のショートカットボタンを作りたかったのです。
どうしてかというと、Windowsのキオスクモードで、キーボードなしで、マウスやタッチパネルでの運用をしているとき、にログアウトのためだけにキーボードを接続したくないからです。

ネットを調べるとすでに作られている方もいます。
スケッチもあります。

GitHub - hidenorlyandroidRebootSwitch USB Android reboot SW
https://github.com/hidenorly/androidRebootSwitch

★そのまま作るでは面白くないので一工夫
スイッチをどこにつけるか。
Digisparkには大きめのレギュレータがついていますが、外部電源を使わないので不要。
まず、足を外し、つづいて本体を外します。
ハンダ吸い取り線でキレイにします。
このスペースにパターンを少しいじってをタクトスイッチを載せることにします。

ここで選択。

・Pull-Upしておき、スイッチでGNDに落とす。
・Pull-Downしておき、スイッチで5V印可する。

前者(Pull-Up)のメリット・デメリット
・マイコン内臓のINPUT_PULLUPが使える
・四つ足タクトスイッチの4点固定はできなさそう
・起動までの5秒待たないBootloaderが使えそう
 (スケッチ書き込み時にスイッチを押しながら接続するという運用)

後者(Pull-Down)のメリット・デメリット
・マイコン内臓のINPUT_PULLUPが使えない
 (ただ電源LEDを外せばLED用の電流制限抵抗(102:1kΩが付いていた)をPull-Down抵抗に流用できる)
・起動までの5秒待たないBootloaderが使えない
・四つ足タクトスイッチの4点固定ができる

起動までの5秒待たないBootloaderは魅力的ですが、少し勉強してからということで、後者の方法で作ってみました。
ds_cad1.jpg
 レギュレータを外し、リューターでパターンにT字の溝を掘る。

ds_cad2.jpg
 追加パーツは四つ足タクトスイッチと配線少々のみ、タクトスイッチは表面実装のものが手元になかったので足を曲げたり切断したりして調整。

ds_cad3.jpg
 熱収縮チューブにボタン部分用の穴をあけて収縮させて完成!

スケッチは以下の通り。
// Enter [Ctrl] + [Alt] + [Del] keys with one button
//   Digispark @ 16.5MHz, V-USB
#include "DigiKeyboard.h"
#define KEY_DELETE      76

void setup() {
    pinMode( 0, INPUT );        // Tactile Switch (pull-down with 1kOhm(102) resister)
    pinMode( 1, OUTPUT );       // Built-in LED
    DigiKeyboard.sendKeyStroke(0);
    // Usable signal (LED flickering)
    digitalWrite( 1, HIGH );
    DigiKeyboard.delay(100);
    digitalWrite( 1, LOW );
    DigiKeyboard.delay(100);
    digitalWrite( 1, HIGH );
    DigiKeyboard.delay(100);
    digitalWrite( 1, LOW );
}

void loop() {
    while( !digitalRead(0) )  DigiKeyboard.update();    // Wait until the switch is pressed
    digitalWrite( 1, HIGH );
    DigiKeyboard.sendKeyStroke(KEY_DELETE, MOD_ALT_LEFT | MOD_CONTROL_LEFT);
    DigiKeyboard.delay(200);                            // chattering control and LED lighting time
    digitalWrite( 1, LOW );
    while(  digitalRead(0) )  DigiKeyboard.update();    // Wait until the switch is released
    DigiKeyboard.delay(200);                            // chattering control
}


タグ:Digispark
nice!(0)  コメント(0) 

Digisparkの準備 - ソフト編 [Arduino]

ds_inst.png

解説というか備忘録です。とりあえず以下の通りにやる。

digispark:tutorials:connecting [Digistump Wiki]
http://digistump.com/wiki/digispark/tutorials/connecting

Arduino IDEは入っているとして、、
●ファイル>環境設定 で、追加のボードマネージャのURLに以下の行を追加。
  http://digistump.com/package_digistump_index.json
・ツール>ボード>ボードマネージャ...で"Digistump AVR Boards"を選択してインストール。
・ツール>ボード>Digistump AVR Boards>"Digispark (Default - 16.5Mhz) "を選択。
●ドライバのインストールも必要。
  ここ、
  %UserProfile%\AppData\Local\Arduino15\packages\digistump\tools\micronucleus\
   以降にある Install_Digistump_Drivers.bat を実行。
  あるいは、
  https://github.com/digistump/DigistumpArduino/releases/download/1.6.7/Digistump.Drivers.zip
  Install Drivers.exe を実行でいいと思う。

・LED点滅スケッチを書き込む。
 (モデルによりBUILTIN LEDのついているピンが異なる(Pin 0かPin 1か)ようなので、スケッチを書き換えLEDがどちらについているか確認したほうがいいと思う)
タグ:Digispark
nice!(0)  コメント(0)