前回は、M6955+arduinoのDSPラジオを全バンド対応にした。
あと市販のラジオに有って、このラジオに無いものは、オートスキャン選局なのである。
今回はオートスキャン選局に対応して、完成(Ver1.0)としたい。
まず、オートスキャンの仕様を決める
- MODEボタンの長押しで開始
スキャン中に受信できた局の数も表示する。
例)「FM Scn14」 - スキャン対象は現在選択されているバンドのみとする。
FMの場合はFMのみスキャン、中波ならMWのみスキャン - スキャンの方法は、周波数を順次ラジオモジュールにセットして、レジスタ0x14の値を読み出し、bit5が1かどうかを確認する。
(レジスタ0x14のbit5が放送受信結果のフラグ) - スキャン終了後、EEPROMに格納し、次回電源投入時に読み出してメモリモードで使う。
- スキャンで格納する周波数は、各バンド最大30局までとする
この場合、周波数を今のfloat型で処理していると1データが4byteとなり
30×4×13=1560byte
EEPROMが1024byteしかないので保存領域が不足する。⇒int型に変更
int型なら780byteとなり、足りる。
FMの周波数計算時は10倍にしてint型にして表示の時だけfloatに戻して10で割って小数点付きにする。 - 30局に達した時点でスキャンは中止する。
- 電源投入時に各バンドのEEPROM領域を確認して何も格納されていない場合は、デフォルトの周波数1個のみメモリ領域としてRAM上に配置する。
- 従来のメモリモードは、お気に入りモード(My Favorites Mode)として残しておく。
う~ん、結構めんどくさいぞ。
こういう時は対話型AIにヒントを聞いてみよう。
まずはEEPROMへの配列の読み書きについてお願い。
----------------------------
お願い
arduinoでEEPROMに複数のint型の配列を書き込み/読み出しするサンプルプログラムを書いて
------------------
以下にArduinoでEEPROMに複数のint型の配列を書き込み/読み出しするサンプルプログラムを示します。
#include <EEPROM.h>
// EEPROMのアドレスオフセット
#define EEPROM_OFFSET 0
// 配列のサイズ
#define ARRAY_SIZE 5
// EEPROMに書き込むデータ
int dataToWrite[ARRAY_SIZE] = {10, 20, 30, 40, 50};
// EEPROMから読み出したデータを格納する配列
int dataToRead[ARRAY_SIZE];
void setup() {
Serial.begin(9600);
// EEPROMにデータを書き込む
writeDataToEEPROM();
// EEPROMからデータを読み出す
readDataFromEEPROM();
// 読み出したデータをシリアルモニタに出力する
printData();
}
void loop() {
// 何もしない
}
void writeDataToEEPROM() {
int address = EEPROM_OFFSET;
for (int i = 0; i < ARRAY_SIZE; i++) {
EEPROM.put(address, dataToWrite[i]);
address += sizeof(int);
}
EEPROM.commit(); // 書き込みを確定させる
}
void readDataFromEEPROM() {
int address = EEPROM_OFFSET;
for (int i = 0; i < ARRAY_SIZE; i++) {
EEPROM.get(address, dataToRead[i]);
address += sizeof(int);
}
}
void printData() {
for (int i = 0; i < ARRAY_SIZE; i++) {
Serial.print("Data ");
Serial.print(i);
Serial.print(": ");
Serial.println(dataToRead[i]);
}
}
このプログラムでは、EEPROM.h
ライブラリを使用してEEPROMにデータを書き込み、読み出しています。EEPROM_OFFSET
はEEPROMのアドレスオフセットを表し、ARRAY_SIZE
は配列の要素数を指定します。dataToWrite
に書き込むデータを設定し、dataToRead
に読み出したデータを格納します。
setup()
関数では、writeDataToEEPROM()
関数を呼び出してEEPROMにデータを書き込み、readDataFromEEPROM()
関数を呼び出してEEPROMからデータを読み出します。最後にprintData()
関数を呼び出して、読み出したデータをシリアルモニタに出力します。
プログラムを実行すると、シリアルモニタに以下のような出力が表示されます(例としてARRAY_SIZE
を5とした場合):
Data 0: 10
Data 1: 20
Data 2: 30
Data 3: 40
Data 4: 50
---------------------------------------------------う~ん、なるほど、なんとなくわかったような気がする。
あとは自力で、ちょっとづつ作ることにする。
これまで、いろいろ触ってきたおかげで、わずかながらにプログラミングスキルが上がったような気がするのである。
そして、だいぶ苦労したが、なんとなくソフトは出来たような気がする。
素人が適当に書き連ねたもので、いい加減なのだが、まぁ良しとする。
出来上がりの具合はこんな感じ
●オートスキャン選局
Modeボタンを長押しするとこんな感じで、オートスキャンが走る。
FMだと、おおよそ35秒くらいでスキャンが終了する。
スキャン終了後はメモリモードに移行し、最後に受信できた放送局が選局される。
オートスキャンはどのくらいの局が受信できるかが一発でわかるので、とても便利な感じがするのである。
●お気に入りモード
従来のメモリーモードはお気に入りモードに名前を変えて残した。
近くの放送局FM3局とAM3局をとりあえず入れてある。
普段はこれだけ聞ければよいのでデフォルトがお気に入りモードでも良いかもしれない。
さて、今回FMの周波数計算をfloat型から、小数点以下をやめてint型に変更した。
例えば、79.7MHzの場合、797として計算し、最後に10で割る。というか計算では
Set_num= (freq*40/10 - 1200);
すると、思わぬ効果が有った。
いままでFMで選局すると、ちゃんと合っていない感じがしていた。
例えば79.7MHzの放送局に合わせてもきれいに受信できなくて79.8MHzで受信できたりと、なんかいまいちだったのが、int型で計算すると、ぴったり選局できるようになった。
float型で計算すると整数に戻す時に変な誤差が出て、計算がぴったり合っていなかったのではないか?と思うのである。
おかげでFM受信の調子がよくなった。
あと、思い付きで、待機時はarduinoをSleepモードにして消費電流の低減を図ってみた。
操作ボタンも、ロータリーエンコーダーも割り込みになっているので、 最も消費電力が少ないパワーダウンモードに落としても、何か操作すれば何事も無く復帰できる。
サンプルプログラムを同じように対話型AIに書いてもらったおかげで、すぐに出来た。
まず、Sleepモードをサポートする<avr/sleep.h>をインクルード
#include <avr/sleep.h>
void setup()でパワーダウンモードを指定
//
// sleep mode
//
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //power down mode
sleep_enable(); //sleep enable
LCDのバックライトoffに合わせて寝る
if (LCD_backlight_count >= back_light_timer){
digitalWrite(back_light, LOW); // LCD back light off
//
sleep_mode(); // sleep
}
たった、4行追加しただけ。
効果のほどはどうかというと、なにも受信していない状態で47mA ⇒ 40mAと約7mAの削減となった。
使っているarduinoは3.3V 8MHzの物なのでもともと消費電流は多くないようだ。ラジオモジュールの消費電流が多いので、削減率は低いが、効果は有ったのでこのままにしておく。
ちなみにラジオモジュールをPower OFFモードに設定すると、電流値はほぼ0に近いところまで下げられることは確認した。しかもI2Cは生きていてI2CからPower ONモードに設定すれば、ちょっとタイムラグがある(起動に時間がかかる)が、何事も無く動き出す。
気が向いたらこれでひと工夫するかも・・・
さて、これまでだいぶ時間はかかったが、だいたいやれることは全てやった気がする。
これでVer1.0の完成としたい。
参考までに、Ver1.0のコードはこちらに置いておく。
回路図(PDF)もこちらに置いておくので、興味のある方はどうぞ。
ああ、プログラミングが苦手なおじさんにとって、ここまでの道のりは遠かったのである。
「ふ~ん、にゃにか出来たのかにゃ?」