差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン 次のリビジョン両方とも次のリビジョン | ||
arduino:grovebeginnerkit [2021/07/14 10:08] – baba | arduino:grovebeginnerkit [2023/05/30 11:48] – [8. Temperature & Humidity Sensor] baba | ||
---|---|---|---|
行 23: | 行 23: | ||
国内だとスイッチサイエンスのgroveカテゴリで探すとよいでしょう. | 国内だとスイッチサイエンスのgroveカテゴリで探すとよいでしょう. | ||
* https:// | * https:// | ||
+ | |||
+ | ===== 入門 ===== | ||
+ | 以下は,grove beginner kit を利用するための超シンプルな導入を記載します.授業ではこちらのページを忘備録としています. | ||
+ | {{: | ||
+ | |||
+ | ==== 1. LED ==== | ||
+ | < | ||
+ | void setup() { | ||
+ | pinMode(4, OUTPUT); // 4番ピンを出力モードに | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | digitalWrite(4, | ||
+ | delay(1000); | ||
+ | digitalWrite(4, | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | ==== 2. Buzzer ==== | ||
+ | 圧電素子の構造:https:// | ||
+ | < | ||
+ | // 何ヘルツの音がなっていますか? | ||
+ | void setup() | ||
+ | { | ||
+ | pinMode(5, OUTPUT); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | digitalWrite(5, | ||
+ | delay(10); | ||
+ | digitalWrite(5, | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | // ド(523Hz),ソ(783Hz)を鳴らすサンプル | ||
+ | void setup() | ||
+ | { | ||
+ | pinMode(5, OUTPUT); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | tone(5, 523, 100); | ||
+ | delay(1000); | ||
+ | tone(5, 783, 100); | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | delay()のパラメータを変更することで任意の周波数の波形を出力することができました。ただし、決められた周波数を鳴らすために上記のようなコードを使っていると、たくさんの音を鳴らす場合少し面倒になります。そのため、Arduinoにはtone()関数が用意されています。 | ||
+ | * https:// | ||
+ | |||
+ | tone(pin, frequency) | ||
+ | tone(pin, frequency, duration) | ||
+ | | ||
+ | 1つ目の引数にはスピーカーにつながっている制御ピン番号を。2つ目の引数には鳴らしたい周波数を指定します。もし鳴らす音の長さ(音長)を指定したい場合、3番目の引数にmilli second単位で値を指定します。例えば次のようなコードで二種類の異なる周波数を順番に鳴らすことが簡単にできます。 | ||
+ | <WRAP center round help 60%> | ||
+ | これは有名なドラマで使われていた効果音になります.なんだか分かる人はどのくらいいるでしょうか? | ||
+ | </ | ||
+ | |||
+ | <code .c countdown.pde> | ||
+ | void setup() | ||
+ | { | ||
+ | pinMode(5, OUTPUT); | ||
+ | } | ||
+ | void loop() { | ||
+ | tone(5, 2217, 70); | ||
+ | delay(1000); | ||
+ | tone(5, 1991, 70); | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <code .c ring.pde> | ||
+ | // Reference: http:// | ||
+ | void setup() | ||
+ | { | ||
+ | pinMode(5, OUTPUT); | ||
+ | } | ||
+ | void loop(void) | ||
+ | { | ||
+ | tone(5, | ||
+ | delay(50); | ||
+ | |||
+ | tone(5, | ||
+ | delay(168); | ||
+ | |||
+ | tone(5, | ||
+ | delay(48); | ||
+ | |||
+ | tone(5, | ||
+ | delay(360); | ||
+ | |||
+ | |||
+ | tone(5, | ||
+ | delay(50); | ||
+ | |||
+ | tone(5, | ||
+ | delay(50); | ||
+ | |||
+ | tone(5, | ||
+ | delay(50); | ||
+ | |||
+ | tone(5, | ||
+ | delay(50); | ||
+ | |||
+ | |||
+ | tone(5, | ||
+ | delay(55); | ||
+ | |||
+ | tone(5, | ||
+ | delay(55); | ||
+ | |||
+ | tone(5, | ||
+ | delay(55); | ||
+ | |||
+ | tone(6, | ||
+ | delay(55); | ||
+ | |||
+ | tone(5, | ||
+ | delay(55); | ||
+ | |||
+ | tone(5, | ||
+ | delay(55); | ||
+ | |||
+ | tone(5, | ||
+ | delay(55); | ||
+ | |||
+ | tone(5, | ||
+ | delay(55); | ||
+ | |||
+ | delay(1500); | ||
+ | } | ||
+ | </ | ||
+ | ==== 音階で音を鳴らしてみる ==== | ||
+ | ON/ | ||
+ | |||
+ | まず最初の周波数と音高の関係ですが、ピアノの真ん中辺りの「ド」の音を鳴らし、一オクターブ上の「ド」を鳴らした場合を考えます。 | ||
+ | 最初に鳴らしたドの周波数を $f_1$とした場合、一オクターブ上のドは $f_2 = 2f_1$として表されます。つまり一オクターブ上の音は下の音の倍の周波数になっているわけです。このような関係をより数学的に表現したものが、十二平均律になります。オクターブ間に12の音程を均等に配置するものです。 | ||
+ | |||
+ | ベースやギターの開放弦を利用した調律では440Hzを利用しますが、この音を基準(ピアノのラ)として、次の式で表すことで、440Hzのオクターブ上(12音上)は $ 440 \times 2^{\frac{12}{12}} = 880 $となります。 | ||
+ | |||
+ | \[ | ||
+ | f = 440 \times 2^{(n/12)} | ||
+ | \] | ||
+ | |||
+ | ただし基準となる440Hzのラはノート番号では69番としているので、nが69のときに440Hzになるように式を下記のようにしておきます。 | ||
+ | \[ | ||
+ | f = 440 \times 2^{\frac{n-69}{12}} | ||
+ | \] | ||
+ | |||
+ | ではここまでの準備を利用して、有名なNokia Tuneを鳴らしてみましょう。下記サイトを参考にします。 | ||
+ | * https:// | ||
+ | |||
+ | <code .c nokiatune.pde> | ||
+ | float getFreq(int n) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | void setup() | ||
+ | { | ||
+ | pinMode(6, OUTPUT); | ||
+ | } | ||
+ | int interval = 250; | ||
+ | void loop() { | ||
+ | tone(6, getFreq(76), | ||
+ | delay(interval/ | ||
+ | tone(6, getFreq(74), | ||
+ | delay(interval/ | ||
+ | tone(6, getFreq(66), | ||
+ | delay(interval); | ||
+ | tone(6, getFreq(68), | ||
+ | delay(interval); | ||
+ | tone(6, | ||
+ | delay(interval/ | ||
+ | tone(6, getFreq(71), | ||
+ | delay(interval/ | ||
+ | tone(6, getFreq(62), | ||
+ | delay(interval); | ||
+ | tone(6, getFreq(64), | ||
+ | delay(interval); | ||
+ | tone(6, getFreq(71), | ||
+ | delay(interval/ | ||
+ | tone(6, getFreq(69), | ||
+ | delay(interval/ | ||
+ | tone(6, getFreq(61), | ||
+ | delay(interval); | ||
+ | tone(6, getFreq(64), | ||
+ | delay(interval); | ||
+ | tone(6, getFreq(69), | ||
+ | delay(interval*4); | ||
+ | delay(interval*4); | ||
+ | } | ||
+ | </ | ||
+ | ==== 余談 ==== | ||
+ | 鳴らしたいノート番号を指定することでその周波数を計算することができますが、その逆である「鳴らしたい周波数が決まっている場合、それはピアノの鍵盤でいうところのどの位置になるのか?」を計算するには、方程式をnについてとけば良いです。 | ||
+ | |||
+ | 上記式を両辺に自然対数とることで簡単にnについて解くことができます。みなさんも実際に計算して確かめてみましょう。 | ||
+ | \[ | ||
+ | n = \frac{12 \times log_e(\frac{f}{440})}{log_e(2)} + 69 | ||
+ | \] | ||
+ | |||
+ | ==== 3. OLED Display 0.96 ==== | ||
+ | Arduino Library Managerから U8g2 をインストールしてから,以下のコードを実行 | ||
+ | < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #ifdef U8X8_HAVE_HW_SPI | ||
+ | #include < | ||
+ | #endif | ||
+ | #ifdef U8X8_HAVE_HW_I2C | ||
+ | #include < | ||
+ | #endif | ||
+ | |||
+ | |||
+ | U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, | ||
+ | |||
+ | // U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, | ||
+ | |||
+ | void setup(void) { | ||
+ | u8g2.begin(); | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | u8g2.clearBuffer(); | ||
+ | u8g2.setFont(u8g2_font_ncenB08_tr); | ||
+ | u8g2.drawStr(0, | ||
+ | u8g2.sendBuffer(); | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | ==== 4. Button ==== | ||
+ | 一般にスイッチにはいくつかの種類がありますが,まずは具体的に見てみます. もっとも安価なものに,タクタイルスイッチという部品があります.これは一般的にモーメンタリスイッチ と呼ばれるもので,押している間だけ内部の回路が通電する,というものです.下の回路図で試してみます. 一般的にタクタイルスイッチには電極が4つあります.内部的には単純に通電するかしないかなので,実際には 2本あれば十分です.これはタクタイルスイッチが様々な電子部品で利用される際,マトリクススキャン等の スイッチセンシングにおいて,電極がそれぞれ2つづつあると基盤的に都合が良いことが多いからです. | ||
+ | |||
+ | {{: | ||
+ | |||
+ | < | ||
+ | void setup() | ||
+ | { | ||
+ | pinMode(4, OUTPUT); | ||
+ | pinMode(6, INPUT); | ||
+ | } | ||
+ | void loop() { | ||
+ | int d = digitalRead(6); | ||
+ | if( d == HIGH){ | ||
+ | digitalWrite(4, | ||
+ | } | ||
+ | else{ | ||
+ | digitalWrite(4, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | ==== 5. Rotary Potentiometer ==== | ||
+ | ロータリーポテンショメーターとは回転式可変抵抗器のことを指します.つまみを回すと内部の接触点が代わり抵抗値が変化する部品です.A0ピンに接続されているので,この値を読み出してみます.ここではシリアルモニタ,シリアルプロッタの使い方も学習します. | ||
+ | < | ||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | void loop() { | ||
+ | int a = analogRead(0); | ||
+ | Serial.println(a); | ||
+ | delay(33); | ||
+ | } | ||
+ | </ | ||
+ | ==== 6. Light ==== | ||
+ | < | ||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | void loop() { | ||
+ | int a = analogRead(6); | ||
+ | Serial.println(a); | ||
+ | delay(33); | ||
+ | } | ||
+ | </ | ||
+ | ==== 7. Sound ==== | ||
+ | < | ||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | void loop() { | ||
+ | int a = analogRead(2); | ||
+ | Serial.println(a); | ||
+ | delay(33); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === FFT === | ||
+ | < | ||
+ | #include < | ||
+ | |||
+ | #define SAMPLES 64 // サンプル数(2の累乗数) | ||
+ | #define SAMPLING_FREQUENCY 1000 // サンプリング周波数 | ||
+ | |||
+ | |||
+ | unsigned int sampling_period_us; | ||
+ | unsigned long microseconds; | ||
+ | |||
+ | double vReal[SAMPLES]; | ||
+ | double vImag[SAMPLES]; | ||
+ | |||
+ | arduinoFFT FFT = arduinoFFT(); | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | sampling_period_us = round(1000000*(1.0/ | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | /* サンプリング */ | ||
+ | for(int i=0; i< | ||
+ | microseconds = micros(); | ||
+ | vReal[i] = analogRead(2); | ||
+ | vImag[i] = 0; | ||
+ | // 次のサンプリング時間まで待つ | ||
+ | while(micros() - microseconds < sampling_period_us){ | ||
+ | // wait | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* FFT */ | ||
+ | FFT.Windowing(vReal, | ||
+ | FFT.Compute(vReal, | ||
+ | FFT.ComplexToMagnitude(vReal, | ||
+ | | ||
+ | double peak = FFT.MajorPeak(vReal, | ||
+ | |||
+ | /* 結果を出力 */ | ||
+ | Serial.println(peak); | ||
+ | |||
+ | // delay(1000); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== 8. Temperature & Humidity Sensor ==== | ||
+ | Grove Temperature And Humidity Sensor | ||
+ | < | ||
+ | // | ||
+ | #include " | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #define DHTPIN 3 // what pin we're connected to | ||
+ | #define DHTTYPE DHT11 // DHT 11 | ||
+ | DHT dht(DHTPIN, DHTTYPE); | ||
+ | |||
+ | U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE); | ||
+ | |||
+ | void setup(void) { | ||
+ | Serial.begin(9600); | ||
+ | Serial.println(" | ||
+ | dht.begin(); | ||
+ | u8x8.begin(); | ||
+ | u8x8.setPowerSave(0); | ||
+ | u8x8.setFlipMode(1); | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | |||
+ | float temp, humi; | ||
+ | temp = dht.readTemperature(); | ||
+ | humi = dht.readHumidity(); | ||
+ | | ||
+ | u8x8.setFont(u8x8_font_chroma48medium8_r); | ||
+ | u8x8.setCursor(0, | ||
+ | u8x8.print(" | ||
+ | u8x8.print(temp); | ||
+ | u8x8.print(" | ||
+ | u8x8.setCursor(0, | ||
+ | u8x8.print(" | ||
+ | u8x8.print(humi); | ||
+ | u8x8.print(" | ||
+ | u8x8.refreshDisplay(); | ||
+ | delay(200); | ||
+ | } | ||
+ | </ | ||
+ | ==== 9. Air Pressure Sensor ==== | ||
+ | Barometer Sensor BMP280 を追加する | ||
+ | < | ||
+ | //Air pressure detection | ||
+ | #include " | ||
+ | #include < | ||
+ | |||
+ | BMP280 bmp280; | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | if (!bmp280.init()) { | ||
+ | Serial.println(" | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | |||
+ | float pressure; | ||
+ | |||
+ | //get and print temperatures | ||
+ | Serial.print(" | ||
+ | Serial.print(bmp280.getTemperature()); | ||
+ | Serial.println(" | ||
+ | |||
+ | //get and print atmospheric pressure data | ||
+ | Serial.print(" | ||
+ | Serial.print(pressure = bmp280.getPressure()); | ||
+ | Serial.println(" | ||
+ | |||
+ | //get and print altitude data | ||
+ | Serial.print(" | ||
+ | Serial.print(bmp280.calcAltitude(pressure)); | ||
+ | Serial.println(" | ||
+ | |||
+ | Serial.println(" | ||
+ | |||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | ==== 10. 3-Axis Accelerator ==== | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||