macsbug

Just another WordPress.com site

Archive for 12月 2017

Audio Spectrum Display with M5STACK

with one comment

M5STACK で Audio Spectrum Display を作りました。            2017.12.31

音をディスプレー にスペクトラム表示します。
音を「Sound Detection Sensor 」( FC-04 ) ( 322円 ) で受けて、その信号を
M5STACK の GPIO36 に入力し スペクトラム を ディスプレー に 表示します。

スケッチ:
_ tobozo氏の「ESP32_Spectrum_Display_03.ino」を M5STACK に移植しました。
_ tobozo氏のソースは G6EJD氏の「ESP32_Spectrum_Display_02.ino」です。
_ 謝辞:G6EJD氏 と tobozo氏に感謝致します。

_ tobozo氏の使用した ディスプレーは 128×64 OLED SSD1306 です。
_ M5STACKのディスプレーは 320×240 TFT ILI9341 です。


.
準備:

No  Nomen  Link、Description   Price
1  M5STACK BASIC  Aliexpress:M5Stack Store ( $33.25 ) ( SALE )  3767円
2  Sound Detection Sensor  
2  ebay:shieldsfans ( AU $1.00)   88円
2  ebay:alice1101983 ( US $0.99)  112円
2  Ali:3C Top-rated Seller (US $0.79)  112円
4  ピンソケット(メス)
1×8 ( 8P )
 秋月電子通商    30円
5  切れる基板
0.3mm厚 両面スルーホール
ユニバーサル基板
 秋月電子通商    60円
 —————————–  ————————————————-   ——
6  G6EJD/
_ Audio-Spectrum-Display
  ESP32_Spectrum_Display_03.ino
7  kosme/arduinoFFT   arduinoFFT

.


.
配線:
GPIO36 は入力専用で SENSOR_VP と言う名前です。
参考:ESP32 Hardware Design Guidelines:Page 27 4.1.2 Pin Definition

_ VCC(FC-04) = 3V3(M5), GND = GND, OUT = AD(GPIO36)へ接続します。
_ FC-04 の電源は 3.3V で使用します。
_ FC-04 の出力は ESP32 のGPIO36 ( SENSOR_VP ) へ入ります。

秋月のハサミで切れる基板と ピンソケットで製作しました。

FC-04の調整:
_ FC-04 のボリュームの調整は 電源を入れ 緑のLEDが点滅する
_ 場所に設定します。スペクトラム表示を見ながらも調整してください。


.
マイクとアンプ:
マイクのアナログ信号は 最適な値である事が 重要です。
_ 以下5つを試し使用できる製品は 左の「FC-04」という製品でした。
_ 販売:右は 秋月電子通商の製品です。他は ebay や Aliexpress です。
_ FC-04 以外は ゲインレベルが正しく取れず 表示範囲が狭いです。
_ 原因は ゲインが取り難い事や飽和しやすく動作範囲が狭い為です。
FC-04:OUT はアナログでは無くデジタルです。何故 デジタルが 動作に
_ 適しているか 分析していません。

_ tobozo氏は 以下の様に述べています。
_「正しい結果が得る方法は、約50mV〜100mV pk-pkのオーディオを
_ DCオフセットなしでADCポートに直接供給することです。」

マイクアンプについての 記事は macsbug:「 FC-04 回路メモ 」にあります。


.
スケッチ変更内容:
_ 1. 「tft.drawFastHLine」を「M5.Lcd.drawFastHLine」に変更します。
_ 2. 「tft.fillRect」 を「M5.Lcd.fillRect」に変更します。
_ 資料:M5STACK の命令は 「M5Stack.h」に定義されています。


.
M5STACK analogRead 時の Speaker nois 問題と解決方法。
問題:analogRead() 時に Speaker (GPIO25) からノイズがでます。
_  例:vReal[i] = analogRead(A0);
方法:dacWrite(25, 0); // Speaker OFF //
解説:
_ GPIO25 (Channel 1) と GPIO26 (Channel 2) は two 8-bit DAC
_ (digital to analog converter) channels です。( 16bit )。
_ GPIO25 の 出力 (サウンド) は NS4148 AUDIO AMPLIFER に入り
_ AUDIO OUTPUT は SPEAKER に接続さています。
_ 資料:M5STACKの回路図
_ 資料:ESP32 Datasheet:Page 8, 2.2 Pin Description:GPIO25=DAC_1
_ GPIO25 は DAC端子ですので dacWrite(25, 0); で出力を制御します。
_ 信号解析:GPIO25 は 無音で 3mVac、analogRead(A0),で 10mVac 発生し
_ スピーカーからプツプツ音がでます。電源は問題なく GPIO25 からの出力
_ が原因の様です。


.
参考:
Github:G6EJD/ESP32-8266-Audio-Spectrum-Display
Github:tobozo/ESP32-8-Octave-Audio-Spectrum-Display
YouTube:G6EJD:Tech Note 077 – ESP32 8-Octave Audio Spectrum Display
YouTube:tobozo tagada:ESP32 Audio Spectrum from saturation to silence
YouTube:tobozo tagada:ESP32 Audio Spectrum on WROVER Kit V3
YouTube:Tech Note 069 – Using the ESP32 ADC and some of its more advanced functions
_ ADCの使用方法、線形性の説明、減衰設定の説明、ADCチャンネルで
_ 使用されるピンの変更方法を示し、多項式を使用して精度を1%未満に
_ 改善する関数を示します。
G6EJD / ESP32-ADC-Accuracy-Improvement-function

macsbug:SplitRadixRealP FFT Analyzer of Arduino DUE
_ Arduino Due + SplitRadixRealP の例。


.
ESP32 MH-ET LIVE D1 mini + OLED 128×64 で Audio Spectrum Display を製作しました。
_ QI で ワイヤレス電源にしてみました。
_ macsbug:Arduinoの電源をワイヤレス化
価格:ESP32 MH-ET LIVE D1 mini: $7.2 ( 811円 )
価格:OLED 128×64:$2.91 ( 328円 )


.
感想:
1.  ESP32 による「ESP32 Spectrum Display」
_ 基本は G6EJD氏により「ESP32_Spectrum_Display_01.ino」と
_  ESP32_Spectrum_Display_02.ino」が作成されました。そして
_ tobozo氏により「ESP32_Spectrum_Display_03.ino」が作成されました。
_ 基本と高速化に G6EJD氏 と tobozo氏 に感謝致します。

2. マイクとアンプ:
_ 音のサンプリングはゲインと帯域がないと 充分に機能しません。
_ 動作範囲の広いボードを使用するべきですが 最善のボードが見つかりません。
_ 課題: AGC機能のあるアンプを使用する必要があると思います。
_ 現在 他のボードを注文 及び 調査中です。

3. M5STACK の ケース。
_ M5STACK はケースが綺麗で素晴らしいです。
_ PROT Module は ありますが REAR CASE がありません。
_ M5STACK の強みは綺麗さです。綺麗に仕上げる為に 本体周辺の部品や
_ ケースを販売して欲しいです。止めネジや やや斜めに於ける台も欲しいです。
_ Jimmy Lai さん に期待しています。

4. FC-04の電源:
_ VCC = 5V での検証はしていません。

5. メモ:高速抽画。
_ 全画面消去の「M5.Lcd.fillScreen」を使用するとチラつきが発生します。
_ 対策は「M5.Lcd.fillScreen」を使用せず 同じ抽画を2度操作します。
_ 横線の高速抽画:
_  1. 前回の線を「drawFastHLine」+ 黒で抽画する。
_  2. 今回の値を前回に保存。
_  3. 今回の線を「drawFastHLine」で 抽画する。
_ 横線複数の高速抽画:
_  1. 前回の線全てを「fillRect」+ 黒で塗りつぶす。
_  2. 今回の値を前回に保存。
_  3. 今回の線を「drawFastHLine」で 抽画する。


.
スケッチ:

/* ESP8266/32 Audio Spectrum Analyser on an SSD1306/SH1106 Display
 * The MIT License (MIT) Copyright (c) 2017 by David Bird. 
 * The formulation and display of an AUdio Spectrum using an ESp8266 or ESP32 and SSD1306 or SH1106 OLED Display using a Fast Fourier Transform
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files 
 * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, 
 * publish, distribute, but not to use it commercially for profit making or to sub-license and/or to sell copies of the Software or to 
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:  
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 * See more at http://dsbird.org.uk 
*/
// https://github.com/tobozo/ESP32-8-Octave-Audio-Spectrum-Display/tree/wrover-kit
// https://github.com/G6EJD/ESP32-8266-Audio-Spectrum-Display
// https://github.com/kosme/arduinoFFT


#include "arduinoFFT.h"          // Standard Arduino FFT library 
arduinoFFT FFT = arduinoFFT();
#include <M5Stack.h>
#define SAMPLES 512              // Must be a power of 2
#define SAMPLING_FREQUENCY 40000 
// Hz, must be 40000 or less due to ADC conversion time.
// Determines maximum frequency that can be analysed by the FFT Fmax=sampleF/2.

struct eqBand {
  const char *freqname;
  uint16_t amplitude;
  int peak;
  int lastpeak;
  uint16_t lastval;
  unsigned long lastmeasured;
};

eqBand audiospectrum[8] = {
  //Adjust the amplitude values to fit your microphone
  { "125Hz", 500, 0, 0, 0, 0},
  { "250Hz", 200, 0, 0, 0, 0},
  { "500Hz", 200, 0, 0, 0, 0},
  { "1KHz",  200, 0, 0, 0, 0},
  { "2KHz",  200, 0, 0, 0, 0},
  { "4KHz",  100, 0, 0, 0, 0},
  { "8KHz",  100, 0, 0, 0, 0},
  { "16KHz", 50,  0, 0, 0, 0}
};

unsigned int sampling_period_us;
unsigned long microseconds;
double vReal[SAMPLES];
double vImag[SAMPLES];
unsigned long newTime, oldTime;
uint16_t tft_width  = 320; // ILI9341_TFTWIDTH;
uint16_t tft_height = 240; // ILI9341_TFTHEIGHT;
uint8_t bands = 8;
uint8_t bands_width = floor( tft_width / bands );
uint8_t bands_pad = bands_width - 10;
uint16_t colormap[255]; // color palette for the band meter (pre-fill in setup)

void setup() {
  Serial.begin(115200);
  M5.begin();
  dacWrite(25, 0); // Speaker OFF
  M5.Lcd.fillScreen(TFT_BLACK);
  M5.Lcd.setTextColor(YELLOW, BLACK);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setRotation(0);
  sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
  delay(2000);
  for(uint8_t i=0;i<tft_height;i++) {
    colormap[i] = M5.Lcd.color565(tft_height-i*.5, i*1.1, 0);
  }
  for (byte band = 0; band <= 7; band++) {
    M5.Lcd.setCursor(bands_width*band + 2, 0);
    M5.Lcd.print(audiospectrum[band].freqname);
  }
}

void loop() {
  for (int i = 0; i < SAMPLES; i++) {
    newTime = micros()-oldTime;
    oldTime = newTime;
    vReal[i] = analogRead(A0); // A conversion takes about 1uS on an ESP32
    vImag[i] = 0;
    while (micros() < (newTime + sampling_period_us)) { 
      // do nothing to wait
    }
  }
  FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
  FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);

  for (int i = 2; i < (SAMPLES/2); i++){ 
    // Don't use sample 0 and only first SAMPLES/2 are usable. 
    // Each array eleement represents a frequency and its value the amplitude.
    if (vReal[i] > 1500) { // Add a crude noise filter, 10 x amplitude or more
      byte bandNum = getBand(i);
      if(bandNum!=8) {
        displayBand(bandNum, (int)vReal[i]/audiospectrum[bandNum].amplitude);
      }
    }
  }
  
  long vnow = millis();
  for (byte band = 0; band <= 7; band++) {
    // auto decay every 50ms on low activity bands
    if(vnow - audiospectrum[band].lastmeasured > 50) {
      displayBand(band, audiospectrum[band].lastval>4 ? audiospectrum[band].lastval-4 : 0);
    }
    if (audiospectrum[band].peak > 0) {
      audiospectrum[band].peak -= 2;
      if(audiospectrum[band].peak<=0) {
        audiospectrum[band].peak = 0;
      }
    }
    // only draw if peak changed
    if(audiospectrum[band].lastpeak != audiospectrum[band].peak) {
      // delete last peak
     M5.Lcd.drawFastHLine(bands_width*band,tft_height-audiospectrum[band].lastpeak,bands_pad,BLACK);
     audiospectrum[band].lastpeak = audiospectrum[band].peak;
     M5.Lcd.drawFastHLine(bands_width*band, tft_height-audiospectrum[band].peak,
                           bands_pad, colormap[tft_height-audiospectrum[band].peak]);
    }
  } 
}

void displayBand(int band, int dsize){
  uint16_t hpos = bands_width*band;
  int dmax = 200;
  if(dsize>tft_height-10) {
    dsize = tft_height-10; // leave some hspace for text
  }
  if(dsize < audiospectrum[band].lastval) {
    // lower value, delete some lines
    M5.Lcd.fillRect(hpos, tft_height-audiospectrum[band].lastval,
                    bands_pad, audiospectrum[band].lastval - dsize, BLACK);
  }
  if (dsize > dmax) dsize = dmax;
  for (int s = 0; s <= dsize; s=s+4){
    M5.Lcd.drawFastHLine(hpos, tft_height-s, bands_pad, colormap[tft_height-s]);
  }
  if (dsize > audiospectrum[band].peak) {
    audiospectrum[band].peak = dsize;
  }
  audiospectrum[band].lastval = dsize;
  audiospectrum[band].lastmeasured = millis();
}

byte getBand(int i) {
  if (i<=2 )             return 0;  // 125Hz
  if (i >3   && i<=5 )   return 1;  // 250Hz
  if (i >5   && i<=7 )   return 2;  // 500Hz
  if (i >7   && i<=15 )  return 3;  // 1000Hz
  if (i >15  && i<=30 )  return 4;  // 2000Hz
  if (i >30  && i<=53 )  return 5;  // 4000Hz
  if (i >53  && i<=200 ) return 6;  // 8000Hz
  if (i >200           ) return 7;  // 16000Hz
  return 8;
}

.
CARD STAND:
ダイソーにある 2個100円の L型カードスタンド。64 x 45 x 20 mm。
M5STACK にピッタリ です!


広告

Written by macsbug

12月 31, 2017 at 9:00 am

カテゴリー: ESP32, ESP8266

GPS CLOCK with M5STACK

leave a comment »

M5STACK と GPS Module で GPS時計 を作りました                                       2017.12.26


日時、時刻を アナログ と デジタル で表示し 切り替えは3つの ボタンで選択します。

動作:
GPS 情報   : 左のボタンを押し 受信すると 右上の丸が 赤から緑。数値は白から緑。
アナログ時計:中央ボタンを押し 受信すると 右上の丸が 赤から緑になります。
デジタル時計: 右ボタンを押し 受信すると 右上の丸が 赤から緑。数値は白から緑。


準備:

No  Nomen  Link、説明   Price
1  M5STACK BASIC  M5Stack Store ( $33.25 )  3767円
2  M5STACK GPS Module (NEO-M8N−0-10)  M5Stack Store ( $37.91 )  4295円
3  M5STACK Battery Module  M5Stack Store ( $15.11 )  1712円
4  28dBi Gain GPS Antenna  importjewelrylover($2.52)   322円
 —————————————-  ————————-   ——
5  M5STACK ライブラリー  GitHub:M5STACK
6  Free_Fonts:M5STACKライブラリーの中にある。  .inoフォルダの中へ入れる
7  TineGPS++ ライブラリー  TinyGPS++
8  jpg 画像:55×55 pixels程度。(apple mark)  SD に入れる。

.


GPS Module:価格は高いですが 初めてですので 純正品を使用しました。

GPS Module:付属品:1.5mm ケーブル Battery Module
GPS Antenna

.
_ GPS Module のカバーが無く 綺麗でないです。そこで 部品が入っていた
_ 小さな透明なケースがあり サイズがピッタリでしたので 被せました。
.


.
GPS Module:GPSのチップは NEO-M8N-0-10 が使用されています。
配線:M5STACK と GPS Module ( NEO-M8N-0-10 )
_ ESP32 UART2 GPIO-16 ( U2RXD ) — GPS TXD ( NEO-M8N-0-10 ) 。
_ ハードウエアーシリアルの設定:例:HardwareSerial ss(2); 



追記:2018.01.13
小型の GPS アンテナ を取り付けました。ケースの中に入り綺麗に仕上がります。
_ ケース内部に取り付ける事が可能で、受信は正常に受ける事ができました。
_ 小型ですので感覚的に受信感度が少ないかなとも思いましたが最初の
_ 受信時間も数分間で同じでした。
_ 名称:GPS Module with Active Ceramic Antenna IPEX Interface 1575MHz
_ 販売:ebay:chip_partner:価格:$2.30 ( 256円 ):輸送期間 = 26日。
_ サイズ:20mm x 6mm x 6mm:ワイヤーの長さ:20mm
_ ケースの中の高さは 6.4mm ですので入ります。


感想:
M5STACK の利点 (強み) は サンプルやライブラリーの充実にあります。
単独で使用するか 今回の様に 合体して多くの機能を直ぐ作る事ができます。
特に 表示操作では SD内のjpg 画像 を DISPLAY へ表示する命令があります。
例: M5.Lcd.drawJpgFile(SD, “/apple_marks/apple_50.jpg”);
_  SD の中にある apple_50.jpg を LCD へ DRAW します。
_  M5STACK のライブラリーは 強力な開発環境です。 


疑問と課題 ( Questions and tasks ):
_ ESP32 M5STACK と 画像のバイト配列:
_ これまで画像をスケッチ内に保存するには xx.c という バイト配列のデーター
_ に変換し 変数名で使用していました。
_ M5STACK は バイト配列を表示すると 色づれ があり使用できません。
_ 色が反転している訳でも無いです。TFT Display と Display library は 何か細工
_ されている様に思えてしまいます。
_ 対策は SD から jpg を読み込む事ですが バイト配列も使用したい。
_ それと 画像データーを変数名で扱うには どうしたら良いのか解らず課題です。


.
スケッチ:GPS CLOCK with M5STACK : 2017.12.26 : macsbug
M5STACK Library にある「GPS/FullExample」と「Display/TFT_Clock」を
合体し作成しました。表示は GPS受信 と 日時、時刻を アナログとデジタル。
切り替えは A,B,C ボタンで選択します。
「time_set」は 場所に応じて設定します。日本の場合は JST に合わせます。
アナログ時計の左上は 55×55ピクセル程度の jpg画像を SD に入れて起きます。
SD に画像が無い場合は 何も表示せず動作します。

// GPS CLOCK WITH M5STACK : 2017.12.26 : macsbug
#include <M5Stack.h>
#include "Free_Fonts.h"
#include <TinyGPS++.h>
TinyGPSPlus gps;
HardwareSerial gs(2);           // ESP32 UART2 GPIO-16 ( RXD2 ) --- GPS TXD
//=========================================================================
int time_set = 9;       // Set to the time of your country. : JST = +9 hour
float    sx = 0,sy = 1,mx = 1,my = 0,hx = -1,hy = 0;
float    sdeg=0, mdeg=0, hdeg=0;
uint16_t osx=120,osy=120,omx=120,omy=120,ohx=120,ohy=120;
uint16_t x0=0, x1=0, yy0=0, yy1=0;
uint32_t targetTime = 0;                   // for next 1 second timeout
static uint8_t conv2d(const char* p);
uint8_t  hh=conv2d(__TIME__);              // Get H, M, S from compile time
uint8_t  mm=conv2d(__TIME__+3), ss=conv2d(__TIME__+6);
boolean  initial = 1;
static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
unsigned long distanceKmToLondon = (unsigned long)
         TinyGPSPlus::distanceBetween(
         gps.location.lat(),gps.location.lng(),LONDON_LAT,LONDON_LON)/1000;
double   courseToLondon = TinyGPSPlus::courseTo(
         gps.location.lat(),gps.location.lng(),LONDON_LAT,LONDON_LON);
const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);
int      ym, dm, dd;                      // year,month,day
String   ym_, dm_, dd_, hh_, mm_, ss_;    // year,month,day,hour,min,sec
char     f1, f2, f3, b1, b2, b3;          // digital:year,month,day buffer
String   L1[11]={"0000/00/00","00:00:00","000.00" // old gps,time,date,,
            ,"000.00","000.00","000.00","000.00"
            ,"000.00","000.00","000.00"};
String   L2[11]={"0000/00/00","00:00:00","000.00" // new gps,time,date,,
            ,"000.00","000.00","000.00","000.00"
            ,"000.00","000.00","000.00"};
String   mode_ = "gps";                   // gps,digital,analog
//=========================================================================
void setup(){
  Serial.begin(115200);
  M5.begin();
  gs.begin(9600);                   //static const uint32_t GPSBaud = 9600;
  M5.Lcd.fillScreen(BLACK);                                // DISPLAY CLEAR
  pinMode(BUTTON_A_PIN, INPUT_PULLUP);                     // Set A button
  pinMode(BUTTON_B_PIN, INPUT_PULLUP);                     // Set B button
  pinMode(BUTTON_C_PIN, INPUT_PULLUP);                     // Set C button
}
//=========================================================================
void loop(){ 
  if ( M5.BtnA.wasPressed()){ mode_ = "gps"    ; gps_setup()    ;}
  if ( M5.BtnB.wasPressed()){ mode_ = "analog" ; analog_setup() ;}
  if ( M5.BtnC.wasPressed()){ mode_ = "digital"; digital_setup();}
   
  // gps mode -------------------------------------------------------------
if ( mode_ == "gps" ){                                     // GPS MODE
  if ( initial == 1 ){ gps_setup();}                       // INITIAL SET
  time_date_read();                                        // READ DATA 

  L2[0] = String(gps.date.year()) + "/" + dm_ + "/" + dd_; // DATE
  L2[1] = hh_ + ":" + mm_ + ":" + ss_;                     // TIME
  L2[2] = String(gps.location.lat(),6);                    // LAT
  L2[3] = String(gps.location.lng(),6);                    // LNG
  L2[4] = String(gps.speed.kmph())          + " km/sec";   // SPEED
  L2[5] = String(gps.speed.mps())           + " m/sec";    // SPEED
  L2[6] = String(gps.speed.value())         + " Raw deg";  // CRS
  L2[7] = String(gps.course.deg())          + " deg";      // CRS
  L2[8] = String(gps.altitude.kilometers()) + " km";       // ALT
  L2[9] = String(gps.altitude.meters())     + " m";        // ALT

  M5.Lcd.setFreeFont(FM12); 
  for ( int i = 0; i < 11; i++ ){                          // DISPLAY
    M5.Lcd.setTextColor(BLACK, BLACK);
    M5.Lcd.drawString( L1[i], 100, 0 + ( 24 * i ));        // ERASE
    M5.Lcd.setTextColor( WHITE, BLACK);
    if (gps.location.lat() > 0){ M5.Lcd.setTextColor(GREEN,BLACK);} // RX
    M5.Lcd.drawString( L2[i], 100, 0 + ( 24 * i ));        // DRAW
    L1[i] = L2[i];                                         // SAVE
  } 

  smartDelay(1000);
 }
 
// analog mode  -----------------------------------------------------------
 if ( mode_ == "analog" ){                                 // ANALOG MODE
  time_date_read();                                        // READ DATA  
  sdeg = ss*6;                     // 0-59 -> 0-354   Pre-compute
  mdeg = mm*6+sdeg*0.01666667;     // 0-59 -> 0-360 - includes seconds
  hdeg = hh*30+mdeg*0.0833333;     // 0-11 -> 0-360 - inc min and seconds
  hx = cos((hdeg-90)*0.0174532925); hy = sin((hdeg-90)*0.0174532925);
  mx = cos((mdeg-90)*0.0174532925); my = sin((mdeg-90)*0.0174532925);
  sx = cos((sdeg-90)*0.0174532925); sy = sin((sdeg-90)*0.0174532925);

  M5.Lcd.drawLine(ohx, ohy, 160, 121, TFT_BLACK);          // ERASE HOUR
  M5.Lcd.drawLine(omx, omy, 160, 121, TFT_BLACK);          // ERASE MIN
  M5.Lcd.drawLine(osx, osy, 160, 121, TFT_BLACK);          // ERASE SEC
  ohx = hx*62+161; ohy = hy*62+121;                        // NEW   HOUR
  omx = mx*84+160; omy = my*84+121;                        // NEW   MIN
  osx = sx*90+161; osy = sy*90+121;                        // NEW   MIN
  M5.Lcd.drawLine(ohx, ohy, 160, 121, TFT_WHITE);          // DRAW  HOUR
  M5.Lcd.drawLine(omx, omy, 160, 121, TFT_WHITE);          // DRAW  MIN 
  M5.Lcd.drawLine(osx, osy, 160, 121, TFT_RED  );          // DRAW  SEC
  M5.Lcd.fillCircle(160, 121, 3, TFT_RED);                 // DOT   CENTER
  smartDelay(1000); 
 }
 
// digital mode  ----------------------------------------------------------
 if ( mode_ == "digital" ){                                // DIGITAL MODE
  time_date_read();                                        // READ DATA                   
  L2[0] = String(gps.date.year()) + "/" + dm_ + "/" + dd_; // OLD DATA
  L2[1] = hh_ + ":" + mm_ + ":" + ss_;                     // NEW DATA
  
  M5.Lcd.setFreeFont(FMB24);                               // FONT
  for ( int i = 0; i < 2; i++ ){                           // DISPLAY
    M5.Lcd.setTextColor(TFT_BLACK, TFT_BLACK);             // BLACK
    M5.Lcd.drawString(L1[i], 20, 60 + ( 80 * i ));         // ERASE
    M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);             // WHITE
    if (gps.location.lat() > 0){M5.Lcd.setTextColor(GREEN,BLACK);} // RX
    M5.Lcd.drawString(L2[i], 20, 60 + ( 80 * i ));         // DRAW
    L1[i] = L2[i];                                         // SAVE
  }
 smartDelay(1000); 
 }
 M5.update();
}                                                          // END OF MAIN
//=========================================================================
static void smartDelay(unsigned long ms){
  unsigned long start = millis();
  do{ while (gs.available())
      gps.encode(gs.read());
  } while (millis() - start < ms);
  if (millis() > 5000 && gps.charsProcessed() < 10){none_gps();}
}
//=========================================================================
static uint8_t conv2d(const char* p){
  uint8_t v = 0;
  if ('0' <= *p && *p <= '9'){v = *p - '0';}
  return 10 * v + *++p - '0';
}
//=========================================================================
void gps_setup(){                                          // GPS  SETUP
  M5.Lcd.fillScreen(TFT_BLACK);                            // CLEAR DISPLAY
  M5.Lcd.setFreeFont(FM12);                                // FONT
  M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);               // GPS  TITLE
  String L[11] = {"DATE","TIME","LAT","LNG","SPEED"        // GPS  TITLE
                    ,"SPEED","CRS","CRS","ALT","ALT"};     // GPS  TITLE
  for ( int i = 0; i < 11; i++ ){
    M5.Lcd.setCursor (     5, 0 + ( 24 * i ));
    M5.Lcd.drawString(L[i],5, 0 + ( 24 * i ));             // DRAW TITLE
  } 
  initial = 0;
}
//=========================================================================
void analog_setup(){                                       // ANALOG SETUP
  M5.Lcd.fillScreen(TFT_BLACK);                            // CLEAR DISPLAY
  M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);
  M5.Lcd.fillCircle( 160, 120, 118, TFT_GREEN);            // CLOCK FACE
  M5.Lcd.fillCircle( 160, 120, 110, TFT_BLACK);            // LOCK FACE
  for(int i = 0; i<360; i+= 30) {                          // 12 LINES
    sx = cos((i-90)*0.0174532925);
    sy = sin((i-90)*0.0174532925);
    x0 = sx*114 + 160; yy0 = sy*114 + 120;
    x1 = sx*100 + 160; yy1 = sy*100 + 120;
    M5.Lcd.drawLine(x0, yy0, x1, yy1, TFT_GREEN);          // DRAW 12 LINES
  }
  for(int i = 0; i<360; i+= 6) {                           // 60 DOTS
    sx = cos((i-90)*0.0174532925);
    sy = sin((i-90)*0.0174532925);
    x0 = sx*102 + 160; yy0 = sy*102 + 120;
    M5.Lcd.drawPixel(x0, yy0, TFT_WHITE);                  // MINUTE
    if(i== 0 || i==180)M5.Lcd.fillCircle(x0,yy0,2,WHITE);  // DOTS
    if(i==90 || i==270)M5.Lcd.fillCircle(x0,yy0,2,WHITE);  // DOTS
  }
  M5.Lcd.fillCircle(160, 121, 3, TFT_RED);                 // DOTS CENTER
  M5.Lcd.drawJpgFile(SD, "/apple_marks/apple_50.jpg");     // apple ICON
  targetTime = millis() + 1000; 
}
//=========================================================================
void digital_setup(){
  M5.Lcd.fillScreen(TFT_BLACK); return;
}
//=========================================================================
void time_date_read(){                           // READ YY.MM.DD, HH,MM,SS
  if (gps.location.lat() > 0){ M5.Lcd.fillCircle(315,5,5,GREEN);} // Rx
  if (gps.location.lat() < 1){ M5.Lcd.fillCircle(315,5,5,RED  );} // not Rx
  ym = gps.date.year();  ym_ = String(ym);
  dm = gps.date.month(); dm_ = String(dm); if (dm < 10){ dm_="0"+dm_;}
  dd = gps.date.day();   dd_ = String(dd); if (dd < 10){ dd_="0"+dd_;}
  ss = gps.time.second();ss_ = String(ss); if (ss < 10){ ss_="0"+ss_;}
  mm = gps.time.minute();mm_ = String(mm); if (mm < 10){ mm_="0"+mm_;}
  hh = gps.time.hour();
  if ( hh < 15 ){ hh = hh + time_set;}     goto t;         // JST ***
  if ( hh > 14 ){ hh = hh - time_set - 6;} goto t;         // JST ***
t:hh_ = String(hh); if (hh < 10){ hh_ = "0" + hh_;}        // ADD ZERO
}
//=========================================================================
void none_gps(){                                           // NONE GPS
  M5.Lcd.setFreeFont(FMB24);                               // FONT
  M5.Lcd.setTextColor(RED, BLACK);
  M5.Lcd.drawString("No GPS data received:", 20, 50);      // MESSAGE
  M5.Lcd.drawString("check wiring", 20, 130);              // MESSAGE
}
//=========================================================================


Written by macsbug

12月 26, 2017 at 2:37 pm

カテゴリー: ESP32

New Modules by Espressif Systems 2017.12

leave a comment »

Espressif Systems による 4つの新しいモジュール。       2017.12.20

2017年12月4日 に Espressif Systems から News があり 新しいモジュールには
TELEC が印字されています。

New Modules by Espressif Systems:Dec 4, 2017。
ESP32-based:ESP-WROOM-32D、ESP32-WROOM-32U。
ESP8266EX-based:ESP-WROOM-02D、ESP-WROOM-02U。


U.FLコネクタ内蔵やRF性能の最適化を実施。 詳細は以下を参照ください。

詳細:New Modules by Espressif Systems

資料:ESP-WROOM-32D/ESP32-WROOM-32U Datasheet:Nov 28,2017

資料:ESP-WROOM-02D/ESP-WROOM-02U Datasheet :2017

資料:ESP8266 System Description


.
FCC ID Database:ここには ESPRESSIF SYSTEMS の FCC Wireless Applications
「FCC ID applications by 2AC7Z」があります。その中は以下の物があります。
ESP32PICOKIT, ESP32PICOKIT, ESPWROOM02D, ESP32WROVER,
ESP32WROVER, ESPWROOMS2, ESPWROOM02, ESPWROOM32,
ESPWROOM32, ESP32, ESPWROOM02, ESP8266EX

ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD FCC Wireless Applications


.
ESP-WROOM-02D :FCC ID 2AC7Z-ESPWROOM02D
_ Espressif Systems による 4つの新しいモジュールは ESP-WROOM-32D、
_ ESP32-WROOM-32U、ESP-WROOM-02D、ESP-WROOM-02U があります。
_ 現在、発売は まだですが、詳細は「FCC ID 2AC7Z-ESPWROOM02D」に
_ ESP-WROOM-02D の User manual, Test setup,Test report, RF Exposure,
_  Internal photos, Label, External photos, Cover letter が書かれています。

資料:ESP-WROOM-02D User Guide ver 1.0


Module Teardown Internal Photos


.
総務省 と ESP-WROOM-32 TELEC の記載について:
_ H28.12.30付けで「総務省」のページに記載されています。
_ 技術基準適合証明等の公示(平成28年度分)一番下の
_ 「(11)Bay Area Compliance Laboratories Corp」の
_ 「115 平成28年12月16日~平成28年12月31日 」。
_ 下から4行目に「ESP-WROOM-32」「211-161007」が書かれています。


.
感想:
Espressif Systems 2017 の計画は ESP-WROOM-32 でした。
今回の改修バージョン と ESP32-PICO-D4 で 2018年に繋がるものかと想像します。

販売されている ESP32-PICO-D4:$20.21
Aliexpress:Lily GO:TTGO T7 ESP32 Module PICO-D4 4MB SPI Flash


Written by macsbug

12月 20, 2017 at 10:31 am

カテゴリー: ESP32

M5STACK TELEC information

leave a comment »

M5STACK TELEC 情報:                 2017.12.14

M5STACK (12/13) によると FCC / CE / MIC(総務省) 認定を取得したとの事です。
JAPAN MIC CERTIFICATE OF TYPE APPROVAL:
TELEC 番号は 211-171004 です。

 

 


感想:ESP32ボード。
これで M5STACK は 最強の ESP32 ボードとなりました。

1. 美しいケース、オールインワンで 多用途に直ぐ使用でき 高機能。
_ 「M5STACK」:3945 円 ( $35.00 )。SALE = 3437 円 ( $30.45 ) 。

2. 低価格で直ぐ使用でき、小型で組み込み安いボード。
_ 「MH-ET LIVE ESP32 MINI KIT」:901 円 ( $7.98 )。


Written by macsbug

12月 14, 2017 at 6:38 pm

カテゴリー: ESP32