8pinoでタクトスイッチを使う
先日、
8pinoで遊ぶための部品を仕入れに、人生で二度目の秋月に足を運びました。
一通り、見終わって、さぁ、お会計という時に、レジ横にあったのがこちら。
10円って。
ごそっと適当に掴んで、5、6個購入したと思います。
ずっと放置していましたが、今回のテーマはこれです。
やりたいこと
前回、Software Serialで実現した、ピアノみたいなものを、タクトスイッチで、作ってみたいです。
簡単かと思ったら…
タクトスイッチの状態は、ArduinoのDigitalRead()で取れば、楽勝だなとタカをくくっていたら、、、
8pinoはピンの数が圧倒的に少ない事に気がつきました。
とてもピアノなんか作れない。 これは困る。
世界には、他にもこれに困っている人がいるはずです。
探しました、見つけました。
ほんと、頭のいい人っているものだ。と、心底思います。
こちら
に、「各スイッチに異なるΩの抵抗をつけて、それら全てを結線したPinについて、AnalogRead()で得られた電圧をもって、どのスイッチが押されたか?を判断する方式」
が載っていました。
具体的な図はこちら。
真似してみます
とはいっても、家にそんなに沢山の種類の抵抗はありません。
8pinoのusbコネクタ保護の為に購入した1.5kΩの抵抗は100個wあったので、これを活用します。
まさか、陽の目を見るとは…
結線図
いくつか抵抗を繋ぎ、それらをブレッドボードの+に繋ぎます。
Software Serialも繋いでいます。理由は後述
最もイライラしたのは
この、タクトスイッチが、なんとも腹の立つ感じで、「ピヨッ」って跳ね上がって、外れてしまうのです。
どんなに強く押しても。
ググったら、対策としてスイッチの足を90度ねじ曲げる方法がありました。画像は無かったので、正解か解りませんが、下記のように曲げると、いい感じにささるようになりました。
(左)対策前, (右)対策後
そろそろコード書きたいけど
我慢です。そもそもAnalogRead()でいくつが返ってくるのか、わかりません。
ほんとは先に計算すべきですが、ここで便利なSoftware Serialの登場です。 とにかく値を読んで見ました。
おぉ、おぉ。
ちゃんと、押したスイッチ応じて、違う値が取得出来るではないか!
うーん?でも、なんか、想像とちょっと違う値…
抵抗一個の時は、1023 / 2 位じゃないの?
(USBのD-のpullup抵抗分が加算されているからですね。ポートの選択を完全に誤りました。)
計算を正しくやることが目的ではないのでさらっと流します。
気力の問題
と、ブレッドボードの余白の問題で、ピアノは断念して、単純にLEDをピからせるだけにしました。
動画はこちら。
わりと、素早くボタン押しても、誤動作しませんでした。
うーん。苦労したわりにアウトプットがショボいと、なえます。
コードはこちら
ピンのアサインがいけてないので、参考程度ですが。
/* Tact Switch test */ #define _8PINO_SOFTWARE_SERIAL_DEBUG #include <SoftwareSerial.h> /************************************************* * For Adafruit NeoPixel *************************************************/ #include <Adafruit_NeoPixel.h> #ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc. #include <avr/power.h> #endif #define NEOPIXEL_IN_PIN 0 #define NUM_OF_PIXELS 16 Adafruit_NeoPixel pixels = Adafruit_NeoPixel( NUM_OF_PIXELS, NEOPIXEL_IN_PIN ); #ifdef _8PINO_SOFTWARE_SERIAL_DEBUG #define _8PINO_SOFTWARE_SERIAL_PIN_RX ( 1 ) #define _8PINO_SOFTWARE_SERIAL_PIN_TX ( 2 ) #define _8PINO_PRINT_NEOPIXEL_RING_CONTROL ( "\r\n Neopixel Ring -> " ) #define _8PINO_PROMPT_STRING ( "\r\n8pino > " ) SoftwareSerial mySerial( _8PINO_SOFTWARE_SERIAL_PIN_RX, _8PINO_SOFTWARE_SERIAL_PIN_TX ); #endif #define TACT_SWITCHES_PIN 3 #define TACT_SWITCH_1_VAL ( 762 ) #define TACT_SWITCH_2_VAL ( 874 ) #define TACT_SWITCH_3_VAL ( 920 ) #define TACT_SWITCH_4_VAL ( 944 ) #define TACT_SWITCH_OFFSET ( 5 ) void setup() { pinMode( NEOPIXEL_IN_PIN, OUTPUT ); pinMode( TACT_SWITCHES_PIN, INPUT ); #ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc. if( F_CPU == 16000000 ) clock_prescale_set( clock_div_1 ); #endif pixels.begin(); pixels.setBrightness(30); pixels.show(); // Initialize all pixels to "off" #ifdef _8PINO_SOFTWARE_SERIAL_DEBUG // set the data rate for the SoftwareSerial port mySerial.begin(4800); //mySerial.println(""); //mySerial.println("--- Hello! from 8pino... ---"); #endif } void loop() // run over and over { int i = 0; char tmpStr[5]; int tact_switches_pin_val = analogRead( TACT_SWITCHES_PIN ); itoa( tact_switches_pin_val, tmpStr, 10 ); #ifdef _8PINO_SOFTWARE_SERIAL_DEBUG mySerial.write( "\r\n" ); mySerial.write( tmpStr ); #endif if( abs( tact_switches_pin_val - TACT_SWITCH_1_VAL ) < TACT_SWITCH_OFFSET ){ for( i = 0; i < NUM_OF_PIXELS; i++ ){ pixels.setPixelColor( i, 255, 0, 0 ); } }else if( abs( tact_switches_pin_val - TACT_SWITCH_2_VAL ) < TACT_SWITCH_OFFSET ){ for( i = 0; i < NUM_OF_PIXELS; i++ ){ pixels.setPixelColor( i, 0, 255, 0 ); } }else if( abs( tact_switches_pin_val - TACT_SWITCH_3_VAL ) < TACT_SWITCH_OFFSET ){ for( i = 0; i < NUM_OF_PIXELS; i++ ){ pixels.setPixelColor( i, 0, 0, 255 ); } }else if( abs( tact_switches_pin_val - TACT_SWITCH_4_VAL ) < TACT_SWITCH_OFFSET ){ for( i = 0; i < NUM_OF_PIXELS; i++ ){ pixels.setPixelColor( i, Wheel( ( i * 256 / pixels.numPixels() ) & 255 ) ); } } pixels.show(); // Initialize all pixels to "off" delay( 30 ); } uint32_t Wheel(byte WheelPos) { if(WheelPos < 85) { return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } else if(WheelPos < 170) { WheelPos -= 85; return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3); } else { WheelPos -= 170; return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3); } }
こんな簡単な機能なのに、HWで多くを対応するっていうのは本当に難しい。