DCモーターのPWM制御を行うと、PWM周波数に従ってモーターから音が発生します。
これを利用して、モーターで音楽を演奏します。
mp3ファイルから読み込んだ音声を、FFTして周波数(時間変化する)に変換します。
得た周波数データを逐次マイコンに送信し、マイコンは受信したPWM周波数でモーターをPWM制御します。
環境
- matlab
- マイコン:mbedLPC1768
- モータドライバ:自作(Hブリッジ式)
- モーター:マブチ rz-735
モータドライバは高い周波数に耐えられればなんでもいいんじゃないかな。
20 kHzくらいまで出せればオッケーなので、Pololuのやつなら何でもいいと思う。
matlabコード
matalab 2020以上でないとserialportが使えないので注意
読み込んだ音声ファイルを、区間NでFFTし、そのときの最大スペクトルを持つ周波数をモーターへの出力周波数としています。
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