RTC用に外部クロック32kHzを使う(Arduino編)

ここにESP32 IDF上で外付32kHzの発振器を使ったRTC製作例が有ります。ー>RTC用に外部クロック32kHzを使う。Arduinoでも付32kHzの発振器が使えないか試して見ました。

使用した回路

RTC用に外部クロック32kHzを使うと同じ回路を使用しました。

Webで関連ソフトを探す

Webを参考に下記のプログラムを作成しました。

test.ino

#include <soc/rtc.h>
#include <ESP32Time.h>
#include "esp_deep_sleep.h"

#define uS_TO_S_FACTOR 1000000ULL  
#define TIME_TO_SLEEP  5        
#define CALIBRATE_ONE(cali_clk) calibrate_one(cali_clk, #cali_clk)

ESP32Time rtc;

void wakeup_reason() 
{
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();
  if(wakeup_reason == ESP_SLEEP_WAKEUP_TIMER) Serial.println("Wakeup caused by timer");
  else Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
  
  print_slow_clock_source();
              
  rtc_clk_32k_bootstrap(10);
  rtc_clk_32k_bootstrap(10);
  rtc_clk_slow_freq_set(RTC_SLOW_FREQ_32K_XTAL);
  rtc_clk_32k_enable(true);

  uint32_t cal_32k = CALIBRATE_ONE(RTC_CAL_32K_XTAL);

  if (cal_32k == 0) Serial.println("32K XTAL OSC has not started up");
  else Serial.println("32K XTAL OSC Calibrated");

  print_slow_clock_source();
}

void print_slow_clock_source() 
{
  rtc_slow_freq_t slow_clk = rtc_clk_slow_freq_get();
  Serial.print("Slow clk source: ");
  switch(slow_clk) 
  {
    case RTC_SLOW_FREQ_RTC: Serial.println("Internal 150kHz"); break;
    case RTC_SLOW_FREQ_32K_XTAL: Serial.println("External 32kHz"); break;
    case RTC_SLOW_FREQ_8MD256: Serial.println("Internal 8MHz");
  }
}

void setup() 
{
  Serial.begin(115200);

  wakeup_reason();
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

  Serial.println("Going to sleep now");
  print_slow_clock_source();
  esp_deep_sleep_start();
}

const float factor = (1 << 19) * 1000.0f;
static uint32_t calibrate_one(rtc_cal_sel_t cal_clk, const char *name)
{
    const uint32_t cal_count = 1000;
    uint32_t cali_val;

    printf("%s:\n", name);
    for (int i = 0; i < 10; ++i)
    {
        printf("calibrate (%d): ", i);
        cali_val = rtc_clk_cal(cal_clk, cal_count);
        printf("%.3f kHz\n", factor / (float)cali_val);
    }
    return cali_val;
}

void loop() 
{
  
}
  • 以下の関数がキーの様です
    • 21行:rtc_clk_32k_bootstrap(10); 
      • 32kHzの発振器を発振させるのに必要は関数と思われる
    • 23行:rtc_clk_slow_freq_set(RTC_SLOW_FREQ_32K_XTAL);
      • RTCの発振器を32kHzにセットする関数
    • 24行:rtc_clk_32k_enable(true);
      • 32kHzを有効にする関数
  • 外部クロックを起動後キャリブレーションを行う。
  • プログラムは5秒間隔でDeepSleepを繰り返します。
  • 要所で現在の有効発振器をprint_slow_clock_source();で表示させています。

rtc_clk_32k_bootstrap()を何回か実行した後、rtc_clk_slow_freq_set(RTC_SLOW_FREQ_32K_XTAL)、rtc_clk_32k_enable(true);を行えば外部32kHzが使える様です。ただこの条件で起動しする場合としない場合をWebで見かけました。取り敢えずこれを実行すると以下の様にモニターに出力されましたがDeepSleepから復帰しませんでした。

monitor

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
Wakeup was not caused by deep sleep: 0
Slow clk source: Internal 150kHz
RTC_CAL_32K_XTAL:
calibrate (0): 32.636 kHz
calibrate (1): 32.766 kHz
calibrate (2): 32.767 kHz
calibrate (3): 32.766 kHz
calibrate (4): 32.767 kHz
calibrate (5): 32.766 kHz
calibrate (6): 32.767 kHz
calibrate (7): 32.766 kHz
calibrate (8): 32.767 kHz
calibrate (9): 24.092 kHz
32K XTAL OSC Calibrated
Slow clk source: External 32kHz
Going to sleep now
Slow clk source: External 32kHz

  • 14行:Slow clk source: Internal 150kHz。 
    • 起動直後は内部発振器150kHzが選択されています。この後32kHzの発振器が起動します。
  • 15行:ここでキャリブレーションを行う。
    • 10回のキャリブレーションを行っていますが、大体32kHz位の値を返すのですが最後が24.092となっています。不十分な値です。
  • 27行:Slow clk source: External 32kHz
    • 外部クロックに切り替わった様に見えますが、実際にはクロックが発振していない様です。
    •  ー>キャリブレーションで正しい値を返していない為
  • 29行:Slow clk source: External 32kHz
    • DeepSleepに入る直前でもう一度クロックを確認すると、32kHzが起動していると返して来ますが、DeepSleepから復帰しません。
    • クロックが発振していないと思われます。

どうもこのプログラムでは発振しないグループの様です。

チップのバージョン

チップのバージョンが3以下では外部発振器の発振に不具合が有る事を思い出しました。そこで使っているチップのバージョンを確認しました。以下はコンパイル後Arduinoに出力された表示の一部です。4行目にrevision 1 と有ります。発振に問題の有るバーションです。

monitor

esptool.py v3.0-dev
Serial port /dev/ttyACM0
Connecting........__
Chip is ESP32-D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: c8:f0:9e:a6:b2:30
Uploading stub...
Running stub...
Stub running...

RTC用に外部クロック32kHzを使うではこれについてmenuconfigで対応しました。ただArduinoで同様の対応の仕方が分かりません。今回はこれで諦めました。

最後に

Webで起動した人、しない人がいるのは使用しているチップのバージョンの関係と思われます。バージョン3以上のESP32で確かめたい所ですが手持ちが有りません。バージョン3以上を手にいれたら確認してみます。

<<Before

Next>>