Mira&Luna's nursery lab

旅乙女と発明娘の子供部屋

EEPROMを使った電子オルゴールの自作3。読み込みと曲を流すプログラムの紹介🌼

f:id:miraluna:20200223191041j:plain:w200 Mira

自作電子工作🐇
ArduinoとEEPROMを使った電子オルゴール🎹
「Tiny蓄音機レコード仕様🍩」の作り方



<第3回>
EEPROMから楽譜を読み取って演奏するプログラム」



目次
   🍩 Tiny蓄音機レコード仕様を作ろう 🍩
🍩1回目「 構想とEEPROMについてと曲紹介
🍩2回目「EEPROMに楽譜を記録♬ "レコード盤作り"
🍩3回目「EEPROMから楽譜を読み取って演奏するプログラム」(この記事)
🍩4回目「トラブル1🐉 ArduinoのRAMが足りない..p_q..💦
🍩5回目「[トラブル2🦇 tone関数ではすべての音符を鳴らせない
🍩6回目「"ちびやっこ"意気消沈。お姉ちゃんの"みつは"は超オンチに🦆
🍩7回目「Tiny蓄音機レコード仕様、実装します。& 動画🎬
🍩8回目「Tiny蓄音機レコード仕様🎶 作り方まとめっ♬


「Tiny蓄音機レコード仕様」~イメージ~
f:id:miraluna:20210926165439j:plain

前回の記事でEEPROMに楽譜データを書き込むことができ、「EEPROMレコード盤🍩」が完成しました(∂. ∂🎀
今回はEEPROMからデータを読み込んで、音を出して楽譜を演奏するプログラムと配線を紹介します🍭



読み出し演奏プログラムスケッチ

このプログラムはArduinoに初めから備わっている"tone関数"を使ったスケッチ例「toneMelody」をベースにしています。

f:id:miraluna:20210926181547p:plain:w300:right



「toneMelody」のスケッチ例は、Arduino IDEのここ⇒ にあります。





このスケッチ(プログラム)に、EEPROMのデータを読み出すプログラムを書き加えて、読み出した楽譜データをtone関数で演奏します。

🍎 プログラム 🍎

// Tiny蓄音機実装用 [各曲共用]
// 周波数を÷4で濃縮還元した曲用
#include<Wire.h>

int eep_read(int device_add, unsigned int eep_add){
  Wire.beginTransmission(device_add);//対象デバイスへ移動
  Wire.write((int)(eep_add >> 8));
  Wire.write((int)(eep_add & 0xff));
  Wire.endTransmission();
  
  Wire.requestFrom(device_add,1);
  if(Wire.available()){}
  return Wire.read();
}

void setup() {
  Wire.begin();
}

void loop() {
  int onpu = eep_read(0x50,0);  //0番地から音符数を読む
  int sokudo = eep_read(0x50,1);//1番地から速度を読む(100分の1)
  
  for(int note = 0; note < onpu; note++){  //演奏部
    int melody =eep_read(0x50,note+2);  //音階の読み出し
    int duration = eep_read(0x50,note+onpu+2);  //音符の長さの読み出し
    int noteDuration = sokudo*100 / duration;   //速度を復元(x100)
    tone(3, melody*4, noteDuration);  //ブザーは3pin

    int note_hazama = noteDuration * 1.10;  //音符同士の合間の長さ
    delay(note_hazama);
  }
}

プログラムをみつは(ATmega328(マイコン))に書き込めば、Tiny蓄音機#レコード仕様の本体のできあがりです。
それではプログラムを書き込んだみつはと、レコード盤であるEEPROMを配線していきましょう。



みつはEEPROM配線
f:id:miraluna:20210920085347p:plain

f:id:miraluna:20200211155724j:plain:w200:left【 [24LC64] pin配置図 ↓ 】 【 [みつは] pin配置図 ↓ 】

f:id:miraluna:20210929195228p:plain:w200f:id:miraluna:20211001191917p:plain:w180

このように配線します🍓
ブザーは3番pin。
抵抗はプルアップ用で2kΩです(値は近似値でO.K.)。
この他に、電源(2.5~5.5v)もつないでね🔋


これでいよいよ"Tiny蓄音機#レコード仕様"でレコードを再生する準備が整いました。
電源を入れてみつはを動作させてみます🚲
f:id:miraluna:20210920085724j:plain:w290 f:id:miraluna:20210920085744j:plain:w290

f:id:miraluna:20191015184121j:plain:w200 ジョージ・ウィンストンさんの『あこがれ/愛』(ミラ仕様) がブザーから流れ出しました。



EEPROMに楽譜データを書き込んで、そこから読み取ったデータを電子オルゴールとして鳴らす。というもくろみはこれにて大成功です(∂, ∂🎀y
これでも満足なんだけど、今回のプロジェクトではもっと長い『OneNight』という曲をEEPROMに保存したいとたくらんでいます。

次回からは『OneNight』プログラムの作製に入ります。
これがまたいつものようになかなかうまくいかなかったんです🍆

ミラでした。
Mira



目次
   🍩 Tiny蓄音機レコード仕様を作ろう 🍩
🍩1回目「 構想とEEPROMについてと曲紹介
🍩2回目「EEPROMに楽譜を記録♬ "レコード盤作り"
🍩3回目「EEPROMから楽譜を読み取って演奏するプログラム」(この記事)
次回」🍩4回目「トラブル1🐉 ArduinoのRAMが足りない..p_q..💦
🍩5回目「[トラブル2🦇 tone関数ではすべての音符を鳴らせない
🍩6回目「"ちびやっこ"意気消沈。お姉ちゃんの"みつは"は超オンチに🦆
🍩7回目「Tiny蓄音機レコード仕様、実装します。& 動画🎬
🍩8回目「Tiny蓄音機レコード仕様🎶 作り方まとめっ♬



<お買い物コーナー>

♬ これを筐体にしたら素敵ね。   ♬ 本物の蓄音機(Bluetooth対応)
             

EEPROMに楽譜を記録する♬ ♪ ♬ Tiny蓄音機レコード仕様プロジェクト2 [EEPROMレコード盤作り]

f:id:miraluna:20180806220931j:plain:w200 Mira

自作電子工作🧸
Arduino外付けEEPROMを使った電子オルゴールTiny蓄音機レコード仕様」を作ろう🍩


<第2回>
EEPROM楽譜記録♬ "レコード盤作り"」



目次
   🍩 Tiny蓄音機レコード仕様を作ろう 🍩
🍩1回目「 構想とEEPROMについてと曲紹介
🍩2回目「EEPROMに楽譜を記録♬ "レコード盤作り"」(この記事)
🍩3回目「EEPROMから楽譜を読み取って演奏するプログラム
🍩4回目「トラブル1🐉 ArduinoのRAMが足りない..p_q..💦
🍩5回目「[トラブル2🦇 tone関数ではすべての音符を鳴らせない
🍩6回目「"ちびやっこ"意気消沈。お姉ちゃんの"みつは"は超オンチに🦆
🍩7回目「Tiny蓄音機レコード仕様、実装します。& 動画🎬
🍩8回目「Tiny蓄音機レコード仕様🎶 作り方まとめっ♬

~これから何回かに分けて書いていきます。書いたら目次も増やしていきます。~



⛅ イメージ図 🦄
f:id:miraluna:20210926165439j:plain

"Tiny蓄音機レコード仕様"のイメージはこんな感じです。
蓄音機には "ATmega328" AVRマイコン(みつは)を、
レコードには "24LC64" EEPROM( "24FC64" その他でもO.K.)を使う予定です。

[24LC64]が記憶媒体のEEPROM。I²C接続なら、他のEEPROMも使えます。
ここに曲を入れて、いろんなレコード盤を作る予定なの🍅


EEPROMの使い方
Arduinoを使って外付けEEPROMを使う方法は以前の記事に書いたので、電子オルゴールとは関係なくEEPROMへの読み書きの方法を知りたい方はこちらを読んでみてね。
miraluna.hatenablog.com


楽譜の再生にはtone関数を使う

EEPROMへの読み書きができるようになったら、そのデータをtone関数で再生します。
「tone関数」というのはArduinoにもともと備わっているスケッチ(プログラム)で、それを使えばブザーとかスピーカで簡単にメロディを鳴らすことができるの。
スケッチは「toneMelody」という名前。Arduino IDEを開いて、「ファイル」→「スケッチ例」→「02.Digital」→「toneMelody」の場所にありす。(ねぇアリス、"ま"が抜けてるわよ。それじゃあまるであなたが......)

ここですよ🍎
f:id:miraluna:20210926181547p:plain

tone関数を使って曲を流したときのプログラムの例はこちら 👇 の記事にあります。
miraluna.hatenablog.com


tone関数では音符の音階[Melody]と、音符の長さ[noteDurations]の2つのデータを組み合わせることで音を出します。「8分音符のド」とか。だから2種類の情報をEEPROMに記憶させておく必要がありますね。私の場合、記憶する番地の前半に音階データを、後半に長さデータを入れました。

ここで1つ問題が発生。tone関数は音符データの他に、曲の音符の総数と、曲の速度という2つの情報も必要です。この情報は再生するプログラムに書かなくてはいけません。でもそれって曲ごとに違う🐧。これでは蓄音機(みつは)のプログラムも曲ごとに書き換えなくちゃいけなくなる。それじゃ「Tiny蓄音機レコード仕様」にならないよ~💦
そこで発明少女ミラヒェン f:id:miraluna:20210106121707j:plain:w30 の工夫が光ります✨(自分で言うな)🍘

工夫音符の数と曲の速度の2つのデータをEEPROM(レコード盤)に収めておいて、蓄音機のプログラムでそのデータも読み取るようにしちゃおう(∂, ∂🎀y
そんなわけでEEPROMの
0番地には曲の音符の総数を、
1番地には曲の速度を、
書き込むことにしました。

さあ、それでは音符データをプログラムしていきましょう、とはりきっていたら、また問題が発生。音符の音階データは、その音の「周波数」を入れるんだけど、EEPROMの1つの番地(1つのデータを書き込める場所)は容量が1バイト。1バイトは0と1の情報(ビット)が8つ集まったものだから、2進法で8桁、つまり0~255の値しか表現できないの。音階の周波数には500とか800とかいう高い音のものもある。これじゃ低い音しか表現できないよ..p_q..💦
そこで🌟 またまた発明少女ミラヒェン f:id:miraluna:20210106121720j:plain:w30 の工夫がきらっと輝きます✨(ドヤ顔すな)🍙

工夫周波数の値を4分の1の大きさでEEPROMに格納して、蓄音機で読みだしたときに4倍する。曲の速度も1700とか5000とかだから、100分の1にして読むときに100倍する。
ほら、ジュースの濃縮果汁還元ってあるでしょ? あれよあれ(∂_∂🎀y ドヤァ



EEPROMに楽譜を書き込むためのプログラム
tone関数を使うための下準備が整ったので、EEPROMに楽譜(音符の音階と長さのデータ)を書き込むためのプログラムを作ります。『OneNight』は私にとって大作なので、まずは短い曲で作ってみましょう。ジョージ・ウィンストンさんの『あこがれ/愛』のサビのところです。

🍎 EEPROMへ楽譜を書き込むためのスケッチ 🍎

//EEPROMへ書込むためのツールスケッチ
//使用時に曲に合わせて書き換えが必要
//『あこがれ』

#include<Wire.h>

 int melody[] = {    //音符の音階(周波数)
  330,440,523, 659,523,440, 587,494,392, 523,494,440,330,
  440,494,523, 330,523,330, 494,294,494,294, 440,262,165,220,  //Akogare
 };
 int durations[] = {    //音符の長さ(16→16分音符)
 16,16,16, 8,16,16, 8,16,16, 16,16,16,8,  //13(音符の数)
 16,16,8,16,16,16, 16,16,16,16, 16,16,16,8,  //14  
 };                                     //音符総数 : 27
    
void eep_write(int device_add, unsigned int eep_add, int data){
  Wire.beginTransmission(device_add);//対象デバイスへ移動
  Wire.write((int)(eep_add >> 8));
  Wire.write((int)(eep_add & 0xff));
  Wire.write(data);
  Wire.endTransmission();
}

void setup() {
  Wire.begin();
    for(int n=2; n < 27+2; n++){        //要書換「音符の数」  2番地から書き込み
              //[あこがれ:27音符]
      eep_write(0x50,n,melody[n-2]/4);  //デバイス[0x50]  4分の1に濃縮
        delay(5);//書き込み待ち
      eep_write(0x50,n+27,durations[n-2]);    //要書換「音符の数」
        delay(5);//書込み待ち
    }
      eep_write(0x50,0,27);  //要書換「音符数」 0番地に音符数格納
        delay(5);
      eep_write(0x50,1,50);  //要書換「曲の速度」 1番地に曲の速度格納(100分の1で書く)
              //速度[あこがれ:5000]
        delay(5);
}

void loop() {

}

EEPROMをArduinoにつなぐ配線

プログラムができあがったら、EEPROMに楽譜を書き込みます。
書き込みを行う装置はArduino。だからArduinoとEEPROMを配線しなきゃいけないわね。

配線方法はこちらです。
f:id:miraluna:20210920085453p:plain
                           「24LC64」の pin配置図
f:id:miraluna:20210929195228p:plain:w200:right  Arduino     EEPROM
  5v      (赤)     Vcc
  GND     (黒)     GND(Vss)
  SCL      (黄)     SCL
  SDA  (緑) 2kΩ分岐    SDA
  5v           分岐した2kΩ
  GND    (水色)     WP
  GND     (橙)     A0
  GND     (橙)     A1
  GND     (橙)     A2

※WPはGNDにつなぐと書き込み可。5vにつなぐと書き込み不可。
※橙のA0~A2はデバイスアドレス用チップセレクト。全部GNDならアドレスは[0x50]。
※SDAの2kΩはプルアップ用。厳密に2kΩでなくてもO.K.(2.2kとか4.7kとか)。


配線完了(∂. < 🎀/

この状態で Arduinoに上の楽譜書き込み用プログラムを書き込めば、
EEPROMの0番地には音符数の「27」が、
1番地には曲の速度(100分の1)の「50」が、
2番地~28番地には音符の音階「melody」が、
29番地~55番地には音符の長さ「durations」が格納されるはず。

つまり楽譜をEEPROMに記憶させたわけだから、
EEPROM🍩レコード盤の完成 f:id:miraluna:20191015184121j:plain:w100


次回はEEPROMレコード盤から楽譜を読み取って、実際に曲を鳴らすプログラムスケッチを紹介します。
ミラでした。またね(∂, ∂🎀ノシ
f:id:miraluna:20180127173159j:plain:w200 🧸ミラの部屋へ🧸



目次   🍩 Tiny蓄音機レコード仕様を作ろう 🍩
🍩1回目「 構想とEEPROMについてと曲紹介
🍩2回目「EEPROMに楽譜を記録♬ "レコード盤作り"」(この記事)
[次回]🍩3回目「EEPROMから楽譜を読み取って演奏するプログラム
🍩4回目「トラブル1🐉 ArduinoのRAMが足りない..p_q..💦
🍩5回目「[トラブル2🦇 tone関数ではすべての音符を鳴らせない
🍩6回目「"ちびやっこ"意気消沈。お姉ちゃんの"みつは"は超オンチに🦆
🍩7回目「Tiny蓄音機レコード仕様、実装します。& 動画🎬
🍩8回目「Tiny蓄音機レコード仕様🎶 作り方まとめっ♬

EEPROM[24LC64]をレコードにするTiny蓄音機🍩 自作電子工作の楽しみ方🍬

f:id:miraluna:20210920081120j:plain:w200 Mira

♪ EEPROMに曲を入れる電子オルゴール ♬
🍩 外付けEEPROMレコード盤にした、レコード仕様Tiny蓄音機 🍨


<第1回>
構想EEPROMについてと紹介」

🍎 今から作ろうとしている電子オルゴール「Tiny蓄音機レコード仕様」は、曲を複数のEEPROMに入れておいて、それをレコード盤のように交換するだけでいろいろな曲を聞くことができる、という「Tiny蓄音機」なの。

 🐟 前に作った「Tiny蓄音機」の記事 ↓
ATtiny85を使ったボトルキャップTiny蓄音機
🎀 EEPROMというのは情報を記憶できるパーツ。外付けメモリね。



目次
このプロジェクトは次々に降りかかる困難(エラー)を乗り越えて、夢に描いたガジェットを創り上げようとする電子工作少女の成長物語です(ちょっと過言)。

   🍩 Tiny蓄音機レコード仕様を作ろう 🍩
🍩1回目「 構想とEEPROMについてと曲紹介」(この記事)
🍩2回目「EEPROMに楽譜を記録♬ "レコード盤作り"
🍩3回目「EEPROMから楽譜を読み取って演奏するプログラム
🍩4回目「トラブル1🐉 ArduinoのRAMが足りない..p_q..💦
🍩5回目「[トラブル2🦇 tone関数ではすべての音符を鳴らせない
🍩6回目「"ちびやっこ"意気消沈。お姉ちゃんの"みつは"は超オンチに🦆
🍩7回目「Tiny蓄音機レコード仕様、実装します。& 動画🎬
🍩8回目「Tiny蓄音機レコード仕様🎶 作り方まとめっ♬

~これから何回かに分けて書いていきます。書いたら目次も増やしていきます。~



🍊 初代Tiny蓄音機            🍋 光センサTiny蓄音機
f:id:miraluna:20180204164053j:plain:w290 f:id:miraluna:20210921195232p:plain:w290


🎀 プロジェクトの構想 🎀

上の写真は「初代Tiny蓄音機」と、開けると鳴りだす「光センサTiny蓄音機」。どちらも1つのマイコンを使って、そこに再生プログラムと曲を入れている。だから他の曲を再生するには、マイコンそのものを交換してたの。
今回作る「レコード仕様」のTiny蓄音機は、再生用のマイコンは蓄音機本体ということにして交換しない。曲を替えたいときにはレコード盤であるEEPROMを交換する、という仕様にするの。どう? 魅力的なアイディアでしょ🍩


もともとの構想🦄(現在失敗中 ↓ )
f:id:miraluna:20191113110718p:plain

初めの構想では、上の図のようにATtiny85(ちびやっこ)という小さなマイコンを蓄音機(再生機)にして、EEPROMをレコード盤にしたかった。どちらも8pinDIP(ピンが8本のちっちゃいIC)という形。でもやってみたら、ちびやっこ(ATtiny85)がレコードを再生してくれない..p_q..💦 プログラムの書き込みまではできてると思うんだけどなぁ。
そんなわけで問題を解決するまでの間はArduino UNOの本体(マイコン)であるATmega328(みつは)を再生機にしてTiny蓄音機を作っていきます。

f:id:miraluna:20191122170945j:plain:w300:right


 みっちゃん=みつは=ATmega328






🎀 EEPROMについて 🎀
EEPROMは情報を格納できるメモリ媒体。ここに曲のデータを入れておいて、みつはでそれを読むことができればいろいろな曲を鳴らすことができる♪ 実はみつはにもちびやっこにもEEPROMが内蔵されてるんだけど、みつはの容量は1kB(キロバイト)、ちびやっこは512B(バイト)。それほど長い曲を入れることはできないの。それに内蔵されているEEPROMじゃ、レコード盤のように交換できないでしょ。

f:id:miraluna:20190422193438j:plain:w300 EEPROMの「24LC64

レコード盤となるEEPROMの「24LC64」。1cm四方のメモリです。
"I²C"という接続方法で、蓄音機マイコン(みつは)と2本の線で通信します。
容量は64kbit(キロビット)=8kByte(キロバイト)。みつはに内蔵されているEEPROMの8倍の容量ね。

1バイトというのは1ビットが8つ集まったもの。8ビット=1バイトね。
1バイトは"0~255"までの256通りの数字を表現できる。この数字が音符のデータになるの。
[24LC64]にはデータ容量が8kB(キロバイト)ある
1kB=1024B だから、8192箇所(0~8191番地)にデータを収められるというわけ。
音符のデータには「音階」と「長さ」の情報が必要だから、0~8191番地まであるEEPROMなら約4000個の音符のデータを収められることになるわね。今回私が挑戦するのは715音符の長い曲。でも無問題👍

ちなみに[24LC64]の姉妹には
4倍の容量(32kB)をもつ[24FC256]や、8倍の容量(64kB)をもつ[24LC512]などいろいろな子がいます。
ちなみのちなみにお値段は(秋月電子通商さんで2021年9月現在)
[24LC64]が50円。 [24FC256]が90円。 [24LC512]なら160円です。安い。
[24LC64]と同じ容量の[24FC64]は、低電圧でも動作する低消費電力で、クロック数を1MHzにできる高速タイプだそうです。値段は同じ50円。yasui.



f:id:miraluna:20210302183413j:plain:w300:right


Mira & Luna's
nursery lab



🎀 紹介 🎀
「Tiny蓄音機レコード仕様」を作ろうと思ったのは、EEPROMによるレコード仕様が素敵だなと思ったのと、もう一つは長い曲を入れることができるから。それなら長い曲に挑戦しないわけにはいきません。
このたび私が挑戦する曲は、
加賀谷玲(かがやれい)さんのOneNightです。
イラストレーターのKAGAYAさんのプラネタリウム作品「銀河鉄道の夜」に使われた曲。私、プラネタリウムが好きだから時々連れていってもらうんだけど、「銀河鉄道の夜プラネタリウムで観てみたいなぁ。
こちらのKAGAYAさんの2作品は、5,6年前に連れていってもらったはずです。(内容まではもう覚えてないけど......。)
🌌全天周プラネタリウム番組【オーロラの調べ】
🌟全天周プラネタリウム番組【スターリーテイルズ~星座は時をこえて】
『OneNight』の作曲者 加賀谷玲さんは、KAGAYAさんの弟さん。「銀河鉄道の夜」は、お兄さんが映像、弟さんが音楽を作ったのね。
「Tiny蓄音機レコード仕様」を作るにあたって、『OneNight』の楽譜が載っているYoutube(加賀谷玲さんのチャンネル)「4.One night【銀河鉄道の夜Score Book】 - YouTube」を参考にさせていただきました。ありがとうございます。
私が作ったものは電子ブザーでしかも和音なしで作っているので、加賀谷玲さんのピアノのように美しい音色は出ないし音程やリズムがちょっとずれてるらしいけど、がんばって作りました(∂, ∂🎀y 大目に見てくださいね🐤。



それでは新しいプロジェクト 🍩Tiny蓄音機レコード仕様を作ろう🍩
の、はじまりはじまり~🎀

f:id:miraluna:20180105114819j:plain:w200 Mira



目次 🍩 Tiny蓄音機レコード仕様を作ろう 🍩

🍩1回目「 構想とEEPROMについてと曲紹介」(この記事)
次回🍩2回目「EEPROMに楽譜を記録♬ "レコード盤作り"
🍩3回目「EEPROMから楽譜を読み取って演奏するプログラム
🍩4回目「トラブル1🐉 ArduinoのRAMが足りない..p_q..💦
🍩5回目「[トラブル2🦇 tone関数ではすべての音符を鳴らせない
🍩6回目「"ちびやっこ"意気消沈。お姉ちゃんの"みつは"は超オンチに🦆
🍩7回目「Tiny蓄音機レコード仕様、実装します。& 動画🎬
🍩8回目「Tiny蓄音機レコード仕様🎶 作り方まとめっ♬