SSブログ

ESP32のLEDCについて調べてみた。 [ESP32]

某SNSで、LEDCで16チャネル分のPWM出力した時、チャネル8以降でDutyを0に設定してもLOWにならない!と言う話があって、ちょっとLEDCについて調べてみた。
なので以下の様なコードを書いてお確かめ。

ESP32_LEDC_TEST.ino
#include  "led.h"

#define  LED_CH0_PIN  32
#define  LED_CH1_PIN  33
#define  LED_CH2_PIN  25
#define  LED_CH3_PIN  26
#define  LED_CH4_PIN  27
#define  LED_CH5_PIN  14
#define  LED_CH6_PIN  13
#define  LED_CH7_PIN  15
#define  LED_CH8_PIN  4
#define  LED_CH9_PIN  16
#define  LED_CH10_PIN  17
#define  LED_CH11_PIN  5
#define  LED_CH12_PIN  18
#define  LED_CH13_PIN  19
#define  LED_CH14_PIN  21
#define  LED_CH15_PIN  22

#define  LED_CH0_FRQ  1000.0  /* hz チャネル0とチャネル1は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH1_FRQ  2000.0  /* hz チャネル0とチャネル1は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH2_FRQ  3000.0  /* hz チャネル2とチャネル3は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH3_FRQ  4000.0  /* hz チャネル2とチャネル3は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH4_FRQ  5000.0  /* hz チャネル4とチャネル5は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH5_FRQ  6000.0  /* hz チャネル4とチャネル5は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH6_FRQ  7000.0  /* hz チャネル6とチャネル7は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH7_FRQ  8000.0  /* hz チャネル6とチャネル7は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH8_FRQ  9000.0  /* hz チャネル8とチャネル9は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH9_FRQ  10000.0  /* hz チャネル8とチャネル9は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH10_FRQ  20000.0  /* hz チャネル10とチャネル11は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH11_FRQ  30000.0  /* hz チャネル10とチャネル11は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH12_FRQ  40000.0  /* hz チャネル12とチャネル13は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH13_FRQ  50000.0  /* hz チャネル12とチャネル13は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH14_FRQ  60000.0  /* hz チャネル14とチャネル15は同一タイマーの為、後から設定した方の周波数になるはず */
#define  LED_CH15_FRQ  70000.0  /* hz チャネル14とチャネル15は同一タイマーの為、後から設定した方の周波数になるはず */

#define  LED_CH0_RES  (8)  /* resolution */
#define  LED_CH1_RES  (8)  /* resolution */
#define  LED_CH2_RES  (8)  /* resolution */
#define  LED_CH3_RES  (8)  /* resolution */
#define  LED_CH4_RES  (8)  /* resolution */
#define  LED_CH5_RES  (8)  /* resolution */
#define  LED_CH6_RES  (8)  /* resolution */
#define  LED_CH7_RES  (8)  /* resolution */
#define  LED_CH8_RES  (8)  /* resolution */
#define  LED_CH9_RES  (8)  /* resolution */
#define  LED_CH10_RES  (8)  /* resolution */
#define  LED_CH11_RES  (8)  /* resolution */
#define  LED_CH12_RES  (8)  /* resolution */
#define  LED_CH13_RES  (8)  /* resolution */
#define  LED_CH14_RES  (8)  /* resolution */
#define  LED_CH15_RES  (8)  /* resolution */

#define  DUTY( duty,res )  map( duty,0,100,0,(1 << res) - 1 )

led led_0( LED_CH0_PIN, 0 );
led led_1( LED_CH1_PIN, 1 );
led led_2( LED_CH2_PIN, 2 );
led led_3( LED_CH3_PIN, 3 );
led led_4( LED_CH4_PIN, 4 );
led led_5( LED_CH5_PIN, 5 );
led led_6( LED_CH6_PIN, 6 );
led led_7( LED_CH7_PIN, 7 );
led led_8( LED_CH8_PIN, 8 );
led led_9( LED_CH9_PIN, 9 );
led led_10( LED_CH10_PIN, 10 );
led led_11( LED_CH11_PIN, 11 );
led led_12( LED_CH12_PIN, 12 );
led led_13( LED_CH13_PIN, 13 );
led led_14( LED_CH14_PIN, 14 );
led led_15( LED_CH15_PIN, 15 );

void setup()
{
  /* led 0 */
  led_0.begin( LED_CH0_FRQ, LED_CH0_RES );
  led_0.write( DUTY( 50,LED_CH0_RES) );
  /* led 1 */
  led_1.begin( LED_CH1_FRQ, LED_CH1_RES );
  led_1.write( DUTY( 50,LED_CH1_RES) );
  /* led 2 */
  led_2.begin( LED_CH2_FRQ, LED_CH2_RES );
  led_2.write( DUTY( 50,LED_CH2_RES) );
  /* led 3 */
  led_3.begin( LED_CH3_FRQ, LED_CH3_RES );
  led_3.write( DUTY( 50,LED_CH3_RES) );
  /* led 4 */
  led_4.begin( LED_CH4_FRQ, LED_CH4_RES );
  led_4.write( DUTY( 50,LED_CH4_RES) );
  /* led 5 */
  led_5.begin( LED_CH5_FRQ, LED_CH5_RES );
  led_5.write( DUTY( 50,LED_CH5_RES) );
  /* led 6 */
  led_6.begin( LED_CH6_FRQ, LED_CH6_RES );
  led_6.write( DUTY( 50,LED_CH6_RES) );
  /* led 7 */
  led_7.begin( LED_CH7_FRQ, LED_CH7_RES );
  led_7.write( DUTY( 50,LED_CH7_RES) );
  /* led 8 */
  led_8.begin( LED_CH8_FRQ, LED_CH8_RES );
  led_8.write( DUTY( 50,LED_CH8_RES) );
//  led_8.write( 0 );
//  led_8.write( 255 );
  /* led 9 */
  led_9.begin( LED_CH9_FRQ, LED_CH9_RES );
  led_9.write( DUTY( 50,LED_CH9_RES) );
  /* led 10 */
  led_10.begin( LED_CH10_FRQ, LED_CH10_RES );
  led_10.write( DUTY( 50,LED_CH10_RES) );
  /* led 11 */
  led_11.begin( LED_CH11_FRQ, LED_CH11_RES );
  led_11.write( DUTY( 50,LED_CH11_RES) );
  /* led 12 */
  led_12.begin( LED_CH12_FRQ, LED_CH12_RES );
  led_12.write( DUTY( 50,LED_CH12_RES) );
  /* led 13 */
  led_13.begin( LED_CH13_FRQ, LED_CH13_RES );
  led_13.write( DUTY( 50,LED_CH13_RES) );
  /* led 14 */
  led_14.begin( LED_CH14_FRQ, LED_CH14_RES );
  led_14.write( DUTY( 50,LED_CH14_RES) );
  /* led 15 */
  led_15.begin( LED_CH15_FRQ, LED_CH15_RES );
  led_15.write( DUTY( 50,LED_CH15_RES) );
}

void loop()
{
}

led.h
/****************************************************************************/
/* led header                                                               */
/*                         Copyright (C) 2018 hamayan All Rights Reserved.  */
/****************************************************************************/
#ifndef LED_h
#define LED_h

#include  <Arduino.h>
#include  <esp32-hal-ledc.h>

extern "C" {
}

class led {
private :
  uint8_t ledPin;
  uint8_t ledChannel;

public :  
  led( uint8_t pin, uint8_t channel );
  ~led();
  double begin( double freq, uint8_t resolution_bits );

  void write( uint32_t duty );
  uint32_t read();
  double tone( double freq );
  double note( note_t note, uint8_t octave );
};

#endif /* LED_h */

/****************************************************************************/
/*                                  Copyright (C) 2018- by hamayan          */
/****************************************************************************/

led.c
/****************************************************************************/
/* led source                                                               */
/*                         Copyright (C) 2018 hamayan All Rights Reserved.  */
/****************************************************************************/
#include  "led.h"

/*************************************************************************/
/*  constructor,destructor                                               */
/*************************************************************************/
led::led( uint8_t pin, uint8_t channel )
{
  ledPin = pin;
  ledChannel = channel;
  ledcAttachPin( pin, channel );
}

led::~led()
{
  ledcDetachPin( ledPin );
}

/*************************************************************************/
/*  begin                                                                */
/*************************************************************************/
double led::begin( double freq, uint8_t resolution_bits )
{
  return ledcSetup( ledChannel, freq, resolution_bits );
}


/*************************************************************************/
/*  write (duty)                                                         */
/*************************************************************************/
void led::write( uint32_t duty )
{
  ledcWrite( ledChannel, duty );
}


/*************************************************************************/
/*  read (duty)                                                          */
/*************************************************************************/
uint32_t led::read()
{
  return ledcRead( ledChannel );
}


/*************************************************************************/
/*  tone                                                                 */
/*************************************************************************/
double led::tone( double freq )
{
  return ledcWriteTone( ledChannel, freq );
}


/*************************************************************************/
/*  note                                                                 */
/*************************************************************************/
double led::note( note_t note, uint8_t octave )
{
  return ledcWriteNote( ledChannel, note, octave );
}


/****************************************************************************/
/*                                  Copyright (C) 2018- by hamayan          */
/****************************************************************************/

チャネル0のみ1000HzでDuty=50%の波形を出力してみると以下の波形となった。
2018-11-16 10.35.13.jpg


次に全16チャネルを出力させてみた。その時のチャネル0の波形が以下である。
2018-11-16 10.43.19.jpg

お判り頂けたであろうか?PWM周波数が変わってしまっている。

以下はesp32_hal_ledc.cの一部抜粋である。
/*
 * LEDC Chan to Group/Channel/Timer Mapping
** ledc: 0  => Group: 0, Channel: 0, Timer: 0
** ledc: 1  => Group: 0, Channel: 1, Timer: 0
** ledc: 2  => Group: 0, Channel: 2, Timer: 1
** ledc: 3  => Group: 0, Channel: 3, Timer: 1
** ledc: 4  => Group: 0, Channel: 4, Timer: 2
** ledc: 5  => Group: 0, Channel: 5, Timer: 2
** ledc: 6  => Group: 0, Channel: 6, Timer: 3
** ledc: 7  => Group: 0, Channel: 7, Timer: 3
** ledc: 8  => Group: 1, Channel: 0, Timer: 0
** ledc: 9  => Group: 1, Channel: 1, Timer: 0
** ledc: 10 => Group: 1, Channel: 2, Timer: 1
** ledc: 11 => Group: 1, Channel: 3, Timer: 1
** ledc: 12 => Group: 1, Channel: 4, Timer: 2
** ledc: 13 => Group: 1, Channel: 5, Timer: 2
** ledc: 14 => Group: 1, Channel: 6, Timer: 3
** ledc: 15 => Group: 1, Channel: 7, Timer: 3
*/

チャネル0とチャネル1は同一タイマーとなっている、、、ようするにチャネル0とチャネル1間では、後から設定した方が有効となってしまう。そりゃそうだ、、、
またチャネル0からチャネル7までと、チャネル8からチャネル15までで異なるグループとなっている。これはグループ0が80MHzを原振とする高速側のタイマー、グループ1が1MHz?を原振とする低速側のタイマーとなっているようである。
つまりledcで沢山のチャネルを使用する時は、上記事柄に気を付けて使う必要がある。

※低速側タイマーの場合、最大のPWM周波数は312KHz(8bit解像度)くらい?
※高速側タイマーの場合、最大のPWM周波数は312KHz(8bit解像度)くらい?
※え!う~~~~ん、高速は判る、80MHzを256で割れば312KHzだしい。まるでウドンのキツネをつまんでいる様な、、、
※結局グループ0側も、グループ1側も、解像度を2bitにすると20MHzの波形を出力できるのう!なんだったのだろう???
※20MHzにすると、IO18とIO21が出力しない。

さて、件のLOWが出ない件であるが、Duty=0とした時の波形が以下である。
2018-11-16 11.11.15.jpg

LOWフラット、、、
試しにDuty=100とした時の波形は以下である。
2018-11-16 11.12.05.jpg

3.3Vフラットに見えるが、立下りのヒゲが出ている、、、

nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。