M5StickC PlusでPWMコントローラを作る

レーザーカッター

PWMか電圧か

前回購入して熱くなっていたモジュールはPWMと呼ばれる高速でスイッチのオンオフを繰り返してモーターの回転を制御するものだ。これとは別に単純にモーターへかける電圧を上下させて回転数を落とすという制御方法もある。PCを自作したことがあればケースファンの配線が3本と4本のものがあるのでご存じの方もいるだろう。現在ではPWMの方が主流だろうか。

今回は余っていたマイコン(M5StickC Plus)を使用して作ることにしたため、より簡単なPWM方式とした。オンオフを繰り返すMOSFETについては発熱を考慮して並列に接続されているものを探す。これにPWM信号を送ればいいだけだ。あとは12Vを5Vへ降圧するものくらい。細々したものは手持ちでどうにかなるだろう。

このPWMとはPulse Width Modulation(パルス幅変調)の略で、これは一定の周期の中でどれだけオンにしておくか(パルス幅)を調整して制御するもの。身近なところではLED照明の調光もこれを利用している。

M5StickC Plusとは

今回使用するM5StickC Plusは、M5Stackという5cm x 5cmでESP32を搭載し、液晶やWi-Fi、バッテリー、ボタンなども搭載しているマイコンモジュールの派生品で、M5Stackの幅を半分にしたような小型版だ。多くはないが、センサー類などを接続できるGPIOを持ち合わせているのでHATと呼ばれる専用のモジュールや自作した基板などとの接続もできる。

M5StickC Plusとバッテリー

これをだいぶ前に購入して飽きて放置していたのを思い出したので使うことにしたのだが、バッテリーが膨らんできていたため、さっさと取り外した。今回はダイヤフラムポンプと電源は共有するのでバッテリーは必要ない。

ほかのESP32やArduinoでも同様の物は作れるが、何らかの表示部品を外付けすると手間が増えるので、この小さな液晶でも今回の用途では十分だろう。可変抵抗の調整だけで済ませるのなら、それでもいいと思う。

その他の部品たち

まずはデュアルMOSFETモジュール

PWMモジュール

MOSFETがふたつ並列に接続されていて、なにより安い(10個で699円)。正直不安になる値段であるが、パワーMOSFETをいくつも買って試すとなると面倒なのでこれでいい。

他に買ったもの

家にあったもの

電線さえ気にしなければだいぶ安かっただろう。クイックコネクタに関してはWAGOあたりに変えたほうが事故は防げるかもしれない。

プログラミング

M5StickCで使えるプログラミング言語はいくつかあるが、今回はArduino IDE(Arduino言語)を使用していく。セットアップとかは他に詳しいブログがたくさんあるので割愛。

まずIDEを立ち上げる前に可変抵抗をM5StickCに接続できるようにしよう。

可変抵抗がつながったM5StickC Plus

Grove4ピンケーブルの片方の端を切り落として被覆を剝き、可変抵抗のピン番号1に黒、2に黄、3に赤となるように接続。これをM5StickCのGrove端子に接続する。可変抵抗はノブの回転によって抵抗値が増減するもので、今回はその値を使ってPWMのDuty比(オンになっているパルス幅の割合)を変化させる予定だ。

問題なくArduino IDEやドライバセットアップ、ボードマネージャでの準備が終わったら、ツールバー上のドロップダウンで「M5StickC-Plus」の選択を確認しておく。こうしないとマイコンにプログラムが書き込まれない。

ここまで来たらさっそくプログラミングだ。

#include <M5StickCPlus.h>
#include "EEPROM.h" 

const int PWMPin = 32;
const int VolPin = 33;
const int ROMAddr = 0;

int iFreq = 3;
int iDuty = 50;

int arFreq[9] = {100, 200, 400, 800, 1600, 3200, 6400, 12800, 20000};

まず#includeで必要なヘッダーファイルを指定する。今回は周波数の設定をEEPROM(M5StickCに搭載されている不揮発性メモリ)に保存・読み込みを行うので、その機能のためのヘッダーファイルも指定している。

次に変数の宣言と初期化。使用するGPIOの番号(32,33)とEEPROMのアドレス(0)、周波数とDuty比、それからボタンを押したときに変更させる周波数用の配列。配列の最後の方が12800のあとで20000となっているのはMOSFETモジュールのサポート範囲が0~20kHzという記載があったためだ。

void setup() {
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.setTextColor(ORANGE, BLACK); 
  M5.Lcd.setTextFont(4);
  M5.Lcd.setTextSize(1);   
  
  EEPROM.begin(1);
  iFreq = EEPROM.read(ROMAddr);
  
  pinMode(VolPin, INPUT);
  ledcSetup(1, arFreq[iFreq], 8);
  ledcAttachPin(PWMPin, 1);

  int iVal = analogRead(VolPin);
  //可変抵抗の値が前回と同じ場合、初回の描画が行われないため一度呼び出す
  ShowStatus(iVal);
}

続いてsetup関数。これが最初に呼び出されるので、色んな初期化処理を行う。M5StickCの液晶の下準備、EEPROMの準備と保存していた値の読み込み、GPIOとPWMのための設定を経て、可変抵抗の値を読み取り(analogRead)、液晶画面表示用の関数(ShowStatus)を呼び出している。

void ShowStatus(int iVolval){
  int iPWM = map(iVolval, 0, 4095, 0, 256);
  iDuty = map(iVolval, 0, 4095, 0, 100);
  
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(10, 30);
  M5.Lcd.printf("Duty: %d %%", iDuty);
  M5.Lcd.setCursor(10, 90);
  if(iFreq < 4){
    M5.Lcd.printf("Freq: %d Hz", arFreq[iFreq]);
  }else{
    M5.Lcd.printf("Freq: %3.1f kHz", arFreq[iFreq] / 1000.0);
  }
  ledcWrite(1, iPWM);
}

液晶画面表示用の関数だ。引数として渡された値を使って画面の表示とPWMの設定の変更を行っている。map関数を使用して、ledcWrite関数へ渡す値とDuty比として画面に表示する値を作り、液晶書き換えの諸々、最後にPWMのDuty比を変更して終わり。

void loop() {
  M5.update();
  bool bBtnRel = false;
  if(M5.BtnA.wasReleased()){
    if(iFreq == 8){
      iFreq = 0;
    }else{
      iFreq++;
    }
    bBtnRel = true;
    ledcSetup(1, arFreq[iFreq], 8);
    EEPROM.write(ROMAddr, iFreq);
    EEPROM.commit();
  }
  
  int iVal = analogRead(VolPin);
  int imapVal = map(iVal, 0, 4095, 0, 100);
  //analogReadの値では安定しないため、Duty比で比較
  if(imapVal != iDuty || bBtnRel == true){
    ShowStatus(iVal);
  }
  delay(100);
}

loop関数は名前の通りデバイスが動いている間繰り返し呼び出される関数だ。ここで可変抵抗の変化、もしくはボタンの状態を読み取って画面表示を変更している。まずボタンが押されていたら周波数の変更(ledcSetup)、その後にEEPROMへの保存を行う。可変抵抗の値を読み取ったら、画面を更新するかどうかの判断をして、値の変化があった場合のみShowStatus関数を呼び出す。こうしないと100ミリ秒毎に画面が更新されてしまい画面がちらつくからだ。

プログラミングはここまで。単純なのであっという間だ。ツールバー上の→(書き込み)ボタンを押してM5StickCへプログラムの書き込みを行う。コードに問題がなければエラーもなくすぐに終わるだろう。

書き込みが終わったら可変抵抗を回したり、ボタンを押したりして画面表示が変わるか確認する。オシロスコープがあるならGrove端子の白い線と可変抵抗の1番ピンを使用してPWMの確認ができる。

PWMの確認。1.6kHz,31%
PWMの確認。100Hz,14%

ユニバーサル基板への実装

実装などと書いているがプログラムが単純ならこちらも単純だ。

本当に単純なので回路図などはない。右下のDCジャックから入ってきた12Vを端子台を経由してMOSFETモジュールと降圧モジュールへ分配する。降圧モジュールからの5VはM5StickCの上部にある5VIN端子へ。12VはそのままMOSFETモジュールのVINへ。グランドも適切に各モジュールへ接続する。Grove端子から伸びた白い線をMOSFETモジュールのTRIG/PWM端子へ。ポンプへの出力のところにダイオードが付いているが、これはフリーホイールダイオードというものでMOSFETを守るために付けている。

試運転と現実的な代替案

赤、黒の線をクイックコネクタ等を使用してポンプへ接続し、DCジャックには12VのACアダプターを接続。ポンプの音や水量を確認しつつ周波数やDuty比を変更しよう。今回は30分ほど試運転を行ったが、MOSFETの温度は室温と変わらなかった。上手く分散されているようだ。

ところで、今回は転がっていたM5StickC Plusを使用したので良いが、これを買おうとすると後継機のM5StickC Plus2が4200円程する。さらにほかの部品や持ってなければ半田ごても買わなければならないしプログラミングもある。わたしのような工作好きなら良いが、そうでない場合は苦痛だろう。

ということで調整可能なPWMモジュールを探してみた。LCDもついて周波数とDuty比も変更できる。これで900円弱だ。多少の配線は必要だがこれとMOSFETモジュールを組み合わせれば、今回行ったことが楽に実現できるだろう。デメリットは問題が起こっても自分で対処することが難しいことくらいだが、この値段なら買い換えればいい。ほかにも同様の機能を持つものがいくつかあるので、探してみてほしい。

さて、今回はここまで。後はミストだなぁ・・・。

コメント

タイトルとURLをコピーしました