USBマイクの音量をリアルタイムプロットする on raspberry pi 2 B

1秒間の入力データをダウンサンプリングしてRMS値を算出しコンソールに出力。
これを100秒繰り返し、その配列データをMatplotにて出力した。
Matplotの上のグラフが100秒間の音量に相当し、下のグラフが最後の1秒入力のダウンサンプリングした配列のグラフ。

RMSでの音量算出は、相対的に高い音は音量が低く、低い音は音量が高く出るような気がした。
周波数に依存するのかな?この辺りを突き詰めてみると面白いかもしれない。

実は、イビキ検知判定システムを作ろうとしているのです。
なんかイビキの周波数とかでなんかありそうやないっすか。



import numpy as np
import threading
import pyaudio
import threading
import matplotlib.pyplot as plt

class plotSound:
    def __init__(self):
        self.chunk = 1024
        self.FORMAT = pyaudio.paInt16
        self.CHANNELS = 1
        #サンプリングレート、マイク性能に依存
        self.RATE = 16000
        self.RECORD_SECONDS = 1
        #pyaudio
        self.audio = pyaudio.PyAudio()
        #plot time
        self.plottime = 100
        self.loopcounter = 0
        self.data_rms = []

        while True:
            
            #マイクからデータ取得
            self.stream = self.audio.open(  format = self.FORMAT,
                                        channels = self.CHANNELS,
                                        rate = self.RATE,
                                        input = True,
                                        frames_per_buffer = self.chunk)
            
            self.all = []
            for i in range(0, self.RATE / self.chunk * self.RECORD_SECONDS):
                self.data = self.stream.read(self.chunk)
                self.all.append(self.data)
                
            self.data = ''.join(self.all)
            self.data=np.frombuffer(self.data, dtype="int16")

            #converting numpy-type-array
            self.np_data=np.array(self.data, dtype = np.float64)

            #downsampling    
            self.overhang = len(self.np_data) % 100
            self.down_data=self.np_data[:-self.overhang]
            self.down_data=np.reshape(self.down_data, (len(self.down_data)/100,100))
            self.down_data=np.average(self.down_data, 1)

            #RMS calculation
            self.rms=np.sqrt(np.mean(np.square(self.down_data)))
            print self.rms
            self.data_rms.append(self.rms)
           
            self.stream.close()
            self.loopcounter = self.loopcounter + 1
            if self.loopcounter == self.plottime : break 

        plt.subplot(2,1,1)
        plt.plot(self.data_rms)
        plt.subplot(2,1,2)
        plt.plot(self.down_data)
        plt.show()

if __name__ == '__main__':
    plot=plotSound()
    


f:id:iroha112233:20160324231806j:plain


pythonリアルタイムプロット

Realtime FFT Graph of Audio WAV File or Microphone Input with Python, Scipy, and WCKgraph » SWHarden.com

Realtime FFT Audio Visualization with Python » SWHarden.com

音声データをMatplotでグラフ表示する on raspberry pi 2 B

raspberry pi 2 B へのmatplotのインストール

 

sudo apt-get install python-matplotlib

sudo apt-get install python-pip

sudo pip install drawnow

 

pythonを使用してプロットテスト↓

import numpy as np

import matplotlib.pyplot as plt

 

x=np.arange(-3, 3, 0.1)

y=np.sin(x)

plt.plot(x,y)

plt.show()

 

分割してRAWデータとローパスフィルタをかけたデータをプロット

 

 

# This program can plot sound data as graphs on matplot 

 

import pyaudio

import sys

import time

import wave

from numpy import *

import numpy as np

import matplotlib.pyplot as plt

import os

 

if __name__ == '__main__':

    chunk = 1024

    FORMAT = pyaudio.paInt16

    CHANNELS = 1

    #サンプリングレート、マイク性能に依存

    RATE = 16000

    #録音時間

    RECORD_SECONDS = input('Please input recoding time>>>'

    #pyaudio

    p = pyaudio.PyAudio()

 

    #マイク0番を設定

    input_device_index = 0

    #マイクからデータ取得

    stream = p.open(format = FORMAT,

                    channels = CHANNELS,

                    rate = RATE,

                    input = True,

                    frames_per_buffer = chunk)

    all =

    for i in range(0, RATE / chunk * RECORD_SECONDS):

        data = stream.read(chunk)

        all.append(data)

 

    stream.close()    

    data = ''.join(all)

    data=frombuffer(data, dtype="int16")/32768.0

    print data

    

    #Lowpass filter

    tap = 100

    aftlowpass_data =

    i = 0

    j = 0

    for i in range(0, len(data)-tap):

        sum_data = 0

        for j in range(0, 99):

            sum_data = sum_data + data[i + j]

        aftlowpass_data.append(sum_data / tap)

 

    #converting numpy-type-array

    np_data=np.array(data, dtype = np.float64)

    np_aftlowpass_data=np.array(aftlowpass_data, dtype = np.float64)

    

    #data plot

    plt.subplot(2,1,1)

    plt.plot(np_data)

    plt.subplot(2,1,2)

    plt.plot(np_aftlowpass_data)

    plt.show()

 

 

    

    p.terminate()

 

 

f:id:iroha112233:20160319112058j:plain

 

 

参考 

・スレッドによるタイマー

一定時間毎の繰り返し

Python スレッドをやってみる(3) | BTY備忘録

 

・numpy配列の作成・型変換

標準python、numpy、pandasを行ったり来たりするために① - Qiita

 

・matlibのインストール

Install numpy, matplotlib and drawnow for Python 2 - YouTube

 

・matplotの使い方

matplotlib入門 - りんごがでている

raspberry piを用いたリアルタイム音声処理の準備

忘備録としてraspberry piを使用した音声のリアルタイム処理に関するサイトを記しておく。

 

VNC経由でidleが起動できない場合の対処法

python - tkinter through VNC without physical display - Stack Overflow

 

Write these few lines to etc/sudoers*:

Defaults    env_reset
Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults    env_keep += "DISPLAY"
Defaults    env_keep += "XAUTHORITY"

And these few lines to ~/.bashrc:

if [ -z "$XAUTHORITY" ]; then
    if [ -e $HOME/.Xauthority ]; then
        export XAUTHORITY=$HOME/.Xauthority;
    fi;
fi

 

・USBマイクを使用した音声処理の環境構築

Raspberry Piで音声認識 - Qiita

 オーディオモジュールの優先順位の変更

 

raspberryPi と pyaudioで録音、音声波形処理 | 半端工作

録音用ファイルのサンプリング数を16000Hzとする。

 

PyAudioによる音声リアルタイム処理

pyqtgraph+PyAudioによるリアルタイムで音声プロット - たけし備忘録

 

 

ArduinoによるPWM制御およびアナログ信号のシリアル通信による受信

win32apiってすごいですよね。

2001年に販売された本をまだ現役で使っています。

いつまでサポートされるんだろう?

今はwindows 8を使用していますが、自分が趣味で使用する範囲ではバリバリ動く。

新しいAPIを覚えるのはめんどくさいからなくならないでほしいな。

 

さて、そんなwin32apiを使用して、データのArduinoへ送信しPWM制御とアナログ信号の受信を行いました。 スレッドを使って、ボタン入力からデータの受信と送信を行います。 

f:id:iroha112233:20151021224702j:plain

↑コンソール側制御GUI

 

 //コンソール側のプログラムの一部

//MainClass内のデータ制御用スレッドの作成

DWORD WINAPI ThreadFunc(LPVOID vdParam)
{
MSG ThredFuncMsg;
bool Flag = TRUE;//無限ループを抜けるためのフラグ


ArduinoDrawing *deg2 = new ArduinoDrawing();//Arduino制御用クラスのインスタンス
HDC hdc = GetDC((HWND)vdParam);


while (Flag)
{
PeekMessage(&ThredFuncMsg, NULL, 0, 0, PM_REMOVE);//メッセージ確認およびキューからの削除
switch (ThredFuncMsg.message) {
case WM_SURE_TEST1://■ボタンが押されたらループから抜ける
{
Flag = FALSE;
break;
}
case WM_SURE_TEST2://speedupボタンが押されたら1を送信
{
deg2->SendingControl(1); //()内は送信用データ
PostThreadMessage(dwID, WM_SURE_TEST4, 0, 0);
break;
}
case WM_SURE_TEST3://speeddownボタンが押されたら2を送信
{
deg2->SendingControl(2); //()内は送信用データ
PostThreadMessage(dwID, WM_SURE_TEST4, 0, 0);
break;
}
case WM_SURE_TEST4://アナログデータの受信
{
deg2->TxMain((HWND)vdParam, hdc);
PostThreadMessage(dwID, WM_SURE_TEST4, 0, 0);
break;
}

default://三角ボタンが押されたらアナログデータの受信を開始。
{
deg2->TxMain((HWND)vdParam, hdc);
break;
}
}
}

ReleaseDC((HWND)vdParam, hdc);
//delete deg2; // <- ここでdeleteするとヒープ破壊のエラーが生じてしまう。どしよ・・・。

ExitThread(0);
}

 

Arduinoプログラム

/*

This code is used for rover program to control arduino 
2015/10/21
*/
const int LED = 11;
int incomingByte = 0; // for incoming serial data
int roverSpeed = 128;

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
}

void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);

// print out the value you read:
Serial.print(sensorValue);
Serial.print('\0');



if (Serial.available() > 0) {
incomingByte = Serial.read();
if(incomingByte == 1){
roverSpeed = roverSpeed + 16;
if(roverSpeed > 255) roverSpeed = 255;
analogWrite(LED,roverSpeed);
}

if(incomingByte == 2){
roverSpeed = roverSpeed - 16;
if(roverSpeed < 0) roverSpeed = 0;
analogWrite(LED,roverSpeed);
}
}

delay(100); // delay in between reads for stability
}

 

コンソールから1が入力された場合、16/256スピードアップ

コンソールから2が入力された場合、16/256スピードダウン

実験結果が下の写真になります。

DCモーターの代わりにLEDを使用し、ADC入力は圧力センサを接続しています。

コンソールGUIに表示されている内容が、ADC出力です。

SPEED UPボタンを押す度に光量が大きくなっていることがわかります。

あとはこれをモーターに変えれば良いハズ・・・。

 

 

f:id:iroha112233:20151021224713j:plain

f:id:iroha112233:20151021224717j:plain

f:id:iroha112233:20151021224707j:plain

~参考~

・web

http://monitorgazer.blogspot.jp/2013/06/carduinoled.html

http://www.japanese-makers.com/archives/157

・書籍

Win32 API 完璧マスタ

制御用GUI作成その1

ウニモグPWM制御の前に、PC側のコンソールGUIを作成してみました。

f:id:iroha112233:20151013233331j:plain

作成はVisiual Studio 2013にてWin32apiを使用。

再生ボタンアイコンがローバーのスイッチオンボタン。

停止ボタンアイコンがローバーのスイッチオフボタン。

ローバーが進んでいるうちにスピードアップボタンもしくはスピードダウンボタンを押すと、モーターのRPMが変化するという構想。

いろいろパラメタ設定できるように、メニューバーにFileとかEditとかおいてみた。

ソースコードはある程度完成したら乗っけてみます。適当に作っているので回りくどいコードになっているかもしれません。

 

【参考】

・ボタン作成

http://wisdom.sakura.ne.jp/system/winapi/win32/win51.html

DCモータ制御その1

とりあえず、DCモーターを制御できんと始まらんという事で、

トランジスタ技術の↓の記事を参考にしつつ

http://toragi.cqpub.co.jp/Portals/0/backnumber/2006/10/p103-104.pdf

 

簡単な回路図を...

f:id:iroha112233:20151012215228j:plain

モーター間のダイオードはサージ保護用らしいです。

 

ここで活躍してもらうのは、大昔に買ったメルセデツベンツウニモグ君1/35。

まずはこいつにArduinoのっけて制御しようと思う。

f:id:iroha112233:20151012215215j:plain

 

回路図から組んだ回路は下記。

手元にあったN型MOS FET。高電流が流せるタイプ。

Arduinoからはサンプルプログラムをそのまま流用してゲートにパルスを印加。

f:id:iroha112233:20151012215236j:plain

ちゃんと動いてテスト終了。

 

次は、PWMでモータを制御したいと思う。

その後、ウニモグ君にArduinoのっけて無線で加速の制御の予定。

構想その1

暇だったのでネットサーフィンをしていたら、こんなサイトを見つけてしまった…。

 

吉野のロボット

http://www2.plala.or.jp/k_y_yoshino/w7/w7_top.html

 

めちゃめちゃカッコイイ...。

そこで自分でも作ってみたいなと。最近仕事も暇だし。

手元にはArduino、Raspberry Pi、Xbeespartan 6 FPGA評価ボード、オシロetc...

これは、コレまで集めたガジェッツをフル活用できるのではないかと直感。

折角なんで、これからのトライアンドエラーを記録に残します。

 

***目標***

・火星のローバーみたいなやつ。

・自分で判断しながら動く(障害物を避けつつテキトーに進んでいく)

・もちろん制御用PCからも制御可能

・分析結果を送信(搭載した各種センサの情報を制御用PCに送信)

********

 

まあ、こんなかんじかな。

 

イメージとしては、windowsマシンからxbeeで無線通信にてローバーを制御・観測。

ローバーの処理系はraspberry Piをメインにして組む。

画像処理なんかはFPGAボード使いたいな〜。

 

センシングはカメラモジュール、距離観測用の超音波センサ、これビームフォーミングとかできたら面白そう。でも機械的な回転が楽だろうな。GPSセンサ、地質分析用のセンサとかできるかな。

まあ、数年がかり計画ぐらいで、気長に作っていこう。趣味だし。

果たして完成するかどうか・・・。