pythonでFFTしてみた

便利な世の中になったもんだ。
参考にしたのは
org-technology.com
ism1000ch.hatenablog.com
など。
ソースは以下。

import numpy as np
from scipy.fftpack import fft
from scipy.fftpack import fftfreq
from scipy.fftpack import fftshift
import matplotlib.pyplot as plt
import pandas as pd

#データ数
N = 800   

#サンプリング周期(sec)
dt = 0.001

#周波数  
f = 5.0

#時間軸       
t = np.linspace(1,N,N) * dt - dt

#時系列データ
y = np.sin(2 * np.pi * f * t)

#周波数軸(MATLAB等で言うfftshiftがかかっている)
freq = fftfreq(N,dt)

#FFT
yf = fft(y)

plt.figure(1)
plt.xlabel("time(sec)")
plt.ylabel("value(a.u.)")
plt.plot(t,y)

plt.figure(2)
plt.xlabel("freq(Hz)")
plt.ylabel("amplitude(a.u.)")
plt.plot(freq,np.abs(yf))
#plt.plot(freq,np.real(yf)) #実部
#plt.plot(freq,np.imag(yf)) #虚部

print(np.real(yf))
plt.show()

df = pd.DataFrame(freq)
df.to_csv("freq.csv")


5Hzのsin波
f:id:ossannt:20170720231304p:plain

FFT結果(power)
f:id:ossannt:20170720231307p:plain

(C#)絶対に二重起動させない方法

毎回忘れるのでメモ。
この方法だと、絶対に二重起動しない。
Application.Run()がusingの中に入っているのがミソ。

[STAThread]
    static void Main() {
        using (Mutex mutex = new Mutex(false, "APP NAME")) {
            if (mutex.WaitOne(0, false) == false) {
                MessageBox.Show("二重起動はできません。", "APP NAME");
                return;
            }
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
            
    }

(BLE)WindowsでKonashiのアナログ入力を読む

ようやくできたよ・・・。
Windows 10のノートPCで動作確認。他は知らない。
ハマったポイントは、
characteristic.ReadValueAsync()メソッドが、デフォルトでキャッシュした値を返していたこと。
BluetoothCacheMode enumeration - Windows app development
にあるように、引数をunchachedにしたら、ちゃんと読めた。

以下ソース。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Popups;


namespace BreathMonitorKonashi {

    public sealed partial class MainPage : Page {

        private const string KONASHI_SERVICE = "229BFF00-03FB-40DA-98A7-B0DEF65C2D4B";
        private const string KONASHI_AIO0_CHARACTERISTIC = "229B3008-03FB-40DA-98A7-B0DEF65C2D4B";

        private GattDeviceService service;
        private GattCharacteristic characteristic;

        Timer timer;


        public MainPage() {
            this.InitializeComponent();
        }

        private async void btnConnect_Click(object sender, RoutedEventArgs e) {
            //デバイスを検索
            var selector = GattDeviceService.GetDeviceSelectorFromUuid(new Guid(KONASHI_SERVICE));
            var deviceInfomations = await DeviceInformation.FindAllAsync(selector);
            var deviceInfomation = deviceInfomations.FirstOrDefault();
            if (deviceInfomation != null) {
                //サービス取得
                this.service = await GattDeviceService.FromIdAsync(deviceInfomation.Id);

                //キャラクタリスティック取得
                var characteristics = this.service.GetCharacteristics(new Guid(KONASHI_AIO0_CHARACTERISTIC));
                if (characteristics.Count > 0) {
                    this.characteristic = characteristics.First();
                    
                    var dialog = new MessageDialog("Connected to " + deviceInfomation.Name);
                    await dialog.ShowAsync();

                    //ADC読み取りスレッド開始
                    TimerCallback timerDelegate = new TimerCallback(onTimer);
                    timer = new Timer(timerDelegate, null, 0, 100);
                }
            }
        }


        private async void onTimer(object sender) {
            if (characteristic == null) {
                return ;
            }
            
            var result = await characteristic.ReadValueAsync(BluetoothCacheMode.Uncached);  //キャッシュしてやがった!
            byte[] value = result.Value.ToArray();
            
            int val = (value[0] << 8) + value[1];   //[0]番目に上位バイト、[1]番目に下位バイト
            System.Diagnostics.Debug.WriteLine(val);

            lastVal = val;
            
        }


    }
}

(UWP)プロジェクト作成でコケるときのおまじない

いろいろ調べたけど、おまじないで逃げることにする。

プロジェクト作成したら、パッケージマネージャで、

PM> Install-Package Microsoft.NETCore.UniversalWindowsPlatform

を実行。

(Java,Android)twitter4jで最新のユーザータイムライン1つだけ取得する

題記の通り。
これで、5秒に1回の頻度(?)で監視できる。

Paging paging = new Paging();
paging.setCount(1); //1個に指定
List<twitter4j.Status> statuses =twitter.getUserTimeline("ユーザ名", paging);
final Status status = statuses.get(0);
Log.d("twitter4j", status.getUser().getScreenName() + " - " + status.getText());

【HTML】mmenuで右からスライドメニューを出す【javascript】

ちゃんとリファレンス読みましょう>俺

デモを見てたら、scriptはこう書く模様。

jQuery(document).ready(function( $ ) {
    $("#menu").mmenu({
        "offCanvas": {
            "position": "right"
        }
    });
});

(ToCoStick)Node.jsでシリアル通信してブラウザでグラフ表示(ccchart)

Node.jsのお勉強が必要になり、ひと段落したからメモ。

TWE-Liteから33msecごとにデータが送られてくると想定。
アナログ入力1の値を読み取り、wsモジュールを使ってccchartに送る。

以下、ソース。

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=480">
<title>TWE-Lite Monitor by ccchart</title>
</head>
<body>

<script src="ccchart-min.js" charset="utf-8"></script>

<canvas id="hoge"></canvas>
<script>

var chartdata = {
	"config": {
		"width": (window.innerWidth-60) ,
		"height": (window.innerHeight-60)/1.2,
		"lineWidth": 2,
		"xScaleSkip": 33,
		"useVal": "no",
		"bg": "#000",
		"colorSet": ["#00FF00",],
		"maxY": 2000,
		"minY": 0,
		"maxWsColLen": 333
  },

  "data": [
    ["時間"],
    ["電圧"]
  ]
};

ccchart
  .init('hoge', chartdata)
  .ws('ws://127.0.0.1:3001')
  .on('message', ccchart.wscase.someColsAtATime);

</script>


</body>
</html>

ccchartTest.js

var WsServer = require('ws').Server;
var ws = new WsServer({port : 3001});
var express = require('express');
var serialport = require('serialport');

const ARRAY_NUM = 333;
var dataArr = new Array(ARRAY_NUM);
var time = 0;	//in msec

clearArray();
function clearArray(){
	var now = new Date();
	var hour = ZeroFormat(now.getHours(),2);
	var min = ZeroFormat(now.getMinutes(),2);
	var sec = ZeroFormat(now.getSeconds(),2);
	var nowStr = hour + ":" + min + ":" + sec;
	
	for(i = 0;i < ARRAY_NUM;i++){
		dataArr.push([[nowStr],[1000.0]]);
	}
	//console.log(dataArr);
}

broadcast();
function broadcast(volt){
	var tid = setInterval( function(){
		ws.clients.forEach(function(client){
			client.send(JSON.stringify(dataArr));
//			console.log(dataArr);
			
		});
	}, 100);	//100msec毎に送信
}



var portName = 'COM3';
var sp = new serialport.SerialPort(portName,{
	baudRate: 115200,
	dataBits: 8,
	parity: 'none',
	stopBits: 1,
	flowControl: false,
	//parser: '\n'//serialport.parsers.readLine("\n");
});

sp.on('open', function(){
	console.log('serial port open');
})
sp.on('data',function(input){
	var inBuffer = new Buffer(input, 'ascii');

	if(inBuffer.length < 49){
		return;
	}
	
	var inStr = inBuffer.toString('ascii',37,39);
	var volt = 1.0 * (parseInt(inStr,16) * 16);	//10進に変換,16倍して電圧にも変換,1.0倍してfloatに変換
//	console.log(volt);
	addData(volt);
	
});

function addData(volt){
	var now = new Date();
	var hour = ZeroFormat(now.getHours(),2);
	var min = ZeroFormat(now.getMinutes(),2);
	var sec = ZeroFormat(now.getSeconds(),2);
	var nowStr = hour + ":" + min + ":" + sec;

	dataArr.shift();	//最初の要素を取り除いて、
	dataArr.push([[nowStr],[volt]]);	//push
}

/**
 * [関数名] ZeroFormat
 * [機 能] ゼロ埋め
 * [説 明] 数値が指定した桁数になるまで数値の先頭をゼロで埋める
 *
 * @param  integer num    数値
 * @param  integer max    桁数
 * @return integer tmpS   ゼロ埋め後の数値
 */
function ZeroFormat(num,max){
    var tmp=""+num;
    while(tmp.length<max){
        tmp="0"+tmp;
    }
    return tmp;
}

ZeroFormat関数は
http://phpjavascriptroom.com/exp.php?f=include/js/formcheck/zero2.inc&ttl=%E6%95%B0%E5%80%A4%E3%81%AE%E5%85%88%E9%A0%AD%E3%82%92%E3%82%BC%E3%83%AD%E3%81%A7%E5%9F%8B%E3%82%81%E3%82%8B
を使わせて頂きました。