チラシのうら

レゴとか、工作とか。

8pinoでタクトスイッチを使う

先日、

8pinoで遊ぶための部品を仕入れに、人生で二度目の秋月に足を運びました。

一通り、見終わって、さぁ、お会計という時に、レジ横にあったのがこちら。
10円って。

ごそっと適当に掴んで、5、6個購入したと思います。

ずっと放置していましたが、今回のテーマはこれです。

やりたいこと

前回、Software Serialで実現した、ピアノみたいなものを、タクトスイッチで、作ってみたいです。

簡単かと思ったら…

タクトスイッチの状態は、ArduinoのDigitalRead()で取れば、楽勝だなとタカをくくっていたら、、、
8pinoはピンの数が圧倒的に少ない事に気がつきました。

とてもピアノなんか作れない。 これは困る。

世界には、他にもこれに困っている人がいるはずです。
探しました、見つけました。

ほんと、頭のいい人っているものだ。と、心底思います。

こちら に、「各スイッチに異なるΩの抵抗をつけて、それら全てを結線したPinについて、AnalogRead()で得られた電圧をもって、どのスイッチが押されたか?を判断する方式」
が載っていました。

具体的な図はこちら。 具体的な図

真似してみます

とはいっても、家にそんなに沢山の種類の抵抗はありません。

8pinoのusbコネクタ保護の為に購入した1.5kΩの抵抗は100個wあったので、これを活用します。
まさか、陽の目を見るとは…

結線図

いくつか抵抗を繋ぎ、それらをブレッドボードの+に繋ぎます。 f:id:tetunori_lego:20150602192414j:plain
Software Serialも繋いでいます。理由は後述

最もイライラしたのは

この、タクトスイッチが、なんとも腹の立つ感じで、「ピヨッ」って跳ね上がって、外れてしまうのです。
どんなに強く押しても。

ググったら、対策としてスイッチの足を90度ねじ曲げる方法がありました。画像は無かったので、正解か解りませんが、下記のように曲げると、いい感じにささるようになりました。 f:id:tetunori_lego:20150602193222j:plain
(左)対策前, (右)対策後

そろそろコード書きたいけど

我慢です。そもそもAnalogRead()でいくつが返ってくるのか、わかりません。

ほんとは先に計算すべきですが、ここで便利なSoftware Serialの登場です。 とにかく値を読んで見ました。

f:id:tetunori_lego:20150602193901j:plain

おぉ、おぉ。 ちゃんと、押したスイッチ応じて、違う値が取得出来るではないか!
うーん?でも、なんか、想像とちょっと違う値…
抵抗一個の時は、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で多くを対応するっていうのは本当に難しい。