LoginSignup
6
0

More than 3 years have passed since last update.

DCモータのPWM制御により曲を演奏する(matlab+mbed)

Last updated at Posted at 2021-02-25

DCモーターのPWM制御を行うと、PWM周波数に従ってモーターから音が発生します。
これを利用して、モーターで音楽を演奏します。
mp3ファイルから読み込んだ音声を、FFTして周波数(時間変化する)に変換します。
得た周波数データを逐次マイコンに送信し、マイコンは受信したPWM周波数でモーターをPWM制御します。

以下のような感じです。
image.png

環境

  • matlab
  • マイコン:mbedLPC1768
  • モータドライバ:自作(Hブリッジ式)
  • モーター:マブチ rz-735

モータドライバは高い周波数に耐えられればなんでもいいんじゃないかな。
20 kHzくらいまで出せればオッケーなので、Pololuのやつなら何でもいいと思う。

matlabコード

matalab 2020以上でないとserialportが使えないので注意

読み込んだ音声ファイルを、区間NでFFTし、そのときの最大スペクトルを持つ周波数をモーターへの出力周波数としています。

image.png

port_name = 'COM26'; %COMポート
filename = 'hogehoge.mp3'; %音声ファイル名

[audio,Fs] = audioread(filename);
T = 1/Fs;
L = length(audio);
start_sec = 0.1;
start = round(start_sec / T);
step = 1000;
N = 1000;
input_list = zeros(1, start+L);

for i = start : step : start+L-N
    % stepずつ走査し,区間NでaudioをFFT
    y = audio(i : i+N);
    Y = fft(y(1:1+N));
    P2 = abs(Y/N);
    P1 = P2(1:N/2+1);
    P1(2:end-1) = 2*P1(2:end-1);
    f = Fs*(0:(N/2))/N;
    [~,I]=max(P1);
    Ma=f(I);
    input_list(i) = round(Ma);

    % テスト用に音声を再現
    t = [T*1 : T : T*N];
    Ma = round(Ma);
    output(i-start+1 : i-start+N) = sin(2*pi*Ma*t);
end

% スピーカーに音声を出力
% sound(output(start:L-N), Fs);

% mbedに送信
s = serialport(port_name, 9600);

for i = start : step : start+L-N
    h = bitshift(input_list(i), -16); %上位ビット
    m = bitshift(input_list(i), -8);  %中位ビット
    l = bitand(input_list(i), 255);   %下位ビット
    %送信
    write(s,h,"uint8");
    write(s,m,"uint8");
    write(s,l,"uint8");
    % 待機
    pause(T*step);
end
write(s,0,"uint8");
write(s,0,"uint8");
write(s,0,"uint8");
clear s;

mbedコード

以下のコードはコンパイル通らないので注意です。
MotorControlerクラスのところだけうまいこと書き換えてください。
シリアル通信のところはそのままで大丈夫です。
通信ずれると止まりますが、まあいいでしょう

#include "mbed.h"
#include "MotorControler.h"

int main()
{
    Serial matlab(USBTX, USBRX);
    MotorControler MOTOR(p21,p22,p23);
    MOTOR.setPwmFrequency(20000);
    MOTOR.enableDriver();
    MOTOR = 0.7;

    while(1)
    {
        if(matlab.readable() > 0)
        {
            int h = (int)matlab.getc();
            int m = (int)matlab.getc();
            int l = (int)matlab.getc();
            MOTOR.setPwmFrequency(h<<16 | m<<8 | l);
        }
    }
}

結果

ボッカデラベリタ
https://twitter.com/newlvAlPr/status/1363865660887998467

夜に駆ける
https://twitter.com/newlvAlPr/status/1364057845604343809

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0