チラシのうら

レゴとか、工作とか。

8pinoでモーターを回してみる

今回も

研修で戴いた、部材を使って8pinoの活用方法を考えます。

で、こちらのセットを使います。 f:id:tetunori_lego:20150605064605j:plain 初心者向けなので、既に研修講師によって配線されたものが配られました。 何てありがたい

ざっと確認して、モーターと電池は何となくわかりますが、コネクタ2つと金属が飛び出ている黒いIC?はよく解りません。 こちらを深堀してみます。

黒いICの理解

目を凝らしてみると、 f:id:tetunori_lego:20150605064950j:plain TOSHIBA JAPAN
TA7291P 1314G
と読み取れました。早速調べます。

メーカーのサイト や、仕様書 は見れたのですが、イマイチ理解が深まらず。

結局、こちらのサイト が一番良く解説してくれてました。

要は、GPIO 2本でStart, Stop, 回転方向の制御を、PWM 1本で回転速度の制御を、それぞれ行う為のICの様です。

GPIO : 回転方向制御 f:id:tetunori_lego:20150605070242j:plain

コネクタとの結線を確認する

f:id:tetunori_lego:20150605070712j:plain

より、詳しく見るために、ICの裏面に番号をふりました。 f:id:tetunori_lego:20150605074235j:plain 対応表はこちら。

ピン番号 ピン名 8pino側 備考
1 GND GND Ground
2 OUT 1 - モーターに繋ぐ
3 - - 未使用
4 Vref PWM モーター速度制御
5 IN 1 GPIO 回転方向制御
6 IN 2 GPIO 回転方向制御
7 Vcc 5.0v IC駆動用電源
8 Vs - モーター駆動用電源
9 - - 未使用
10 OUT 2 - モーターに繋ぐ

 

8pinoと繋ぐ

f:id:tetunori_lego:20150605075555j:plain GPIOはPin3,4を、PWMにはPin0をそれぞれアサインしてみました。
回転制御をシリアル経由で指示してみたかったので、Pin1,2はシリアル接続しています。
Pin数ギリギリ!

制御仕様

ターミナルから下記の様に指示出します。

char コマンド
m Start motor
x Stop motor
+ Speed up
- Speed down

 
f:id:tetunori_lego:20150605180853j:plain
これで、思うように、モーターを制御する事が出来ました。

デモ 1(レゴ StarWars)

何をデモに使おうかなと、思ったのですが、今年はStarWars yearですし、棚に飾ってあったMaster Yodaに、Episode 2を再現させる事にしました。

結果、やっぱり最強のJediです。

ベイダー卿倒す前に、フォース(回転数)を大きくしています。

楽しくて、止まりません。息子とStarWarsごっこ。

何度、ヨーダが外れて、飛んでいったことか。

デモ 2(レゴ ヘリコプター)

レゴで回ると言えばヘリコプター。 羽の部分を取り外して、モーターに取り付けてみました。
こっちはイマイチ。

以上!

次回は、残り物の部材、最後の一点を使った開発となります。

忘れてた。

コードはこちら。

/*
  8pino Motor Control Test
*/

#include <SoftwareSerial.h>

#define _8PINO_SOFTWARE_SERIAL_PIN_RX ( 1 ) 
#define _8PINO_SOFTWARE_SERIAL_PIN_TX ( 2 ) 

#define _8PINO_PROMPT_STRING ( "\r\n8pino > " )

SoftwareSerial mySerial( _8PINO_SOFTWARE_SERIAL_PIN_RX, _8PINO_SOFTWARE_SERIAL_PIN_TX );

#define _8PINO_MOTOR_SPEED_CTRL_PIN ( 0 )
#define _8PINO_MOTOR_ROTATION_CTRL_PIN1 ( 3 )
#define _8PINO_MOTOR_ROTATION_CTRL_PIN2 ( 4 )

#define _8PINO_MOTOR_DEFAULT_SPEED ( 10 )

#define _8PINO_MOTOR_SPEED_MAX ( 100 )
#define _8PINO_MOTOR_SPEED_MIN ( 10 )
int motor_speed = _8PINO_MOTOR_DEFAULT_SPEED;

void setup(){
  
  // set the data rate for the SoftwareSerial port
  mySerial.begin(4800);
  mySerial.println("");
  mySerial.println("--- Hello! from 8pino... ---");
  mySerial.write( _8PINO_PROMPT_STRING );
  
  pinMode( _8PINO_MOTOR_SPEED_CTRL_PIN, OUTPUT );
  pinMode( _8PINO_MOTOR_ROTATION_CTRL_PIN1, OUTPUT );
  pinMode( _8PINO_MOTOR_ROTATION_CTRL_PIN2, OUTPUT );
  analogWrite( _8PINO_MOTOR_SPEED_CTRL_PIN, motor_speed ); 
  stopMotor();
  
  /*
  // TEST 1
  setRotationCW();
  delay( 1000 );
  stopMotor();
  delay( 3000 );
  setRotationCCW();
  delay( 1000 );
  stopMotor();
  */
}

void loop(){
  
  int tmp_char = 0;
  
  if ( mySerial.available() ){
    tmp_char = mySerial.read();
    if( tmp_char == '\r' ){
      mySerial.write( _8PINO_PROMPT_STRING );
    }else if( tmp_char == '+' ){
      if( motor_speed < _8PINO_MOTOR_SPEED_MAX ){
        motor_speed += 10;
        mySerial.write( tmp_char );
        mySerial.write( "\r\nSpeed Up! : " );
        mySerial.print( motor_speed );
        mySerial.write( _8PINO_PROMPT_STRING );
        analogWrite( _8PINO_MOTOR_SPEED_CTRL_PIN, motor_speed ); 
      }
    }else if( tmp_char == '-' ){
      if( motor_speed > _8PINO_MOTOR_SPEED_MIN ){
        motor_speed -= 10;
        mySerial.write( tmp_char );
        mySerial.write( "\r\nSpeed Down! : " );
        mySerial.print( motor_speed );
        mySerial.write( _8PINO_PROMPT_STRING );
        analogWrite( _8PINO_MOTOR_SPEED_CTRL_PIN, motor_speed ); 
      }
    }else if( tmp_char == 'm' ){
      setRotationCW();
      mySerial.write( tmp_char );
      mySerial.write( "\r\nStart Motor!" );
      mySerial.write( _8PINO_PROMPT_STRING );
    }else if( tmp_char == 'x' ){
      stopMotor();
      mySerial.write( tmp_char );
      mySerial.write( "\r\nStop Motor..." );
      mySerial.write( _8PINO_PROMPT_STRING );
    }else{
      mySerial.write( tmp_char );
    }
  }
}

void stopMotor(){
  
  digitalWrite( _8PINO_MOTOR_ROTATION_CTRL_PIN1, LOW );
  digitalWrite( _8PINO_MOTOR_ROTATION_CTRL_PIN2, LOW );
  
}

void setRotationCW(){
  
  digitalWrite( _8PINO_MOTOR_ROTATION_CTRL_PIN1, HIGH );
  digitalWrite( _8PINO_MOTOR_ROTATION_CTRL_PIN2, LOW );
  
}

void setRotationCCW(){
  
  digitalWrite( _8PINO_MOTOR_ROTATION_CTRL_PIN1, LOW );
  digitalWrite( _8PINO_MOTOR_ROTATION_CTRL_PIN2, HIGH );
  
}

8pinoでI2C液晶パネルを使ってみる

一年位前に

自分の中でIoTブームが来た事があって、社内のRaspberryPi講座を受けさせてもらいました。

そのときに、教材として、色々と電子工作部品を戴いたなと、ハタと思い出したので、埃を被っていた袋をこじ開けて、これを見つけました。 初心者には、大変嬉しい完成版。

今回のゴール

液晶パネルが2行×8文字なので、
1行目 : 起動時間表示
2行目 : お店の看板みたいな文字列スクロール
をやってみようかと思います。

動かないんです

結線については、I2Cなので、V、GND、SDA、SCLを8pinoのそれらの専用端子に繋ぐだけです。何て、簡単。 f:id:tetunori_lego:20150603220553j:plain
iの24~28に差し込みます

f:id:tetunori_lego:20150603220608j:plain 差し込んだ後の図

で、格闘する事、小一時間。 うんともすんとも言ってくれません。 おんなじ部品で、Arduinoで実現している人沢山いるのに。

あまりに放置したから、壊れた?

原因を探る

原因1 : pull-up抵抗足りなかった

こちらのサイト曰く、

The pull-up resistors are necessary when using the ATtiny85. They are not necessary on the arduino because the arduino has internal pull-ups enabled when using the I2C interface.

SDA, SCLの共に、10kΩの抵抗を結線する必要がありました。
嬉しいことに、こちらの基板、その抵抗が実装済みで、ちょっとハンダ盛るだけで、実現可能です。

f:id:tetunori_lego:20150603222222j:plain 対応前

f:id:tetunori_lego:20150603222250j:plain 対応後

原因2 : スレーブアドレス間違い

だって、説明書に0x7Cって。 f:id:tetunori_lego:20150604072903j:plain
なんか世の中のサンプルコード見てたら、みんな0x3Eで実装している人が沢山いて、薄々おかしいなとは思っていました。
0x7C(0111 1100)を右に1ビットずらしたら、0x3E(0011 1110)となることに気が付いて、試してみたら動作しました!

調べてみたら、I2Cのアドレスは7bitだそうで。うーん、果たして誰が悪いのか。俺か。

ソフトウェアの準備

TinyWireM

ArduinoでI2Cを使うには、通常、Wire Libraryを使う様ですが、ATTiny85 では非対応な様で、 8pino公式サイトにもあるように

[I2C通信について]
下記のTinyWireMライブラリをご利用ください。
TinyWireM
https://github.com/adafruit/TinyWireM

TinyWireMライブラリを使います。 インストール方法等は、下記を参考にさせていただきました。

LCD表示のためのライブラリ

上で紹介したblogのコードを見てみたのですが、割りとマジックナンバー系の調整?が沢山必要そうでした。
それもそのはず、表示のための仕様書がこうですもの f:id:tetunori_lego:20150604072740j:plain
とても、気軽に実装できる内容ではありません。
Arduinoには、LiquidCrystalというライブラリがありますが、私の環境では、何かが不満らしく、動作しません。

探してみると、神様が現れました。 こちらのblogで、本LCDパネルをサポートした、Arduino向けのライブラリ(しかも、LiquidCrystal api コンパチ!)が公開されていました!

ただ、これは、Arduino向けのライブラリですので、TinyWireM向けに、修正します。

Wire.を、TinyWireM.に  Wire.write()を、TinyWireM.send()に書き換えれば動く。

→ どこかで見つけた、修正方法

LCD Test

Test 1

とにかく表示させてみる。
8pino LCD Test 1
カーソルの点滅がそれらしさを醸し出します。

Test 2

Test 1に加えて、scrollDisplayLeft()を確認。 f:id:tetunori_lego:20150604075307j:plain
そういう事ね。

Test 3

目的の1つだった、autoscroll()を試します。
スクロールはしてくれるのですが、インターフェースがわかりにくいのと、行毎のスクロール非対応っぽいので、使わないと、判断。 スクロールはAPI使わず実現すれば良いです。

本対応

出来ました。

起動開始からの時刻の表示は、millis() を利用しています。

LCD使えると、とたんに表現力が上がるなと感じます。デバッグにも良いでしょうし。

コードはこちら

#include <TinyWireM.h>
#include <ST7032.h>

// ST7032 lcd( int i2c_addr );
// i2c_addr: slave address
// omit i2c_addr -> 0x3E will be set.
// AE-AQM0802 works well with the default setting above.
ST7032 lcd;

#define _8PINO_LCD_NUM_OF_COLUMNS ( 8 )
#define _8PINO_LCD_NUM_OF_ROWS    ( 2 )

#define _8PINO_LCD_CONTRAST ( 30 )
#define _8PINO_LCD_TEXT_SCROLL_DELAY ( 200 )

void setup(){
  
  // For LCD Panel.
  lcd.begin( _8PINO_LCD_NUM_OF_COLUMNS, _8PINO_LCD_NUM_OF_ROWS );
  lcd.setContrast( _8PINO_LCD_CONTRAST );
  
  /* 
  // TEST 1
  lcd.print("8pino:");
  lcd.setCursor(0, 1);
  lcd.print("Awesome");
  lcd.cursor();
  lcd.blink();
  */
  
  /*
  // TEST 2
  lcd.print("8pino:");
  lcd.setCursor(0, 1);
  lcd.print("Awesome");
  lcd.cursor();
  lcd.blink();
  lcd.scrollDisplayLeft();
  */

  /*
  // TEST 3
  lcd.setCursor(0, 0);
  for (int thisChar = 0; thisChar < 8; thisChar++) {
   lcd.print(thisChar);
   delay( _8PINO_LCD_TEXT_SCROLL_DELAY );
  }

  lcd.setCursor(8, 1);
  // set the display to automatically scroll:
  lcd.autoscroll();
  for (int thisChar = 9; thisChar < 8; thisChar++) {
    lcd.print(thisChar);
    delay( _8PINO_LCD_TEXT_SCROLL_DELAY );
  }
  // turn off automatic scrolling
  lcd.noAutoscroll();
  lcd.clear();
  */
  
}

void loop(){
  
  int i = 0;
  int str_head_pos = 0;
  char teststr[] = "        8pino -> The minimalist's arduino/trinket compatible!          ";
  
  while( 1 ){
    
    // Text Scroll
    lcd.setCursor( 0, 1 );
    for ( i = str_head_pos; i < str_head_pos + _8PINO_LCD_NUM_OF_COLUMNS; i++ ){
      lcd.print( teststr[i] );
    }
    
    str_head_pos++;
    if( str_head_pos > sizeof( teststr ) - _8PINO_LCD_NUM_OF_COLUMNS ){
      str_head_pos = 0;
    }
    
    // Time
    unsigned long time;
    time = millis();
    
    lcd.setCursor( 0, 0 );
    lcd.print( "Sec:" );
    lcd.print( ( time / 10000 ) % 10 );
    lcd.print( ( time / 1000 ) % 10 );
    lcd.print( "." );
    lcd.print( ( time / 100 ) % 10 );
    delay( _8PINO_LCD_TEXT_SCROLL_DELAY );
    
  }
  
}

まだ

他にも、RaspberryPi研修でもらった部品があるので、次回はそちらを深堀してみます。

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で多くを対応するっていうのは本当に難しい。

8pinoでSoftwareSerialを使う その2

以前の投稿

ただ、あまりUART経由で指示を出すと、電子工作の勉強からは外れてしまうので、それほど深堀しない予定です。

と言ったはずですが、ソフト屋さんとしては、ちょっとだけ、パチコチやりたくなってしまうわけです。

と言うわけで

まずは対話型のインターフェースの基礎をテストすべく、Neopixelの制御を実装してみました。

動画はこちら

仕様は下記の通り

  • r → 赤く光る
  • g → 緑色に光る
  • b → 青く光る
  • 8 → 七色に光る
  • x → 消灯

ターミナル上はこんな感じ。 f:id:tetunori_lego:20150602070055j:plain
うん、想定通り動いています。
※ コードは一番下に記載。

もう一個くらい、デモしたい

せっかくベースを作ったので、他の例も試してみたいです。

この間 とかのシリーズで、圧電スピーカーを制覇したので、これを応用してみたい!
そんな前提で辺りを見回すと、こんなものがありました。 f:id:tetunori_lego:20150602074521j:plain
子供向け(おもちゃ)のピアノ絵本です。
これを作ってみましょう。

キーボードに対して、白鍵・黒鍵をこのようにマッピングします。 f:id:tetunori_lego:20150602074656j:plain

そして、結果

できました。

今回も音階に合わせて、LED光らせています。

ピアノを習っている六歳児に渡すと、それなりに弾ける様でした。

ターミナルの様子。
f:id:tetunori_lego:20150602075847j:plain

考察

ピアノ絵本は楽天価格で、2000円以上するみたいなので、わりとリーズナブルに同程度の環境が構築出来たことになります。

だから、何?

後、やっぱり、出来そうなことをやって、
結果、出来ても、成長はしないですね。
次回は電子工作寄りの話に戻します。

LEDのコードはこちら。

/*
  Software serial test
  Control Adafruit Neopixel Ring
 */

#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 );

#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 );

void setup()  
{
  
  pinMode( NEOPIXEL_IN_PIN, OUTPUT );
  
#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"
  
  // set the data rate for the SoftwareSerial port
  mySerial.begin(4800);
  mySerial.println("");
  mySerial.println("--- Hello! from 8pino... ---");
  mySerial.write( _8PINO_PROMPT_STRING );
  
}

void loop() // run over and over
{
  
  int tmp_char = 0;
  int i = 0;
  
  if ( mySerial.available() ){
    tmp_char = mySerial.read();
    if( tmp_char == '\r' ){
      mySerial.write( _8PINO_PROMPT_STRING );
    }else if( tmp_char == 'r' ){
      mySerial.write( tmp_char );
      mySerial.write( _8PINO_PRINT_NEOPIXEL_RING_CONTROL);
      mySerial.write( "Red!" );
      for( i = 0; i < NUM_OF_PIXELS; i++ ){
        pixels.setPixelColor( i, 255, 0, 0 );
      }
      pixels.show();
      mySerial.write( _8PINO_PROMPT_STRING );
    }else if( tmp_char == 'g' ){
      mySerial.write( tmp_char );
      mySerial.write( _8PINO_PRINT_NEOPIXEL_RING_CONTROL);
      mySerial.write( "Green!" );
      for( i = 0; i < NUM_OF_PIXELS; i++ ){
        pixels.setPixelColor( i, 0, 255, 0 );
      }
      pixels.show();
      mySerial.write( _8PINO_PROMPT_STRING );
    }else if( tmp_char == 'b' ){
      mySerial.write( tmp_char );
      mySerial.write( _8PINO_PRINT_NEOPIXEL_RING_CONTROL);
      mySerial.write( "Blue!" );
      for( i = 0; i < NUM_OF_PIXELS; i++ ){
        pixels.setPixelColor( i, 0, 0, 255 );
      }
      pixels.show();
      mySerial.write( _8PINO_PROMPT_STRING );
    }else if( tmp_char == '8' ){
      mySerial.write( tmp_char );
      mySerial.write( _8PINO_PRINT_NEOPIXEL_RING_CONTROL);
      mySerial.write( "Rainbow!" );
      for( i = 0; i < NUM_OF_PIXELS; i++ ){
        pixels.setPixelColor( i, Wheel( ( i * 256 / pixels.numPixels() ) & 255 ) );
      }
      pixels.show();
      mySerial.write( _8PINO_PROMPT_STRING );
    }else if( tmp_char == 'x' ){
      mySerial.write( tmp_char );
      mySerial.write( _8PINO_PRINT_NEOPIXEL_RING_CONTROL);
      mySerial.write( "Off!" );
      for( i = 0; i < NUM_OF_PIXELS; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      pixels.show();
      mySerial.write( _8PINO_PROMPT_STRING );
    }else{
      mySerial.write( tmp_char );
    }
  }
  
}

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);
  }
  
}

ピアノのコードはこちら。

/*
  Software serial test
  Control Buzzer
 */

#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 );

#define _8PINO_SOFTWARE_SERIAL_PIN_RX ( 1 ) 
#define _8PINO_SOFTWARE_SERIAL_PIN_TX ( 2 ) 

#define _8PINO_PROMPT_STRING ( "\r\n8pino > " )

SoftwareSerial mySerial( _8PINO_SOFTWARE_SERIAL_PIN_RX, _8PINO_SOFTWARE_SERIAL_PIN_TX );

#define _8PINO_TONE_DELAY_TIME  ( 150 )

#define _8PINO_TONE_SPEAKER_PIN_1 ( 1 )
#define _8PINO_TONE_SPEAKER_PIN_2 ( 4 )

#define _8PINO_TONE_START ( 0x00 )
#define _8PINO_TONE_STOP  ( 0x01 )

#define _8PINO_TONE_NOT_USED ( 0 )

#define _8PINO_TONE_DO_2    ( 238 )
#define _8PINO_TONE_RE_2    ( 212 )
#define _8PINO_TONE_MI_2    ( 189 )
#define _8PINO_TONE_FA_2    ( 178 )
#define _8PINO_TONE_FA_SH_2 ( 168 )
#define _8PINO_TONE_SO_2    ( 158 )
#define _8PINO_TONE_SO_SH_2 ( 150 )
#define _8PINO_TONE_RA_2    ( 141 )
#define _8PINO_TONE_SI_FL_2 ( 133 )
#define _8PINO_TONE_SI_2    ( 126 )
#define _8PINO_TONE_DO_3    ( 118 )
#define _8PINO_TONE_DO_SH_3 ( 112 )
#define _8PINO_TONE_RE_3    ( 106 )
#define _8PINO_TONE_RE_SH_3 (  99 )
#define _8PINO_TONE_MI_3    (  94 )
#define _8PINO_TONE_FA_3    (  89 )
#define _8PINO_TONE_FA_SH_3 (  83 )
#define _8PINO_TONE_SO_3    (  79 )
#define _8PINO_TONE_SO_SH_3 (  74 )
#define _8PINO_TONE_RA_3    (  70 )
#define _8PINO_TONE_SI_FL_3 (  66 )
#define _8PINO_TONE_SI_3    (  62 )
#define _8PINO_TONE_DO_4    (  59 )
#define _8PINO_TONE_DO_SH_4 (  55 )
#define _8PINO_TONE_RE_4    (  52 )
#define _8PINO_TONE_MI_4    (  46 )
#define _8PINO_TONE_FA_4    (  44 )
#define _8PINO_TONE_SO_4    (  39 )
#define _8PINO_TONE_RA_4    (  34 )

void setup()  
{
  
  pinMode( NEOPIXEL_IN_PIN, OUTPUT );
  pinMode( _8PINO_TONE_SPEAKER_PIN_2, OUTPUT );
  
#ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc.
  if( F_CPU == 16000000 ) clock_prescale_set( clock_div_1 );
#endif
  pixels.begin();
  pixels.setBrightness(15);
  pixels.show(); // Initialize all pixels to "off"
  
  // Configure Registers for PWM of PB4(PIN No.4)
  //  1. Comparator A Mode -> Set the OC1A output line.
  //  2. Time/Counter1 Prescale Select -> 8MHz/256 = 32KHz.
  //  3. Enable Pulse Width Modulator B.
  //  4. Comparator B Mode -> Set the OC1B output line
  TCCR1 = _BV (COM1A1) | _BV (COM1A0) | 
             _BV (CS13) | _BV (CS10);
  GTCCR = _BV (PWM1B) | _BV (COM1B1) | _BV (COM1B0);
  
  // set the data rate for the SoftwareSerial port
  mySerial.begin(4800);
  // mySerial.println("");
  // mySerial.println("--- Hello! from 8pino... ---");
  mySerial.write( _8PINO_PROMPT_STRING );
  
}

void loop() // run over and over
{
  
  int tmp_char = 0;
  int i = 0;
  int note = 0;
  int light_index = 0;
  
  if ( mySerial.available() ){
    tmp_char = mySerial.read();
    if( tmp_char == '\r' ){
      mySerial.write( _8PINO_PROMPT_STRING );
    }else{
      mySerial.write( tmp_char );
      mySerial.write( "\r\n " );
      switch( tmp_char ){
        case 'q':
          mySerial.write( "FA# 2" );
          note = _8PINO_TONE_FA_SH_2;
          light_index = 1;
          break;
        case 'a':
          mySerial.write( "SO 2" );
          note = _8PINO_TONE_SO_2;
          light_index = 2;
          break;
        case 'w':
          mySerial.write( "SO# 2" );
          note = _8PINO_TONE_SO_SH_2;
          light_index = 2;
          break;
        case 's':
          mySerial.write( "RA 2" );
          note = _8PINO_TONE_RA_2;
          light_index = 3;
          break;
        case 'e':
          mySerial.write( "SIb 2" );
          note = _8PINO_TONE_SI_FL_2;
          light_index = 3;
          break;
        case 'd':
          mySerial.write( "SI 2" );
          note = _8PINO_TONE_SI_2;
          light_index = 4;
          break;
        case 'f':
          mySerial.write( "DO 3" );
          note = _8PINO_TONE_DO_3;
          light_index = 5;
          break;
        case 't':
          mySerial.write( "DO# 3" );
          note = _8PINO_TONE_DO_SH_3;
          light_index = 5;
          break;
        case 'g':
          mySerial.write( "RE 3" );
          note = _8PINO_TONE_RE_3;
          light_index = 6;
          break;
        case 'y':
          mySerial.write( "RE# 3" );
          note = _8PINO_TONE_RE_SH_3;
          light_index = 6;
          break;
        case 'h':
          mySerial.write( "MI 3" );
          note = _8PINO_TONE_MI_3;
          light_index = 7;
          break;
        case 'j':
          mySerial.write( "FA 3" );
          note = _8PINO_TONE_FA_3;
          light_index = 8;
          break;
        case 'i':
          mySerial.write( "FA# 3" );
          note = _8PINO_TONE_FA_SH_3;
          light_index = 8;
          break;
        case 'k':
          mySerial.write( "SO 3" );
          note = _8PINO_TONE_SO_3;
          light_index = 9;
          break;
        case 'o':
          mySerial.write( "SO# 3" );
          note = _8PINO_TONE_SO_SH_3;
          light_index = 9;
          break;
        case 'l':
          mySerial.write( "RA 3" );
          note = _8PINO_TONE_RA_3;
          light_index = 10;
          break;
        case 'p':
          mySerial.write( "SIb 3" );
          note = _8PINO_TONE_SI_FL_3;
          light_index = 10;
          break;
        case ';':
          mySerial.write( "SI 3" );
          note = _8PINO_TONE_SI_3;
          light_index = 11;
          break;
        case ':':
          mySerial.write( "DO 4" );
          note = _8PINO_TONE_DO_4;
          light_index = 12;
          break;
        case '[':
          mySerial.write( "DO# 4" );
          note = _8PINO_TONE_DO_SH_4;
          light_index = 12;
          break;
        case ']':
          mySerial.write( "RE 4" );
          note = _8PINO_TONE_RE_4;
          light_index = 13;
          break;
        default : 
          mySerial.write( tmp_char );
          return;
      }
      
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_2, note, _8PINO_TONE_START );
      for( i = 0; i < light_index; i++ ){
        pixels.setPixelColor( i, 255, 255, 255 );
      }
      pixels.show();
      delay( _8PINO_TONE_DELAY_TIME );
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP );
      for( i = 0; i < NUM_OF_PIXELS; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      pixels.show();
      mySerial.write( _8PINO_PROMPT_STRING );
      
    }
    
  }
  
}

void _8pinoTone( int pin_speaker, uint8_t freq, uint8_t startstop ){
  if( startstop == _8PINO_TONE_START ){
    pinMode( pin_speaker, OUTPUT );
    // if( pin_speaker == _8PINO_TONE_SPEAKER_PIN_1 ){
    //   OCR0A = freq;
    //   OCR0B = OCR0A - 1;
    // }else{
      OCR1C = freq;
      OCR1B = OCR1C - 1;
    // }
  }else{
     pinMode( pin_speaker, INPUT );
  }
}

8pinoでSoftwareSerialを使う その1

困っていること

8pinoさんには、USBシリアルなどの手段がデフォルトで用意されていないため、デバッグが非常に困難です。

外部のセンサ情報を観察したい場合などで、困ることになります。 (注意:普通のarduinoでやれば、シリアル使えると思います。本ページでは8pino固執していまして…)

じゃあ、どうするか

策はありそうです。以前も参照した8pino+の方が、SoftwareSerialが使えたと記載されています。 これを試してみます。

SoftwareSerialを使うための部材

上記では変換基板を使われていますが、普通の家庭にはありません。
ですので、今回はこちらを仕入れました。

ただ

Compatible with Raspberry Pi A+,B,B+/2.

と言われると、arduino/trinket/8pinoに使えるのか不安だったのですが、UARTなんか共通仕様だろっ、とエイヤで。
(→結果、使えました)

接続トポロジー

Pin1を緑色、Pin2を白色に接続しています。勿論、黒はGNDf:id:tetunori_lego:20150527071241j:plain

ジャンパピン接続の拡大図。 8pinoから見て、それぞれ 緑色(Pin1) : RX、白色(Pin2) : TX
となります。 重要なポイントは、赤い線を接続していないこと。
この赤線は、USBからの電源供給用ですので、こっちのV系に入れちゃうと、電圧がぶつかるのかな?とブルったので結線せず。 f:id:tetunori_lego:20150527071256j:plain

上から俯瞰した図。
USBポートが2つあれば、満足いく開発が可能です。 f:id:tetunori_lego:20150527071309j:plain

Windowsでdriverのinstall

USBケーブルを挿すだけで、自動的にインストールが始まりました。特に他には何もせず、すぐに完了。私の環境では、COM5にアサインされました。 f:id:tetunori_lego:20150527073009j:plain

ターミナルの準備

みんな大好きteratermを使います。 f:id:tetunori_lego:20150527073213j:plain 新規接続すると、先程インストール済の「COM5 : Prolific …」が出てきますので、これでOK押します。 また、別途、ボーレートを4800に設定下さい。

SoftwareSerialを実装

API仕様や、 サンプルコードを一通り見た後、実装します。

対話型のサンプルアプリができました。 f:id:tetunori_lego:20150527074151j:plain 1発であまりにも上手く動いてしまい、teratermのローカルエコーか?と思ってしまったので、デバッグ的に'%'入力時だけ出力変えています。深い意味はありません。

コードはこちら

/*
  Software serial test
 */

#include <SoftwareSerial.h>

#define _8PINO_SOFTWARE_SERIAL_PIN_RX ( 1 ) 
#define _8PINO_SOFTWARE_SERIAL_PIN_TX ( 2 ) 

SoftwareSerial mySerial( _8PINO_SOFTWARE_SERIAL_PIN_RX, _8PINO_SOFTWARE_SERIAL_PIN_TX );

void setup()  
{
  
  // set the data rate for the SoftwareSerial port
  mySerial.begin(4800);
  mySerial.println("");
  mySerial.println("--- Hello! from 8pino... ---");
  mySerial.write( "\r\n > " );
  
}

void loop() // run over and over
{
  
  int tmp_char = 0;
  if ( mySerial.available() ){
    tmp_char = mySerial.read();
    if( tmp_char == '\r' ){
      mySerial.write( "\r\n > " );
    }else if( tmp_char == '%' ){
      mySerial.write( tmp_char );
      mySerial.write( "\r\n" );
      mySerial.write( "  % : Percentage sign \r\n" );
      mySerial.write( "    Percentage : In mathematics, a percentage is a number or ratio expressed as a fraction of 100. \r\n" ); 
      mySerial.write( "    It is often denoted using the percent sign. \"%\" \r\n" );
      mySerial.write( "    Sometimes the abbreviation \"pc\" is used in the case of quantities in economics.  \r\n");
      mySerial.write( "       From Wikipedia...  \r\n" );
      mySerial.write( "\r\n > " );
    }else{
      mySerial.write( tmp_char );
    }
  }
  
}

これで

UART経由で、外部から指示が出せるようになりました。
ただ、あまりUART経由で指示を出すと、電子工作の勉強からは外れてしまうので、それほど深堀しない予定です。

8pinoで圧電スピーカーを鳴らす その5

もう、飽きましたよね

8pinoで圧電スピーカーから曲を流すのはこれが最終回です。

発端は

前回の輪唱 を家族に自慢しに行った時の話です。

(私)「スゴいでしょ、これ!」
(家)「ウーン、すごさがよくわからないよ。輪唱もそんなに好きじゃないし」
(私)「…じゃあ、なんなら良いのさ!」
(家)「やっぱり、別々の旋律/和音を聞きたいでしょう。合唱とか、ピアノの曲とか」
(私)「ほぅ。例えば?」
(家)「合唱なら『ふるさと』、ピアノは『 パッフェルベルのカノン 』が好き」

と言うわけで 今度は、上記の2つを実現してみます。

早速、結果からどうぞ。

文部省唱歌 故郷(ふるさと) 合唱Ver.

ブザー音なのに、哀愁漂います。

パッフェルベルのカノン 両手Ver.

Johann Pachelbel : Canon in C.

エンドレスリピートな曲に仕上がりました。ちょっとペース早いかなぁ。

苦労した点とか

輪唱は良かったんです。だって、演奏するデータは、どっちのスピーカーも同じで良いので。
別々の旋律と言うことは、メモリも2倍、データ入力作業も2倍必要です。 例えばカノンの例だと、入力作業に1時間程かかっています。

「ふるさと」のコードはこちら

#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
#define NEOPIXEL_BRIGHTNESS 30
Adafruit_NeoPixel pixels = Adafruit_NeoPixel( NUM_OF_PIXELS, NEOPIXEL_IN_PIN );

// Definitions
#define _8PINO_TONE_START ( 0x00 )
#define _8PINO_TONE_STOP  ( 0x01 )

#define _8PINO_TONE_NOT_USED ( 0 )

#define _8PINO_TONE_SO_2 ( 158 )
#define _8PINO_TONE_RA_2 ( 141 )
#define _8PINO_TONE_SI_2 ( 126 )
#define _8PINO_TONE_DO_3 ( 118 )
#define _8PINO_TONE_RE_3 ( 106 )
#define _8PINO_TONE_MI_3 (  94 )
#define _8PINO_TONE_FA_3 (  89 )
#define _8PINO_TONE_FA_SH_3 (  83 )
#define _8PINO_TONE_SO_3 (  79 )
#define _8PINO_TONE_RA_3 (  70 )
#define _8PINO_TONE_SI_3 (  62 )
#define _8PINO_TONE_DO_4 (  59 )
#define _8PINO_TONE_RE_4 (  52 )
#define _8PINO_TONE_MI_4 (  46 )

// Global variables
#define _8PINO_TONE_SPEAKER_PIN_1 ( 1 )
#define _8PINO_TONE_SPEAKER_PIN_2 ( 4 )

#define SIZE_OF_TONE_ARRAY ( 192 )
PROGMEM prog_uint16_t noteArray1[] =
{
  
  // U-Sa-Gi O-I-Shi Ka-No-Ya-Ma-
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SI_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RE_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 

  // Ko-Bu-Na-Tsu-Ri-Shi Ka-No-Ka-Wa-
  _8PINO_TONE_DO_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RE_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_MI_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_DO_4, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_FA_SH_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  
  // Yu-Me-Ha-I-Ma-Mo-Me-Gu-Ri-Te
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_SO_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RE_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_RA_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_SI_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_MI_4, _8PINO_TONE_STOP, 
  _8PINO_TONE_RE_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_DO_4, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  
  // Wa-Su-Re-Ga-Ta-Ki Hu-Ru-Sa-To
  _8PINO_TONE_RE_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RE_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RE_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_RA_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  
};

PROGMEM prog_uint16_t noteArray2[] =
{
  
  // U-Sa-Gi O-I-Shi Ka-No-Ya-Ma-
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_FA_SH_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SO_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_FA_SH_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 

  // Ko-Bu-Na-Tsu-Ri-Shi Ka-No-Ka-Wa-
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_RA_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_FA_SH_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_FA_SH_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RE_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  
  // Yu-Me-Ha-I-Ma-Mo-Me-Gu-Ri-Te
  _8PINO_TONE_FA_SH_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_MI_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_FA_SH_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RE_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_FA_SH_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_SO_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_DO_4, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_RA_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  
  // Wa-Su-Re-Ga-Ta-Ki Hu-Ru-Sa-To
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_FA_SH_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_FA_SH_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  
};

void setup(){
  
  // Initialize PIN mode.
  pinMode( _8PINO_TONE_SPEAKER_PIN_1, OUTPUT );
  pinMode( _8PINO_TONE_SPEAKER_PIN_2, OUTPUT );
  
  // Configure Registers for PWM of PB1(PIN No.1)
  //  1. Waveform Generation Mode -> Fast PWM
  //  2. Clock Select -> 8MHz/256 = 32KHz.
  //  3. Compare Match Output B Mode
  //    -> Clear OC0A/OC0B on Compare Match, 
  //        set OC0A/OC0B at BOTTOM
  TCCR0A = _BV (COM0B1) | _BV (WGM01) | _BV (WGM00);
  TCCR0B = _BV (WGM02) | _BV (CS02);
  
  // Configure Registers for PWM of PB4(PIN No.4)
  //  1. Comparator A Mode -> Set the OC1A output line.
  //  2. Time/Counter1 Prescale Select -> 8MHz/256 = 32KHz.
  //  3. Enable Pulse Width Modulator B.
  //  4. Comparator B Mode -> Set the OC1B output line
  TCCR1 = _BV (COM1A1) | _BV (COM1A0) | 
             _BV (CS13) | _BV (CS10);
  GTCCR = _BV (PWM1B) | _BV (COM1B1) | _BV (COM1B0);
  
  // NeoPixel LED
  pinMode( NEOPIXEL_IN_PIN, OUTPUT );
  
#ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc.
  if( F_CPU == 16000000 ) clock_prescale_set( clock_div_1 );
#endif
  pixels.begin();
  pixels.setBrightness( NEOPIXEL_BRIGHTNESS );
  pixels.show(); // Initialize all pixels to "off"
  
}

void loop(){
  
  for( int count = 0; count < SIZE_OF_TONE_ARRAY; count++ )
  {
    if( pgm_read_word( &noteArray1[count] ) == _8PINO_TONE_NOT_USED ){
      // Do Nothing.
    }else if( pgm_read_word( &noteArray1[count] ) == _8PINO_TONE_STOP ){
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_1, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP );
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_1, _8PINO_TONE_STOP );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_2, _8PINO_TONE_STOP );
    }else{
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_1, pgm_read_word( &noteArray1[count] ), _8PINO_TONE_START );
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_2, pgm_read_word( &noteArray2[count] ), _8PINO_TONE_START );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_1, pgm_read_word( &noteArray1[count] ) );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_2, pgm_read_word( &noteArray2[count] ) );
    }
    
    pixels.show();
    delay( 8000 / OCR0A );
  }
  
}

void _8pinoTone( int pin_speaker, uint8_t freq, uint8_t startstop ){
  if( startstop == _8PINO_TONE_START ){
    pinMode( pin_speaker, OUTPUT );
    if( pin_speaker == _8PINO_TONE_SPEAKER_PIN_1 ){
      OCR0A = freq;
      OCR0B = OCR0A - 1;
    }else{
      OCR1C = freq;
      OCR1B = OCR1C - 1;
    }
  }else{
     pinMode( pin_speaker, INPUT );
  }
}

void setNeopixelColor( int speaker_id, int tone ){
  
  uint8_t led_index = 0;
  int i = 0;
  
  if( speaker_id == _8PINO_TONE_SPEAKER_PIN_1 ){
    switch( tone ){
      case _8PINO_TONE_RE_3:
        led_index = 12;
        break;
      case _8PINO_TONE_FA_SH_3:
        led_index = 14;
        break;
      case _8PINO_TONE_SO_3:
        led_index = 15;
        break;
      case _8PINO_TONE_RA_3:
        led_index = 0;
        break;
      case _8PINO_TONE_SI_3:
        led_index = 1;
        break;
      case _8PINO_TONE_DO_4:
        led_index = 2;
        break;
      case _8PINO_TONE_RE_4:
        led_index = 3;
        break;
      case _8PINO_TONE_MI_4:
        led_index = 3;
        break;
    }
    
    if( tone == _8PINO_TONE_STOP ){
      for( i = 0; i < 4; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      for( i = 12; i < 16; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
    }else{
      for( i = 0; i < 4; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      for( i = 12; i < 16; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      if( led_index < 4 ){
        for( i = 0; i < led_index + 1; i++ ){
          pixels.setPixelColor( i, 255, 0, 0 );
        }
        for( i = 12; i < 16; i++ ){
          pixels.setPixelColor( i, 255, 0, 0 );
        }
        
      }else{
        for( i = 12; i < led_index + 1; i++ ){
          pixels.setPixelColor( i, 255, 0, 0 );
        }
      }
    }
    
  }else{
    switch( tone ){
      case _8PINO_TONE_RE_3:
        led_index = 11;
        break;
      case _8PINO_TONE_MI_3:
        led_index = 10;
        break;
      case _8PINO_TONE_FA_SH_3:
        led_index = 9;
        break;
      case _8PINO_TONE_SO_3:
        led_index = 8;
        break;
      case _8PINO_TONE_RA_3:
        led_index = 7;
        break;
      case _8PINO_TONE_SI_3:
        led_index = 6;
        break;
      case _8PINO_TONE_DO_4:
        led_index = 5;
        break;
    }
    
    if( tone == _8PINO_TONE_STOP ){
      for( i = 5; i < 12; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
    }else{
      for( i = 5; i < 12; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      for( i = led_index; i < 12; i++ ){
        pixels.setPixelColor( i, 0, 255, 0);
      }
    }
    
  }
  
}

「カノン」のコードはこちら

#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
#define NEOPIXEL_BRIGHTNESS 30
Adafruit_NeoPixel pixels = Adafruit_NeoPixel( NUM_OF_PIXELS, NEOPIXEL_IN_PIN );

// Definitions
#define _8PINO_TONE_START ( 0x00 )
#define _8PINO_TONE_STOP  ( 0x01 )

#define _8PINO_TONE_NOT_USED ( 0 )

#define _8PINO_TONE_DO_2 ( 238 )
#define _8PINO_TONE_RE_2 ( 212 )
#define _8PINO_TONE_MI_2 ( 189 )
#define _8PINO_TONE_FA_2 ( 178 )
#define _8PINO_TONE_SO_2 ( 158 )
#define _8PINO_TONE_RA_2 ( 141 )
#define _8PINO_TONE_SI_2 ( 126 )
#define _8PINO_TONE_DO_3 ( 118 )
#define _8PINO_TONE_RE_3 ( 106 )
#define _8PINO_TONE_MI_3 (  94 )
#define _8PINO_TONE_FA_3 (  89 )
#define _8PINO_TONE_FA_SH_3 (  83 )
#define _8PINO_TONE_SO_3 (  79 )
#define _8PINO_TONE_RA_3 (  70 )
#define _8PINO_TONE_SI_3 (  62 )
#define _8PINO_TONE_SI_FL_3 ( 66 )
#define _8PINO_TONE_DO_4 (  59 )
#define _8PINO_TONE_RE_4 (  52 )
#define _8PINO_TONE_MI_4 (  46 )
#define _8PINO_TONE_FA_4 (  44 )
#define _8PINO_TONE_SO_4 (  39 )
#define _8PINO_TONE_RA_4 (  34 ) // 35

// Global variables
#define _8PINO_TONE_SPEAKER_PIN_1 ( 1 )
#define _8PINO_TONE_SPEAKER_PIN_2 ( 4 )

#define SIZE_OF_TONE_ARRAY ( 12 * 16 )
PROGMEM prog_uint16_t noteArray1[] =
{
  // 1
  _8PINO_TONE_SO_4, _8PINO_TONE_STOP, _8PINO_TONE_MI_4, _8PINO_TONE_FA_4, 
  _8PINO_TONE_SO_4, _8PINO_TONE_STOP, _8PINO_TONE_MI_4, _8PINO_TONE_FA_4, 
  _8PINO_TONE_SO_4, _8PINO_TONE_SO_3, _8PINO_TONE_RA_3, _8PINO_TONE_SI_3, 
  _8PINO_TONE_DO_4, _8PINO_TONE_RE_4, _8PINO_TONE_MI_4, _8PINO_TONE_FA_4, 

  _8PINO_TONE_MI_4, _8PINO_TONE_STOP, _8PINO_TONE_DO_4, _8PINO_TONE_RE_4, 
  _8PINO_TONE_MI_4, _8PINO_TONE_STOP, _8PINO_TONE_MI_3, _8PINO_TONE_FA_3, 
  _8PINO_TONE_SO_3, _8PINO_TONE_RA_3, _8PINO_TONE_SO_3, _8PINO_TONE_FA_3, 
  _8PINO_TONE_SO_3, _8PINO_TONE_MI_3, _8PINO_TONE_FA_3, _8PINO_TONE_SO_3, 

  _8PINO_TONE_FA_3, _8PINO_TONE_STOP, _8PINO_TONE_RA_3, _8PINO_TONE_SO_3, 
  _8PINO_TONE_FA_3, _8PINO_TONE_STOP, _8PINO_TONE_MI_3, _8PINO_TONE_RE_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_RE_3, _8PINO_TONE_DO_3, _8PINO_TONE_RE_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_FA_3, _8PINO_TONE_SO_3, _8PINO_TONE_RA_3, 

  _8PINO_TONE_FA_3, _8PINO_TONE_STOP, _8PINO_TONE_RA_3, _8PINO_TONE_SO_3, 
  _8PINO_TONE_RA_3, _8PINO_TONE_STOP, _8PINO_TONE_SI_3, _8PINO_TONE_DO_3, 
  _8PINO_TONE_SO_3, _8PINO_TONE_RA_3, _8PINO_TONE_SI_3, _8PINO_TONE_DO_4, 
  _8PINO_TONE_RE_4, _8PINO_TONE_MI_4, _8PINO_TONE_FA_4, _8PINO_TONE_SO_4, 

  // 5
  _8PINO_TONE_MI_4, _8PINO_TONE_STOP, _8PINO_TONE_DO_4, _8PINO_TONE_RE_4, 
  _8PINO_TONE_MI_4, _8PINO_TONE_STOP, _8PINO_TONE_RE_4, _8PINO_TONE_DO_4, 
  _8PINO_TONE_RE_4, _8PINO_TONE_SI_3, _8PINO_TONE_DO_4, _8PINO_TONE_RE_4, 
  _8PINO_TONE_MI_4, _8PINO_TONE_RE_4, _8PINO_TONE_DO_4, _8PINO_TONE_SI_3, 

  _8PINO_TONE_DO_4, _8PINO_TONE_STOP, _8PINO_TONE_RA_3, _8PINO_TONE_SI_3, 
  _8PINO_TONE_DO_4, _8PINO_TONE_STOP, _8PINO_TONE_DO_3, _8PINO_TONE_RE_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_FA_3, _8PINO_TONE_MI_3, _8PINO_TONE_RE_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_DO_4, _8PINO_TONE_SI_3, _8PINO_TONE_DO_4, 

  _8PINO_TONE_RA_3, _8PINO_TONE_STOP, _8PINO_TONE_DO_4, _8PINO_TONE_SI_3, 
  _8PINO_TONE_RA_3, _8PINO_TONE_STOP, _8PINO_TONE_SO_3, _8PINO_TONE_FA_3, 
  _8PINO_TONE_SO_3, _8PINO_TONE_FA_3, _8PINO_TONE_MI_3, _8PINO_TONE_FA_3, 
  _8PINO_TONE_SO_3, _8PINO_TONE_RA_3, _8PINO_TONE_SI_3, _8PINO_TONE_DO_4, 

  _8PINO_TONE_RA_3, _8PINO_TONE_STOP, _8PINO_TONE_DO_4, _8PINO_TONE_SI_3, 
  _8PINO_TONE_DO_4, _8PINO_TONE_STOP, _8PINO_TONE_SI_3, _8PINO_TONE_RA_3, 
  _8PINO_TONE_SI_3, _8PINO_TONE_DO_4, _8PINO_TONE_RE_4, _8PINO_TONE_DO_4, 
  _8PINO_TONE_SI_3, _8PINO_TONE_DO_4, _8PINO_TONE_RA_3, _8PINO_TONE_SI_3, 

  // 9
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SO_4, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_4, _8PINO_TONE_STOP, _8PINO_TONE_RA_4, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_4, _8PINO_TONE_STOP, _8PINO_TONE_FA_4, _8PINO_TONE_STOP, 
  
  _8PINO_TONE_MI_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_MI_4, _8PINO_TONE_STOP, 
  _8PINO_TONE_MI_4, _8PINO_TONE_STOP, _8PINO_TONE_FA_4, _8PINO_TONE_STOP, 
  _8PINO_TONE_MI_4, _8PINO_TONE_STOP, _8PINO_TONE_RE_4, _8PINO_TONE_STOP, 
  
  _8PINO_TONE_DO_4, _8PINO_TONE_STOP, _8PINO_TONE_SI_FL_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_3, _8PINO_TONE_STOP, _8PINO_TONE_SI_FL_3, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SO_3, _8PINO_TONE_STOP, 

  _8PINO_TONE_FA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_4, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

};

PROGMEM prog_uint16_t noteArray2[] =
{
  // 1
  _8PINO_TONE_DO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  
  _8PINO_TONE_RA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_MI_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  
  _8PINO_TONE_FA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

  _8PINO_TONE_FA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

  // 5
  _8PINO_TONE_DO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

  _8PINO_TONE_RA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_MI_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

  _8PINO_TONE_FA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

  _8PINO_TONE_FA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

  // 9
  _8PINO_TONE_DO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_MI_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

  _8PINO_TONE_RA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_MI_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

  _8PINO_TONE_FA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_DO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_MI_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

  _8PINO_TONE_FA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_RA_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_SI_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 

};

void setup(){
  
  // Initialize PIN mode.
  pinMode( _8PINO_TONE_SPEAKER_PIN_1, OUTPUT );
  pinMode( _8PINO_TONE_SPEAKER_PIN_2, OUTPUT );
  
  // Configure Registers for PWM of PB1(PIN No.1)
  //  1. Waveform Generation Mode -> Fast PWM
  //  2. Clock Select -> 8MHz/256 = 32KHz.
  //  3. Compare Match Output B Mode
  //    -> Clear OC0A/OC0B on Compare Match, 
  //        set OC0A/OC0B at BOTTOM
  TCCR0A = _BV (COM0B1) | _BV (WGM01) | _BV (WGM00);
  TCCR0B = _BV (WGM02) | _BV (CS02);
  
  // Configure Registers for PWM of PB4(PIN No.4)
  //  1. Comparator A Mode -> Set the OC1A output line.
  //  2. Time/Counter1 Prescale Select -> 8MHz/256 = 32KHz.
  //  3. Enable Pulse Width Modulator B.
  //  4. Comparator B Mode -> Set the OC1B output line
  TCCR1 = _BV (COM1A1) | _BV (COM1A0) | 
             _BV (CS13) | _BV (CS10);
  GTCCR = _BV (PWM1B) | _BV (COM1B1) | _BV (COM1B0);
  
  // NeoPixel LED
  pinMode( NEOPIXEL_IN_PIN, OUTPUT );
  
#ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc.
  if( F_CPU == 16000000 ) clock_prescale_set( clock_div_1 );
#endif
  pixels.begin();
  pixels.setBrightness( NEOPIXEL_BRIGHTNESS );
  pixels.show(); // Initialize all pixels to "off"
  
}

void loop(){
  
  for( int count = 0; count < SIZE_OF_TONE_ARRAY; count++ )
  {
    if( pgm_read_word( &noteArray1[count] ) == _8PINO_TONE_NOT_USED ){
      // Do Nothing.
    }else if( pgm_read_word( &noteArray1[count] ) == _8PINO_TONE_STOP ){
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_1, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_1, _8PINO_TONE_STOP );
    }else{
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_1, pgm_read_word( &noteArray1[count] ), _8PINO_TONE_START );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_1, pgm_read_word( &noteArray1[count] ) );
    }
    
    if( pgm_read_word( &noteArray2[count] ) == _8PINO_TONE_NOT_USED ){
      // Do Nothing.
    }else if( pgm_read_word( &noteArray2[count] ) == _8PINO_TONE_STOP ){
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_2, _8PINO_TONE_STOP );
    }else{
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_2, pgm_read_word( &noteArray2[count] ), _8PINO_TONE_START );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_2, pgm_read_word( &noteArray2[count] ) );
    }
    
    pixels.show();
    delay( 8000 / OCR0A );
  }
  
}

void _8pinoTone( int pin_speaker, uint8_t freq, uint8_t startstop ){
  if( startstop == _8PINO_TONE_START ){
    pinMode( pin_speaker, OUTPUT );
    if( pin_speaker == _8PINO_TONE_SPEAKER_PIN_1 ){
      OCR0A = freq;
      OCR0B = OCR0A - 1;
    }else{
      OCR1C = freq;
      OCR1B = OCR1C - 1;
    }
  }else{
     pinMode( pin_speaker, INPUT );
  }
}

void setNeopixelColor( int speaker_id, int tone ){
  
  uint8_t led_index = 0;
  int i = 0;
  int highlight = 0;
  
  if( speaker_id == _8PINO_TONE_SPEAKER_PIN_1 ){
    switch( tone ){
      case _8PINO_TONE_DO_3:
        led_index = 12;
        break;
      case _8PINO_TONE_RE_3:
        led_index = 12;
        highlight = 1;
        break;
      case _8PINO_TONE_MI_3:
        led_index = 13;
        break;
      case _8PINO_TONE_FA_3:
        led_index = 13;
        highlight = 1;
        break;
      case _8PINO_TONE_SO_3:
        led_index = 14;
        break;
      case _8PINO_TONE_RA_3:
        led_index = 14;
        highlight = 1;
        break;
      case _8PINO_TONE_SI_3:
        led_index = 15;
        break;
      case _8PINO_TONE_DO_4:
        led_index = 15;
        highlight = 1;
        break;
      case _8PINO_TONE_RE_4:
        led_index = 0;
        break;
      case _8PINO_TONE_MI_4:
        led_index = 0;
        highlight = 1;
        break;
      case _8PINO_TONE_FA_4:
        led_index = 1;
        break;
      case _8PINO_TONE_SO_4:
        led_index = 1;
        highlight = 1;
        break;
      case _8PINO_TONE_RA_4:
        led_index = 2;
        break;
      default:
        led_index = 12;
        break;
    }
    
    if( tone == _8PINO_TONE_STOP ){
      for( i = 0; i < 4; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      for( i = 12; i < 16; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
    }else{
      for( i = 0; i < 4; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      for( i = 12; i < 16; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      if( led_index < 4 ){
        for( i = 0; i < led_index + 1; i++ ){
          pixels.setPixelColor( i, 255, 0, 0 );
        }
        for( i = 12; i < 16; i++ ){
          pixels.setPixelColor( i, 255, 0, 0 );
        }
        
      }else{
        for( i = 12; i < led_index + 1; i++ ){
          pixels.setPixelColor( i, 255, 0, 0 );
        }
      }
      if( highlight == 1 ){
        pixels.setPixelColor( led_index, 255, 255, 255 );
      }
    }
    
  }else{
    switch( tone ){
      case _8PINO_TONE_DO_2:
        led_index = 11;
        break;
      case _8PINO_TONE_MI_2:
        led_index = 10;
        break;
      case _8PINO_TONE_FA_2:
        led_index = 9;
        break;
      case _8PINO_TONE_SO_2:
        led_index = 8;
        break;
      case _8PINO_TONE_RA_2:
        led_index = 7;
        break;
      case _8PINO_TONE_SI_2:
        led_index = 6;
        break;
      case _8PINO_TONE_DO_3:
        led_index = 5;
        break;
      default:
        led_index = 11;
        break;
    }
    
    if( tone == _8PINO_TONE_STOP ){
      for( i = 5; i < 12; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
    }else{
      for( i = 5; i < 12; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      for( i = led_index; i < 12; i++ ){
        pixels.setPixelColor( i, 0, 255, 0);
      }
    }
    
  }
  
}

以上で

8pinoコンサートは終演となります。
お付き合い頂き、ありがとうございました。

8pinoで圧電スピーカーを鳴らす その4

もう1つ輪唱

前回の投稿 で、輪唱の基礎は構築したので、応用は大変容易です。

目標の1つだった、「静かな湖畔」の輪唱にもチャレンジしてみましょう。

といってもやることは、ネットに落ちていた楽譜をデータ列に起こすだけです。 約30分で完了しました。

では、どうぞ

こちらも、輪唱パート毎にLEDを分けて光らせています。

基礎を1つ作ると、その後は超簡単ですね!

コードはこちら

#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
#define NEOPIXEL_BRIGHTNESS 30
Adafruit_NeoPixel pixels = Adafruit_NeoPixel( NUM_OF_PIXELS, NEOPIXEL_IN_PIN );

// Definitions
#define _8PINO_TONE_START ( 0x00 )
#define _8PINO_TONE_STOP  ( 0x01 )

#define _8PINO_TONE_NOT_USED ( 0 )

#define _8PINO_TONE_SO_2 ( 158 )
#define _8PINO_TONE_RA_2 ( 141 )
#define _8PINO_TONE_SI_2 ( 126 )
#define _8PINO_TONE_DO_3 ( 118 )
#define _8PINO_TONE_RE_3 ( 106 )
#define _8PINO_TONE_MI_3 (  94 )
#define _8PINO_TONE_FA_3 (  89 )
#define _8PINO_TONE_SO_3 (  79 )
#define _8PINO_TONE_RA_3 (  70 )
#define _8PINO_TONE_SI_3 (  62 )
#define _8PINO_TONE_DO_4 (  59 )

// Global variables
#define _8PINO_TONE_SPEAKER_PIN_1 ( 1 )
#define _8PINO_TONE_SPEAKER_PIN_2 ( 4 )

#define SIZE_OF_TONE_ARRAY ( 160 )
PROGMEM prog_uint16_t noteArray[] =
{
  
  // Wait...
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  
  // Shi-Zu-Ka-Na-Ko-Han-No
  _8PINO_TONE_DO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_DO_3, 
  _8PINO_TONE_DO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_RE_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_MI_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_MI_3, 
  
  // Mo-Ri-No-Ka-Ge-Ka-Ra
  _8PINO_TONE_RE_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_DO_3, 
  _8PINO_TONE_RE_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_MI_3, 
  _8PINO_TONE_DO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_DO_3, 
  _8PINO_TONE_SO_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  
  // Mou-Oki-Tya-I-Ka-Ga-To-Kakko-Ga-Na-Ku Ka-
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_FA_3, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SO_3, 
  _8PINO_TONE_SO_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SO_3, 
  _8PINO_TONE_FA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_MI_3, 
  _8PINO_TONE_FA_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SO_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SO_3, 
  
  //Kko Ka-Kko Ka-Kko Ka-Kko Ka-Kko
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_SO_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_SO_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SO_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, _8PINO_TONE_SO_3, 
  _8PINO_TONE_MI_3, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP, 
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  
  // Wait...
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED, _8PINO_TONE_NOT_USED,
  
};

void setup(){
  
  // Initialize PIN mode.
  pinMode( _8PINO_TONE_SPEAKER_PIN_1, OUTPUT );
  pinMode( _8PINO_TONE_SPEAKER_PIN_2, OUTPUT );
  
  // Configure Registers for PWM of PB1(PIN No.1)
  //  1. Waveform Generation Mode -> Fast PWM
  //  2. Clock Select -> 8MHz/256 = 32KHz.
  //  3. Compare Match Output B Mode
  //    -> Clear OC0A/OC0B on Compare Match, 
  //        set OC0A/OC0B at BOTTOM
  TCCR0A = _BV (COM0B1) | _BV (WGM01) | _BV (WGM00);
  TCCR0B = _BV (WGM02) | _BV (CS02);
  
  // Configure Registers for PWM of PB4(PIN No.4)
  //  1. Comparator A Mode -> Set the OC1A output line.
  //  2. Time/Counter1 Prescale Select -> 8MHz/256 = 32KHz.
  //  3. Enable Pulse Width Modulator B.
  //  4. Comparator B Mode -> Set the OC1B output line
  TCCR1 = _BV (COM1A1) | _BV (COM1A0) | 
             _BV (CS13) | _BV (CS10);
  GTCCR = _BV (PWM1B) | _BV (COM1B1) | _BV (COM1B0);
  
  // NeoPixel LED
  pinMode( NEOPIXEL_IN_PIN, OUTPUT );
  
#ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc.
  if( F_CPU == 16000000 ) clock_prescale_set( clock_div_1 );
#endif
  pixels.begin();
  pixels.setBrightness( NEOPIXEL_BRIGHTNESS );
  pixels.show(); // Initialize all pixels to "off"
  
}

void loop(){
  
  for( int count = 32; count < SIZE_OF_TONE_ARRAY; count++ )
  {
    if( pgm_read_word( &noteArray[count] ) == _8PINO_TONE_NOT_USED ){
      // Do Nothing.
    }else if( pgm_read_word( &noteArray[count] ) == _8PINO_TONE_STOP ){
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_1, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_1, _8PINO_TONE_STOP );
    }else{
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_1, pgm_read_word( &noteArray[count] ), _8PINO_TONE_START );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_1, pgm_read_word( &noteArray[count] ) );
    }
    
    if( pgm_read_word( &noteArray[count-32] ) == _8PINO_TONE_NOT_USED ){
      // Do Nothing.
    }else if( pgm_read_word( &noteArray[count-32] ) == _8PINO_TONE_STOP ){
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_2, _8PINO_TONE_NOT_USED, _8PINO_TONE_STOP );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_2, _8PINO_TONE_STOP );
    }else{
      _8pinoTone( _8PINO_TONE_SPEAKER_PIN_2, pgm_read_word( &noteArray[count-32] ), _8PINO_TONE_START );
      setNeopixelColor( _8PINO_TONE_SPEAKER_PIN_2, pgm_read_word( &noteArray[count-32] ) );
    }
    
    pixels.show();
    delay( 8000 / OCR0A );
  }
  
}

void _8pinoTone( int pin_speaker, uint8_t freq, uint8_t startstop ){
  if( startstop == _8PINO_TONE_START ){
    pinMode( pin_speaker, OUTPUT );
    if( pin_speaker == _8PINO_TONE_SPEAKER_PIN_1 ){
      OCR0A = freq;
      OCR0B = OCR0A - 1;
    }else{
      OCR1C = freq;
      OCR1B = OCR1C - 1;
    }
  }else{
     pinMode( pin_speaker, INPUT );
  }
}

void setNeopixelColor( int speaker_id, int tone ){
  
  uint8_t led_index = 0;
  int i = 0;
  
  if( speaker_id == _8PINO_TONE_SPEAKER_PIN_1 ){
    switch( tone ){
      case _8PINO_TONE_SO_2:
        led_index = 12;
        break;
      case _8PINO_TONE_DO_3:
        led_index = 13;
        break;
      case _8PINO_TONE_RE_3:
        led_index = 14;
        break;
      case _8PINO_TONE_MI_3:
        led_index = 15;
        break;
      case _8PINO_TONE_FA_3:
        led_index = 0;
        break;
      case _8PINO_TONE_SO_3:
        led_index = 1;
        break;
    }
    
    if( tone == _8PINO_TONE_STOP ){
      for( i = 0; i < 2; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      for( i = 12; i < 16; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
    }else{
      for( i = 0; i < 2; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      for( i = 12; i < 16; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      if( led_index < 2 ){
        for( i = 0; i < led_index + 1; i++ ){
          pixels.setPixelColor( i, 255, 0, 0 );
        }
        for( i = 12; i < 16; i++ ){
          pixels.setPixelColor( i, 255, 0, 0 );
        }
        
      }else{
        for( i = 12; i < led_index + 1; i++ ){
          pixels.setPixelColor( i, 255, 0, 0 );
        }
      }
    }
    
  }else{
    switch( tone ){
      case _8PINO_TONE_SO_2:
        led_index = 11;
        break;
      case _8PINO_TONE_DO_3:
        led_index = 10;
        break;
      case _8PINO_TONE_RE_3:
        led_index = 9;
        break;
      case _8PINO_TONE_MI_3:
        led_index = 8;
        break;
      case _8PINO_TONE_FA_3:
        led_index = 7;
        break;
      case _8PINO_TONE_SO_3:
        led_index = 6;
        break;
    }
    
    if( tone == _8PINO_TONE_STOP ){
      for( i = 6; i < 12; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
    }else{
      for( i = 6; i < 12; i++ ){
        pixels.setPixelColor( i, 0, 0, 0 );
      }
      for( i = led_index; i < 12; i++ ){
        pixels.setPixelColor( i, 0, 255, 0);
      }
    }
    
  }
  
}

まだまだ

圧電スピーカーハックは続きます。