DSPラジオ(arduino+M6955)の完成を目指す。 | お父にゃんの電子工作

お父にゃんの電子工作

暇なおじさんが、電子工作(主にラジオ製作)をして勝手な感想を書く

前回は、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);
ということで、40倍から4倍に変えて計算する。
 
すると、思わぬ効果が有った。
いままで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)もこちらに置いておくので、興味のある方はどうぞ。
 
ああ、プログラミングが苦手なおじさんにとって、ここまでの道のりは遠かったのである。
 
 
 
「ふ~ん、にゃにか出来たのかにゃ?」