macsbug

Just another WordPress.com site

Part 2 of the FM radio in the ESP8266

with 2 comments

FM Radio TEA5767 を 「 mroger / TEA5767 」 ライブラリーで作りました 。  2016.04.06

「 mroger / TEA5767 」 ライブラリーは多数の機能があります。

上 :FM局名と周波数に 信号レベルを追加し 視聴中は 3D Cube が回転しています。
左下:信号レベルをアナログバーで表示。
右下:76~108MHz までの信号の強さをスペクトルで表示。


準備:
1. ライブラリー:mroger / TEA5767 Library をダウンロードする。Marcos氏に感謝。
2. ライブラリー変更: TEA5767N.cpp の  Wire.begin(); を使用不可(// のコメント)にします。
_  対応:スケッチ側で Wire.begin(4,5); を宣言し SDA,SCL 端子の割り振りをしました。

#include <Arduino.h>
#include <Wire.h>
#include <TEA5767N.h>

TEA5767N::TEA5767N() {
  //Wire.begin();                // 2016.04.06  macsbug
  initializeTransmissionData();
  muted = false;
}

3. スケッチを動かしてみる。「 FM局名 + 信号レベル + 周波数 + 3D Cube 」を表示します。


メモ:
前回ライブラリは 周波数のみの操作しかできませんでした。
mroger / TEA5767 ライブラリーは幾つかの機能があります。
サーチ:setSearchUp、setSearchDown、setSearchLowStopLevel、
_   setSearchMidStopLevel、setSearchHighStopLevel、searchNext、
_   searchNextMuting、startsSearchFrom、startsSearchFromBeginning、
_   startsSearchFromEnd、startsSearchMutingFromBeginning、
_   startsSearchMutingFromEnd、isSearchUp、isSearchDown
ミュート:mute、muteLeft、muteRight、setSoftMuteOn、setSoftMuteOff、isMuted
サウンド・オン・オフ:setStandByOn、setStandByOff、turnTheSoundBackOn、
_          turnTheLeftSoundBackOn、turnTheRightSoundBackOn
ステレオ・モノラル切り替え:setStereoReception、setMonoReception、isStereo();
フィルター:setHighCutControlOn、setHighCutControlOff、
_     setStereoNoiseCancellingOn、setStereoNoiseCancellingOff
周波数設定:selectFrequencyMuting
周波数読み取り:readFrequencyInMHz
信号レベル:getSignalLevel
その他:setStereoReception、setMonoReception

ミュート、ステレオ、モノラル、フィルター等の機能が用意されていて素晴らしい。
幾つか使用してみましたが今回使用する範囲では 使う場面はありませんでした。
最初からミュートはしない、ステレオのままとかシンプルにすると使用しない訳です。
サーチ機能はプログラムの工夫も含めて自動サーチ(自動選局)ができますが、増加か減少
時の判断に時間を要します。結果、かなりの工夫が必要となります。
使える物としては「信号レベル」と「周波数」が役に立ちます。


感想:
ライブラリーの不具合: Wire.begin(); にてSDA,SCLが設定されていない為です。
_ スケッチ側から値を渡す方法もありますが 今回はスケッチ側で宣言しました。
無線チップ:I2C接続は簡単である事とプログラムで操作できる事が素晴らしい。
_ チップから取得できる信号として周波数と信号レベルがあるのは便利です。
_ オーデーオ信号もあればスペクトラムも出来そうなのですが、無いので残念です。
_ 76〜108MHzまでの受信レベルのスペクトラムを128×64の小さな画面にグラフにして
_ みましたが、チップからの安定した値を取る為には時間を使用します。
TEA5767 FM Stereo Radio:IC単独よりもTDA1308アンプが内蔵されたもので楽でした。


スケッチ:

// FM Radio I2C TEA5767 and 3D Cube : 2016.04.06 macsbug //
// https://github.com/squix78/esp8266-oled-ssd1306       // OLED Driver
// Add drawLine to SSD1306.h and SSD1306.cpp : macsbug   // Modification
// https://github.com/mroger/TEA5767                     // FM Radio
#include <Wire.h>                                        // with mod SSD1306.cpp
#include <TEA5767N.h>                                    // FM Radio
#include "SSD1306.h"                                     // with mod SSD1306.h
#include "SSD1306Ui.h"                                   // OLED
extern "C" {
  #include "user_interface.h" 
}
SSD1306 display(0x3c,4,5);                               // OLED Initialize
TEA5767N radio = TEA5767N();                             // radio
float r, x1, z1, y2;                                     // Cube
int f[8][2];                                             // Draw box
int c[8][3];                                             // Cube
float m[]={80.0,81.3,82.5,88.3,89.7,90.5,91.6,93.0,77.3};// FM Frequency
String n[] = {"TOKYO FM","JWave","NHK FM","Ropopngi",    // FM Name
  "Inter FM","TBS","BUNKA","NIPPON","LOVEARTH"};         // FM Name
int fr = 0;                                              // Frequency
int ck = 0;                                              // chattering ck
byte g;                                                  // FM Sig Level

void setup() {                                           //
  pinMode (12, INPUT_PULLUP );                           // switch sens RL
  pinMode (13, INPUT_PULLUP );                           // switch sens FB
  Wire.begin(4,5);                                       // SDA=GPIO04,SCL=5
  display.init();                                        // OLED
  display.setFont(ArialMT_Plain_24);                     // Font
  display.setTextAlignment(TEXT_ALIGN_LEFT);             // Font direction
  display.displayOn();                                   //
  display.clear();                                       //
  display.drawString(  0, 0, "ESP8266" );                // Title
  display.drawString(  0,30, "FM RADIO");                // Title
  display.display();                                     //
  delay(3000);                                           //
  display.clear();                                       //
  display.drawString(  0, 0, n[fr] );                    // Freq name
  display.drawString(  0,28, String(m[fr],1) );          // Frequency
  display.drawString( 54,28, "MHz" );                    // Frequency
  display.display();                                     //
  radio.selectFrequency( m[fr] );                        // Freq set
  delay(3000);                                           //
  g = radio.getSignalLevel();                            // FM Sig Level
}                                                        //

void loop() {                                            //
  for ( int q = 10; q < 20; q = q + 2 ){ cube(q); }      // Expansion
  for ( int q = 20; q > 10; q = q - 2 ){ cube(q); }      // Reduction
}                                                        //

void cube(int q){                                        // Fast display
  int c[8][3] = {                                        // Cube
    {-q,-q, q},{q,-q, q},{q,q, q},{-q,q, q},             //
    {-q,-q,-q},{q,-q,-q},{q,q,-q},{-q,q,-q} };           //
  for (int a = 0; a <= 360; a = a + 3 ) {                // 0 to 360 degree
   if ( digitalRead(12) == LOW){ freq(12,+1);}           // Ball SW:+freq:RL
   if ( digitalRead(13) == LOW){ freq(13,-1);}           // Ball SW:-freq:FB
   for (int i = 0; i < 8; i++) {                         // Calculation
    r       = a * 0.0174532;                             // 1 degree
    x1      = c[i][2] * sin(r) + c[i][0] * cos(r);       // rotate X
    z1      = c[i][2] * cos(r) - c[i][0] * sin(r);       // rotate Z
    y2      = c[i][1] * cos(r) - z1      * sin(r);       // rotate Y
    f[i][0] = x1      * cos(r) - y2      * sin(r) + 64;  // X + Center
    f[i][1] = x1      * sin(r) + y2      * cos(r) + 32;  // Y + Center
    f[i][2] = c[i][1] * sin(r) + z1      * cos(r);       // Z
   }                                                     //
  display.clear();                                       //
  display.setFont(ArialMT_Plain_16);                     // Font
  display.setTextAlignment(TEXT_ALIGN_LEFT);             // Font direction
  display.drawString(  0, 0,n[fr]);                      // Freq Name
  display.drawString( 60,48,String(m[fr],1));            // Frequency
  display.setTextAlignment(TEXT_ALIGN_RIGHT);            // Font direction
  display.drawString(127, 0,String(g));                  // FM Sig level
  display.drawString(127,48,"MHz");                      // Frequency
  display.drawLine(f[0][0],f[0][1],f[1][0],f[1][1]);     // Cube
  display.drawLine(f[1][0],f[1][1],f[2][0],f[2][1]);     //
  display.drawLine(f[2][0],f[2][1],f[3][0],f[3][1]);     //
  display.drawLine(f[3][0],f[3][1],f[0][0],f[0][1]);     //
  display.drawLine(f[4][0],f[4][1],f[5][0],f[5][1]);     //
  display.drawLine(f[5][0],f[5][1],f[6][0],f[6][1]);     //
  display.drawLine(f[6][0],f[6][1],f[7][0],f[7][1]);     //
  display.drawLine(f[7][0],f[7][1],f[4][0],f[4][1]);     //
  display.drawLine(f[0][0],f[0][1],f[4][0],f[4][1]);     //
  display.drawLine(f[1][0],f[1][1],f[5][0],f[5][1]);     //
  display.drawLine(f[2][0],f[2][1],f[6][0],f[6][1]);     //
  display.drawLine(f[3][0],f[3][1],f[7][0],f[7][1]);     //
  display.drawLine(f[1][0],f[1][1],f[3][0],f[3][1]);     // cross
  display.drawLine(f[0][0],f[0][1],f[2][0],f[2][1]);     // cross
  display.display();                                     //
  delay(1);                                              // Hang-up prevention
  }                                                      //
}                                                        //

void freq(int gpio, int dir){                            //
  for ( int i = 0; i < 60; i++){ delay(10);              // chattering ck
    if ( digitalRead(gpio) == HIGH ){ ck = 1;}           // RL/FB
  }                                                      // 60 x 10 msec
  if ( ck == 0 ){                                        // Frequency Change
    fr = fr + dir; if ( fr > 8 || fr < 0 ){ fr = 0;}     // position
    display.clear();                                     // OLED
    display.setFont(ArialMT_Plain_24);                   // Font
    display.setTextAlignment(TEXT_ALIGN_LEFT);           // Font direction
    display.drawString(  0, 0, n[fr]);                   // Name
    display.drawString(  0,28, String(m[fr],1));         // Frequency
    display.drawString( 54,28, "MHz" );                  // Frequency
    display.display();                                   //
    radio.selectFrequency( m[fr] );                      // Frequency set
    delay(1000);                                         //
    g = radio.getSignalLevel();                          // FM Sig Level
  }                                                      //
  ck = 0;                                                //
}                                                        //
 

Written by macsbug

4月 6, 2016 @ 6:01 am

カテゴリー: ESP8266

コメント / トラックバック2件

Subscribe to comments with RSS.

  1. 詳細にわたる解説と何よりもそのエキサイティングな内容で次回のアップが待ち遠しく思っています。とても勉強になります。ありがとうございます。

    野比須

    4月 7, 2016 at 2:33 am

    • 野比須さん、ブログを見に来ていただきありがとうございます。
      まとめていると基礎が無い事に気づいたり解らない事も多い中で進めています。
      投稿後の修正もありますが今後もよろしくお願いします。

      macsbug

      4月 7, 2016 at 5:37 am


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。