So-net無料ブログ作成

CLIP DISPLAY(仮)のソフト開発難航中…(´・ω・`) [Arduino]

CLIP DISPLAY(仮)の電気系が完成したものの、肝心のソフトウェアがまだ完成途中。しかも、このタイミングで仕事が修羅場になってしまい、平日はほぼ時間がとれそうになく、とってもやばい状況。(´・ω・`)


DSC04218.JPG


ソフトで問題なのが、六軸センサーを用いた速度計。いろいろ実験した結果、センサーの加速度はオフセットはあるし、しかも値もあてにならない。ノイズを取りきってパラメータを調整するか、歩数計から速度計を作るか悩ましいところ。しかし、この時期に設計変更は非常に厳しい。うーん、どうしたものか・・・。
σ(-_-;)








心拍センサ

心拍センサ

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



ESP-WROOM-02ピッチ変換済みモジュール《フル版》

ESP-WROOM-02ピッチ変換済みモジュール《フル版》

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス




極小ESP-WROOM-02 に部品をとりつけてみた [Arduino]

CLIP DISPLAY のために作った極小 ESP-WROOM-02 それに部品をとりつけてみました。まず最初に MPU-6050 と電源ブロック+バッテリーを付けてみました。


DSC_0580.JPG


苦労しましたが、無事に動きました!これで基本的な部分は出来ました。これに心拍センサーとOLEDディスプレイをつければ電気系は完成です。

ということで、着けてみました!ケーブルにもポリウレタン銅線を使ってかなり細くなりました。


DSC_0582.JPG


一号機よりも小さくスタイリッシュになりました。いやー苦労した甲斐がありました。残すはソフトと息子担当の外装デザインのみとなりました。いよいよ最後の追い込みです!
(^_^)/~









心拍センサ

心拍センサ

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



ESP-WROOM-02ピッチ変換済みモジュール《シンプル版》

ESP-WROOM-02ピッチ変換済みモジュール《シンプル版》

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス




極小 ESP-WROOM-02 計画 [Arduino]

CLIP DISPLAYの再設計に着手し、Arduino Pro Mini から ESP-WROOM-02 にマイコンを変更しました。せっかく小さくなったので、小ささを追及することにしました。計画がこちら。


ESP-WROOM-02-Mini.png^; 


DSC_0568.JPG


下にあるのは、バッテリー接続用のコネクターと3.7V から 3.3V を生成するための LDO 、チップコンデンサー、スイッチが入っている電源ブロックです。この大きさでPCからスケッチを書き込むこともできます。我ながら小さくできました!
σ(^_^)

















CLIP DISPLAY(仮) の再設計にチャレンジ [Arduino]

MFT2016 に出展予定の CLIP DISPLAY(仮) の再検討をはじめました。


CLIPDISPLAY_1.jpg


今までは Arduino Pro Mini を使っていましたが、CLIP DISPLAY(仮) の全ての機能を盛り込むとメモリ不足になってしまいます。ということで、代わりのマイコンとして ESP-WROOM-02 を選択しました。

ESP-WROOM-02 のメモリと処理能力は Arduino Pro Mini とは比較にならないくらい高いです。(参考記事:http://makers-with-myson.blog.so-net.ne.jp/2016-04-13) また大きさも Arduino Pro Mini よりも小さく、文句ない選択です。


DSC04217.JPG


あと試作をしていて困ったのがケーブルです。意外と機内配線のケーブルが体積を占め、全てのパーツを納めるのに苦労しました。その体積をできるだけ小さくするために、ポリウレタン銅線を使うことにしました。いわゆるエナメル線です。



2UEW エナメル線 2種 ポリウレタン銅線 0.2mm 20m

2UEW エナメル線 2種 ポリウレタン銅線 0.2mm 20m

  • 出版社/メーカー: サンコー電商
  • メディア:




これは"はんだ付け"をすると表面のポリウレタンが溶けて結線でき、"はんだ"されていない部分は絶縁されたままという優れものです。何より、とにかく細いので省スペースで実装できそうです。

一番の悩みは電源。前回の試作はバッテリーを内蔵しましたが、これではバッテリ交換ができません。バッテリーは別モジュールにしようかと考えています。
( ̄_ ̄ )。o0





Arduino Pro Mini 328 3.3V 8MHz

Arduino Pro Mini 328 3.3V 8MHz

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



ESP-WROOM-02 Wi-Fiモジュール

ESP-WROOM-02 Wi-Fiモジュール

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



2UEW エナメル線 2種 ポリウレタン銅線 0.2mm 20m

2UEW エナメル線 2種 ポリウレタン銅線 0.2mm 20m

  • 出版社/メーカー: サンコー電商
  • メディア:



MPU6050 の Digital Motion Processor の性能を試してみた(5) [Arduino]

前回、MPU6050 のオフセットを解消するためのフィルターを考えてみました。今回はその性能を試してみたいと思います。


DSC04208.JPG


フィルターなしの場合は、動きを与えたあとにオフセットが発生していました。


MPU6050DMPnotConvergenceToZero2.png


今回、64サンプルのフィルターを使ってデータを取得してみました。センサーを左右に大きく振ってみました。


W64Filtered_accel.png


フィルターのおかげでオフセットはキャンセルされています。うまくいきました。このデータから速度のデータを算出してみました。


W64Filtered_speed.png


だいたい1.2m/sec。左右の振り幅は1mくらいなので、感覚的になんとなく合っています。次に距離を計算してみました。左右に大きく30回振りましたので、だいたい30m位のはずです。


W64Filtered_distance.png


悪くないデータになりましたが、静止状態でもずるずると距離が伸びてしまっています。加速度データの正負の値が一致していないので、差し引きで速度が残ってしまっています。これ位はしょうがないレベル?悩む。
(。-`ω´-)ンー





MPU-6050搭載三軸加速度三軸ジャイロセンサモジュール

MPU-6050搭載三軸加速度三軸ジャイロセンサモジュール

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



ESPr Developer(ESP-WROOM-02開発ボード)

ESPr Developer(ESP-WROOM-02開発ボード)

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス







MPU6050 の Digital Motion Processor の性能を試してみた(4) [Arduino]

前回の検討で、MPU6050をCalibrationをしてもオフセットが残ってしまう問題が残りました。何か解決策を考えなければなりません。


DSC04208.JPG


一般的なやり方は、センサーの出力値からローパスフィルターを使ってDC成分を得て除去するというもの。Android のページでも紹介されています。

SensorEvent
https://developer.android.com/reference/android/hardware/SensorEvent.html


具体的には下記のようなアルゴリズムです。

 // alpha は 0.5 ~ 0.8 で調整
 lpf_signal = alpha * x[i-1] + (1 - alpha) * x[i]; // low pass filter
 hpf_signal = x[i] - lpf_signal; // distill high pass value using low pass value


しかし、これを実際のセンサーの出力(10msec間隔)に適用すると、ローパスフィルタの値がセンサーの出力値とほぼ重なってしまい、正しい加速度が算出できません。(赤がローパスフィルターの波形で、その下に青のセンサーからの出力波形が隠れています)

general_lowpass_filter.png


理想的には数十サンプルの平均値をとるようなローパスフィルターを実現したいところです。でも配列はメモリを食うので使いたくないし・・・。

ということで、下記のようなアルゴリズムを考えてみました。


#include 
#include 
#include "I2Cdev.h"
#include "MPU6050DMP.h"
extern "C" {
#include "user_interface.h"
}

#define INT_PIN 4

MPU6050DMP mpu6050;
bool dmpReady = false;
uint16_t  packetSize = 0;

volatile bool mpuInterrupt = false;
void dmpDataReady() {
    mpuInterrupt = true;
}

unsigned long getCurrentTimeMS() {
  return ESP.getCycleCount() / 80000L;
}

void setup() {

  Wire.begin(12, 14);  
  Wire.setClock(400000);
  Serial.begin(115200);
  pinMode(INT_PIN, INPUT);
  WiFi.disconnect();
  WiFi.mode(WIFI_OFF);
  WiFi.forceSleepBegin();

  if (mpu6050.testConnection()) {
    Serial.println("MPU6050 OK");
    attachInterrupt(INT_PIN, dmpDataReady, RISING);
  } else {
    Serial.println("MPU6050 NG");
    return;
  }
  
  mpu6050.initialize();
  // offset values for my sensor
  mpu6050.setXAccelOffset(565);
  mpu6050.setYAccelOffset(-5);
  mpu6050.setZAccelOffset(1432);
  mpu6050.setXGyroOffset(17);
  mpu6050.setYGyroOffset(550);
  mpu6050.setZGyroOffset(464);

  Serial.println("");
  Serial.println("");

  if (mpu6050.dmpInitialize() == 0) {
    Serial.println("MPU6050DMP OK");
    mpu6050.setDMPEnabled(true); 
    packetSize = mpu6050.dmpGetFIFOPacketSize();
    dmpReady = true;    
  } else {
    Serial.println("MPU6050DMP NG");
  }
}

uint16_t fifoCount  = 0;
uint8_t  fifoBuffer[64];
unsigned long preTime = 0;

unsigned int loop_counter = 0;

#define WSIZE 16 // change this value for your purpose

long sum_x = 0;
long sum_y = 0;
long sum_z = 0;
int adj_x = 0;
int adj_y = 0;
int adj_z = 0;


void loop() {
  
  if (!dmpReady) return;
  
  while (!mpuInterrupt);
  mpuInterrupt = false;

  while (fifoCount < packetSize) {
    fifoCount = mpu6050.getFIFOCount();
  }
  
  uint8_t mpuIntStatus = mpu6050.getIntStatus();
  
  if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
    mpu6050.resetFIFO();
    return;
  } else if ((mpuIntStatus & 0x02) == false) {
    return;
  }
  
  mpu6050.getFIFOBytes(fifoBuffer, packetSize);
  fifoCount -= packetSize;

  unsigned long curTime = getCurrentTimeMS();
  unsigned long duration = curTime - preTime;

  Quaternion q;
  VectorInt16 aa;
  VectorInt16 aaReal;
  VectorFloat gravity;
  
  mpu6050.dmpGetQuaternion(&q, fifoBuffer);
  mpu6050.dmpGetAccel(&aa, fifoBuffer);
  mpu6050.dmpGetGravity(&gravity, &q);
  mpu6050.dmpGetLinearAccel(&aaReal, &aa, &gravity);
  
  if (loop_counter < 2000) {
    if (loop_counter % 80 == 0)
      Serial.println("");
    ++loop_counter;
    Serial.print(".");
    return;
  } else if (loop_counter < 2000 + WSIZE) {
    sum_x += aaReal.x;
    sum_y += aaReal.y;
    sum_z += aaReal.z;
    if (loop_counter % 80 == 0)
      Serial.println("");
    ++loop_counter;
    Serial.print("*");
    return;
  } else {
    adj_x = sum_x / WSIZE;
    adj_y = sum_y / WSIZE;
    adj_z = sum_z / WSIZE;
    
    sum_x = sum_x - adj_x + aaReal.x;
    sum_y = sum_y - adj_y + aaReal.y;
    sum_z = sum_z - adj_z + aaReal.z;  
    
    /* 
    // High-pass values
    aaReal.x -= adj_x;
    aaReal.y -= adj_y;
    aaReal.z -= adj_z; 
    */   
  }
  
  Serial.print("areal\t");
  Serial.print(aaReal.x);
  Serial.print("\t");
  Serial.print(aaReal.y);
  Serial.print("\t");
  Serial.print(aaReal.z);
  Serial.print("\t");
  Serial.print(adj_x);
  Serial.print("\t");
  Serial.print(adj_y);
  Serial.print("\t");
  Serial.print(adj_z);
  Serial.print("\t");
  Serial.print(duration);
  Serial.println("");
  preTime = curTime;
}



アイディアは単純です。指定サンプル分の積算値を保持しておき、そこから平均値を出します。計算が終わったら、積算値から平均値を一つ分を減算して、直近の得られた値を積算値に加えるというものです。

このアルゴリズム適用した結果を以下に示します。赤がサンプル数分の平均値で、青がセンサーからの出力です。なかなか良い感じのデータが得られました。


16サンプル平均
16ave_lowpass_filter.png


32サンプル平均
32ave_lowpass_filter.png


64サンプル平均
64ave_lowpass_filter.png


128サンプル平均
128ave_lowpass_filter.png


このフィルターの欠点はオリジナルの波形に対して少し位相が遅れてしまうところです。位相の遅延を最低限にしつつ加速度の値をとれそうなのは、64か32あたりかな・・・。

適正なサンプル数は速度や距離を実測して決めたいと思います。
(^^)





MPU-6050搭載三軸加速度三軸ジャイロセンサモジュール

MPU-6050搭載三軸加速度三軸ジャイロセンサモジュール

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



ESPr Developer(ESP-WROOM-02開発ボード)

ESPr Developer(ESP-WROOM-02開発ボード)

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス







MPU6050 の Digital Motion Processor の性能を試してみた(3) [Arduino]

引き続きMPU6050のDMPの性能テストです。前回までのテストで、MPU6050のDMP(Digital Motion Processor)は重力の影響を排除してくれることは分かりました。


DSC04208.JPG


問題はXYZ軸の加速度が静止状態でゼロでない値に収束してしまうことです。このままでは静止していても、計算上は、どんどん速度が上がってしまいます。


MPU6050DMPnotConvergenceToZero.png

Google師匠に聞いてみると、キャリブレーションが効果がありそうです。


Arduino Sketch to automatically calculate MPU6050 offsets
http://www.i2cdevlib.com/forums/topic/96-arduino-sketch-to-automatically-calculate-mpu6050-offsets/


ということで、上記サイトにあるキャリブレーション用のスケッチを試してみることにしてみました。


MPU6050_calibration_v1.1.zip


フォーラム中でも話題になっていましたが、このキャリブレーションスケッチ、一向に値が収束しません。仕方ないので収束条件を緩めるように変更しました。


int acel_deadzone=30;     //Acelerometer error allowed, make it lower to get more precision, but sketch may not converge  (default:8)
int giro_deadzone=5;     //Giro error allowed, make it lower to get more precision, but sketch may not converge  (default:1)



これでも値がなかなか収束しません。どうも、かなり厳密にセンサーを平行に保たないと収束しないようです。何度も試行錯誤して、ようやく結果が得られました。


XAccelOffset: 82
YAccelOffset: 333
ZAccelOffset: 1443
XGyroOffset: -3
YGyroOffset: 716
ZGyroOffset: 475
※センサーによって値はまったく異なるので注意してください。


実際に試してみると、確かに静止状態では前よりも収束していますが(これでも若干のオフセットがあります)、センサーに動きを与えると、また大きなオフセットが発生してしまいました。

MPU6050DMPnotConvergenceToZero2.png


これでは速度、距離を算出することはできません。どうやら、オフセットを除去するためのフィルターを考える必要がありそうです。
σ(。-`ω´-)






MPU-6050搭載三軸加速度三軸ジャイロセンサモジュール

MPU-6050搭載三軸加速度三軸ジャイロセンサモジュール

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



ESPr Developer(ESP-WROOM-02開発ボード)

ESPr Developer(ESP-WROOM-02開発ボード)

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



Arduino 9軸モーションシールド

Arduino 9軸モーションシールド

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス




MPU6050 の Digital Motion Processor の性能を試してみた(2) [Arduino]

引き続き MPU6050 の DMP の性能テストです。今回は斜めの状態で、DMPの値がどのように収束していくか試してみます。スケッチは前回使ったものと同じものです。

まず、左に傾けてみました。

DSC04209.JPG


平面の静止状態とあまり変わりません。すごいですね。

MPU6050_back_up.png


次に右に傾けてみました。

DSC04210.JPG


傾向は変わらないようです。

MPU6050_front_up.png


今度は手前に傾けてみました。

DSC04211.JPG


ここまで来ると想像通りの振る舞いですね。

MPU6050_left_up.png


せっかくなので、奥にも傾けてみましょう。

DSC04212.JPG


予想通りの結果です。

MPU6050_right_up.png


これで平行に置かなくても値は収束することが分かりました。しかし、若干オフセットがかかっているのが気になります。加速度では変化なくても、速度にするとどんどん加速もしくは減速してしまいます。

やっぱり、キャリブレーションは必要そうですね。チャレンジしてみますか・・・。
σ( ̄・ω・ ̄)





サインスマート(SainSmart) MPU-6050 3軸ジャイロスコープ モジュール for Arduino

サインスマート(SainSmart) MPU-6050 3軸ジャイロスコープ モジュール for Arduino

  • 出版社/メーカー: サインスマート(SainSmart)
  • メディア: エレクトロニクス



ESP-WROOM-02ピッチ変換済みモジュール《フル版》

ESP-WROOM-02ピッチ変換済みモジュール《フル版》

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



図解入門よくわかる最新センサーの基本と仕組み (How‐nual Visual Guide Book)

図解入門よくわかる最新センサーの基本と仕組み (How‐nual Visual Guide Book)

  • 作者: 高橋 隆雄
  • 出版社/メーカー: 秀和システム
  • 発売日: 2011/03/23
  • メディア: 単行本




MPU6050 の Digital Motion Processor の性能を試してみた(1) [Arduino]

MPU6050 ので速度と距離を測定するため、MPU6050 の Digital Motion Processor (DMP) がどの程度の精度が出るのか性能を測定をして見ることにしました。


DSC04208.JPG


DMPで取れる座標には REAL ACCEL とWORLD ACCEL の2種類あります。REAL ACCEL と WORLD ACCES の違いはこちらを参照してください。どちらがいいのか調べてみたら、下記のスレッドのやりとりで、WORLD ACCEL は精度が低いからやめろとありました。

MPU-6050 Accelerometer Calibration and DMP
http://www.i2cdevlib.com/forums/topic/75-mpu-6050-accelerometer-calibration-and-dmp/

ということで、静止状態でリセットした時の REAL ACCEL の出力データの様子を、下記のスケッチで試すことにしてみました。

#include <Wire.h>
#include "I2Cdev.h"
#include "MPU6050DMP.h"
extern "C" {
#include "user_interface.h"
}

#define INT_PIN 4

MPU6050DMP mpu6050;
bool dmpReady = false;
uint16_t  packetSize = 0;

volatile bool mpuInterrupt = false;
void dmpDataReady() {
    mpuInterrupt = true;
}

unsigned long getCurrentTimeMS() {
  return ESP.getCycleCount() / 80000L;
}

void setup() {

  Wire.begin(12, 14);  
  Wire.setClock(400000);
  Serial.begin(115200);
  pinMode(INT_PIN, INPUT);

  if (mpu6050.testConnection()) {
    Serial.println("MPU6050 OK");
    attachInterrupt(INT_PIN, dmpDataReady, RISING);
  } else {
    Serial.println("MPU6050 NG");
    return;
  }
  
  mpu6050.initialize();
  mpu6050.setXGyroOffset(220);
  mpu6050.setYGyroOffset(76);
  mpu6050.setZGyroOffset(-85);
  mpu6050.setZAccelOffset(1688);

  if (mpu6050.dmpInitialize() == 0) {
    Serial.println("MPU6050DMP OK");
    mpu6050.setDMPEnabled(true); 
    packetSize = mpu6050.dmpGetFIFOPacketSize();
    dmpReady = true;    
  } else {
    Serial.println("MPU6050DMP NG");
  }
}

uint16_t fifoCount  = 0;
uint8_t  fifoBuffer[64];
unsigned long preTime = 0;

void loop() {
  
  if (!dmpReady) return;
  
  while (!mpuInterrupt);
  mpuInterrupt = false;

  while (fifoCount < packetSize) {
    fifoCount = mpu6050.getFIFOCount();
  }
  
  uint8_t mpuIntStatus = mpu6050.getIntStatus();
  
  if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
    mpu6050.resetFIFO();
    return;
  } else if ((mpuIntStatus & 0x02) == false) {
    return;
  }
  
  mpu6050.getFIFOBytes(fifoBuffer, packetSize);
  fifoCount -= packetSize;

  unsigned long curTime = getCurrentTimeMS();
  unsigned long duration = curTime - preTime;

  Quaternion q;
  VectorInt16 aa;
  VectorInt16 aaReal;
  VectorFloat gravity;
  
  mpu6050.dmpGetQuaternion(&q, fifoBuffer);
  mpu6050.dmpGetAccel(&aa, fifoBuffer);
  mpu6050.dmpGetGravity(&gravity, &q);
  mpu6050.dmpGetLinearAccel(&aaReal, &aa, &gravity);
  Serial.print("areal\t");
  Serial.print(aaReal.x);
  Serial.print("\t");
  Serial.print(aaReal.y);
  Serial.print("\t");
  Serial.print(aaReal.z);
  Serial.print("\t");
  Serial.print(duration);
  Serial.println("");
  preTime = curTime;
}



4回データを測定をしてみました。縦軸の単位は G(9.8m/s^2) になります。0.5 は0.5G の意味です。


MPU6050DMP1.png

MPU6050DMP2.png

MPU6050DMP3.png

MPU6050DMP4.png


だいたいの傾向が見えてきました。データの間隔は10msecなので、17秒くらいで収束をしているようです。20秒静止していれば問題ないでしょう。

XYZ軸いずれもノイズ成分は Peak to Peak で 0.1G 程度あるようです。結構大きいですね。またZ軸(グレー)はオフセットがかかっているようなので調整が必要そうです。

次は斜め静止状態でどのようなデータが取れるか試してみたいと思います。
(^_^)/~









ESPr Developer(ESP-WROOM-02開発ボード)

ESPr Developer(ESP-WROOM-02開発ボード)

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



Make: Sensors: Projects and Experiments to Measure the World with Arduino and Raspberry Pi

Make: Sensors: Projects and Experiments to Measure the World with Arduino and Raspberry Pi

  • 作者: Tero Karvinen
  • 出版社/メーカー: Maker Media, Inc
  • 発売日: 2014/06/02
  • メディア: ペーパーバック




3Dプリンタを使ってディスプレイフォルダを設計 [3Dプリンター]

MFT2016に出展を予定している「CLIPDISPLAY(仮)」のディスプレイフォルダ。前回は文房具のクリップを流用した暫定デザイン。


CLIPDISPLAY_1.jpg


出展するには強度や見た目がいまいちなので、息子にデザインを依頼しました。どんなものが出てくるのか楽しみにしていたのですが、かなり大雑把なものが出てきました。


DisplayFolder.png


最初は強度や位置を見極めるためのものなのでこれで良いそうです。なるほど。

3Dプリンタで出力してみました。思ったよりも格好良くてびっくりしました。

DSC04205.JPG

DSC04206.JPG

DSC04207.JPG


帽子からディスプレイの支持棒がやや長いのと、ディスプレイが傾きが気になります。ケーブルもどう収めるか。それらが次の試作の課題となりそうです。

息子もだいぶメカ・エンジニアっぽくなってきました。すっかり逞しくなったなぁ。
(^_^)






最新版 DIY 3dプリンター prusa i4 prusa i3より高性能! フィラメントとSD付属

最新版 DIY 3dプリンター prusa i4 prusa i3より高性能! フィラメントとSD付属

  • 出版社/メーカー: prusa
  • メディア: エレクトロニクス



自宅ではじめるモノづくり超入門 ~ 3DプリンタとAutodesk 123D Designによる、新しい自宅製造業のはじめ方 ~

自宅ではじめるモノづくり超入門 ~ 3DプリンタとAutodesk 123D Designによる、新しい自宅製造業のはじめ方 ~

  • 作者: 水野 操
  • 出版社/メーカー: ソフトバンククリエイティブ
  • 発売日: 2013/05/28
  • メディア: 大型本