ESP32でLINX for LabVIEW入門 その3 PWM

概要

前回はデジタル入出力と、アナログ入力を行いました。今回はPWM出力を行いたいと思います。ライブラリを最新版にしてから実行するようにしてください。

PWMとは?

PWMとはデジタル出力を高速でオン、オフすることで明るさなどを調整するための仕組みです。

上記の場合、8スロットにわけて、2スロット分だけオンをした場合になります。全体の25%の時間がオンになっていますので、LEDなどは25%の明るさで光ります。

こちらは、8スロットにわけて、4スロット分だけオンをした場合になります。全体の50%の時間がオンになっていますので、LEDなどは50%の明るさで光ります。

上記が実際の出力をオシロスコープで測定した図ですが、0%、50%、100%の順番で出力を変更されているのがわかります。

スケッチ

#include <M5StickC.h>
#include <LinxESP32.h>
#include <LinxESP32WifiListener.h>
#include <LinxSerialListener.h>
LinxESP32* LinxDevice;
void setup()
{
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);
  LinxDevice = new LinxESP32();
  // PWM & Servo Setup
  uint8_t pwmList[] = {0, 26};    // Max16Ch {0, 26, ...}
  uint16_t pwmFrequency = 12000;  // LED:12000, Servo:50
  for (int i = 0; i < sizeof(pwmList); i++) {
    ledcSetup(i, pwmFrequency, 8);
    pinMode(pwmList[i], OUTPUT);
    ledcAttachPin(pwmList[i], i);
  }
  LinxWifiConnection.Start(LinxDevice, 44300);
  LinxSerialConnection.Start(LinxDevice, 3);
}
void loop()
{
  LinxWifiConnection.CheckForCommands();
  LinxSerialConnection.CheckForCommands();
  M5.update();
  if (millis() % 1000 == 0) {
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.println("LinxESP32");
    M5.Lcd.print("IP  : ");
    M5.Lcd.println(WiFi.localIP());
    byte macAddress[6];
    WiFi.macAddress(macAddress);
    M5.Lcd.printf("MAC : %02X:%02X:%02X:%02X:%02X:%02X\n", macAddress[0], macAddress[1], macAddress[2], macAddress[3], macAddress[4], macAddress[5]);
  }
  if (M5.Axp.GetBtnPress() != 0) {
    ESP.restart();
  }
  delay(1);
}

上記はM5StickCで画面に表示もするスケッチ例です。PWMを使う場合にはあらかじめ、どのGPIOをPWMに使うのかを設定しておく必要があります。

  // PWM & Servo Setup
  uint8_t pwmList[] = {0, 26};    // Max16Ch {0, 26, ...}
  uint16_t pwmFrequency = 12000;  // LED:12000, Servo:50
  for (int i = 0; i < sizeof(pwmList); i++) {
    ledcSetup(i, pwmFrequency, 8);
    pinMode(pwmList[i], OUTPUT);
    ledcAttachPin(pwmList[i], i);
  }

上記が設定部分になります。PWMチャンネル0にGPIO0、PWMチャンネル1にGPIO26を設定しています。また、PWMの周波数もここで設定します。通常のPWMの場合は12000(12kHz)ぐらいでいいと思いますが、サーボを利用する場合には50に設定してください。

共存する場合にはループではなくて、個別に設定をしたほうがシンプルになると思います。

LINX – PWM 1 Channel.vi

上記の画面で、PWMのチャンネル数と出力比を設定します。PWMはGPIOではなく、PWMチャンネル番号の0から15を指定するので間違えないようにしてください。Duty Cycleは0から1までを設定できるので、0.5を指定すると50%の出力となります。

いつものRunではなく、その隣にあるRun Continuousボタンを押すと、パラメータを変更したものがすぐに反映して便利です。

処理内容もシンプルです。

LINX – PWM N Channel.vi

こちらも他のNチャンネルと一緒ですね。

処理もシンプルです。

LINX – Digital Write Square Wave.vi

こちらはtone関数で圧電スピーカーを鳴らすような処理です。ESP32はtone関数が無いので、PWMを使うようになっていますので、GPIOではなくPWMチャンネル数を指定してください。

また、このサンプルは音がなり終わる前に次のループが始まってしまうのでWaitを追加しました。実際のところLabVIEWを使って音を鳴らすのであればアクティブブザーなどを使って、通常のデジタル出力をしたほうがいいと思います。

LINX – Servo 1 Channel.vi

サーボを使う場合には、PWM周波数を50Hzに設定する必要があります。LabVIEWからはマイクロ秒単位のパルス幅を指定することで制御します。

SG90サーボの場合は、データシート上500マイクロ秒から2400マイクロ秒が指定できますが、このサンプルは2500まで設定できるので注意してください。

まとめ

PWMまわりを動くようにしてみました。アナログ出力も使えるようにしようとしたのですが、Arduino UNOでもサポートしておらず、サンプルもないので対応しないことにしました。

コメント

  1. 大橋康司 より:

    ありがとうございます。「LinxESP32」ライブラリを活用させていただいています。ESP32でI2Cセンサーを使いたかったので、一部改変させて使わせていただきました。
    NIのディスカッションフォーラムの北東北LabVIEWユーザー会に以下のタイトルで記事を書きました。
    ESP32でLINX(その2)「ESP32 MH-LIVE Mini KitとI2C接続のCCS811空気品質センサー」

    誤った点などがあれば訂正したいと思いますので、お時間のある時に一読願えれば幸いです。

  2. たなかまさゆき より:

    おー、I2Cも触ってみようと思いつつ手が出ていませんでした
    本当はコールバック関数とかを登録して、自由に使える方が良さそうですよね

    アナログチャンネル41以上をコールバック用にして、コールバック関数でI2Cからデータ取得して返却の方がいいのかなーって思っていますが、構想がまとまっていません