もよいめも

不定期更新ものづくりブログ

【Arduino】Arduinoでステッピングモーターを回してみた

今回はステッピングモーターを入手したのでArduinoで制御してみようと思います。

モータードライバー

Arduino単体では制御できないのでモータードライバー↓をポチりました。

5個もいらないですがまあしょうがないです。
ちなみに制御できるステッピングモーターは2相4線の物オンリーなのでご注意ください。
また、今回使ったステッピングモーターは1ステップ1.8度で一回転200ステップのものを使いました。

つなぎ方

テスターでステッピングモーターの線を調べて内部でつながっている物同士を
モータードライバーのそれぞれ右左につなげます。
f:id:moyoi:20190519114446j:plain

そして以下の通りにAdruinoに接続します。
A-1B - D8
A-1A - D9
GND - GND
VCC - VIN
B-1B - D10
B-1A - D11

動かす

Arduino IDEには初めからステッピングモーターを制御するライブラリが入っているのでそれを使います
使うプログラムは以下↓の通りです。
f:id:moyoi:20190516082104p:plain


このプログラムをマイコンに書き込むと0.5 秒ごとにステッピングモーターが少し回転します。

このプログラムをもとに、必要な角度までステッピングモーターを回すプログラムを作りました。

#include <Stepper.h>//ライブラリをインクルード

Stepper stepper(200, 8, 9, 10, 11); //(モーターのステップ数、ピン1、ピン2、ピン3、ピン4)

void setup() {
}

void stepperMotor(int d, int s) {//関数を作成
  int k = map(d, -360, 360, -200, 200);
  if (k < 0) {
    for (k; k <= 0; k++) {
      stepper.step(-1);
      delay(s);
    }
  } else {
    for (k; k >= 0; k--) {
      stepper.step(1);
      delay(s);
    }
  }
}

void loop() {
  stepperMotor(360,10);//360度まで1ms秒ずつ1.8度動かす(何度回すか、何msごとに1ステップ動かすか)
  delay(1000);
  stepperMotor(-360,10);//-360度まで1ms秒ずつ-1.8度動かす(ちなみにスピードを2ms未満にすると回らないので注意)
  delay(1000);
}

動作の様子↓

Arduinoでステッピングモータを動かす
すごくうるさいです。もしかしたら何か間違っているのかも…
あとドライバーがかなり熱くなるのでヒートシンク等をつけたほうがいいかもしれませんね。

ステッピングモーターは何となく難しそうで手を付けていませんでしたが、実際にやってみると意外とすんなりできてしまいました。
何事も挑戦が大切ですね。

流れるLED(WS2812B)をArduinoで制御してみた

流れるテープLEDって知ってますか?
名前の通り、LEDが流れるように順番に点灯していくテープLEDです。

どんな仕組みになっているのか気になっていたんですが、どうやら
LED1つ1つにICが入っていてそれが数珠つなぎになっているようです。

という事で今回はそんなIC「WS2812B」が搭載されたLEDのリングをポチったので紹介します。

買ったLED

今回はAmazonですぐに届くこちらの商品↓を購入しました。

ちょっと高いですがRGBLEDなのでしょうがないですかね。

準備

まずははんだ付けして線をはやします。
基板の後ろの「IN、VCC、GND」から3本の線をはやします。
たくさんのLEDが信号線一本で制御でできてしまうので楽ですね~

テープ状の場合も方向があるので気をつけください。
f:id:moyoi:20190914081125j:plain

配線

GND-GND
VCC-VIN
IN-D6

光らせる

まずはライブラリを入れます。
以下のようにライブラリの管理ウィンドウを開きます。
f:id:moyoi:20190517082726p:plain
開けたら他のライブラリの更新が行われるので少し待ってから検索欄に「NeoPixel」と入れます
そして多分上から3番目の「Adafruit_NeoPixel」を左下のインストールボタンを押してインストールします。
f:id:moyoi:20190517082855p:plain
そしたらIDEを再起動して完了です。

プログラム

このライブラリーにはいろいろな関数がありなかなか面倒なので、
今回は基本だけ紹介させていただきます。
(ライブラリーのサンプルプログラムから色々な光り方を試せます。)

#include <Adafruit_NeoPixel.h>

#define PIN 6 //LEDの信号線をつなぐマイコンのピン番号
#define STRIP_COUNT 12 //つなぐLEDの数

Adafruit_NeoPixel strip = Adafruit_NeoPixel(STRIP_COUNT, PIN, NEO_GRB + NEO_KHZ800); //あれこれ初期設定

void setup() {
  strip.begin();
}

void loop() {
  for (int i = 0; i <= STRIP_COUNT; i++) {
    strip.setPixelColor(i, strip.Color(0, 0, 255)); //先ほど初期設定した名前.setPixelColor(設定するLEDの番号, strip.Color(緑の強さ, 赤の強さ, 青の強さ)); ちなみにこの場合は青を最大の明るさで点灯
    strip.show(); //LEDの設定を反映
    delay(30);
    strip.setPixelColor(i, strip.Color(0, 0, 0)); //青を消灯
  }
}

といった感じで、初期設定をして設定するLEDの番号を指定して光らせる色を設定して反映させるだけです。簡単ですね。

まあ、この記事は急いで書いたのでもしかすると色々追加していくかもしれません。

それでは良きArduinoライフを~

OpenCVのトラッキング方法「GOTURN」を試す方法

どうもこんにちは
最近画像認識をはじめてOpenCVでトラッキングとかをさせてるんですけどそのトラッキングの方法の一つである
「GOTURN」のやり方がちょっと大変だったので書いておきます。

ファイルをダウンロードして展開

下のページからデータをZIP形式でダウンロードします。
github.com

ダウンロードが終わったらファイルを展開してください。
ファイルの中身はこんな感じ。
f:id:moyoi:20190429152437j:plain

ZIPファイルを統合

先ほどのファイル内に「goturn.caffemodel.zip.001」などが4つありますが
このままだと使えないのでファイルを統合します。

まずは
「goturn.caffemodel.zip.001」
「goturn.caffemodel.zip.002」
「goturn.caffemodel.zip.003」
「goturn.caffemodel.zip.004」
の四つのファイルを
こちらのサイトを参考に統合してください
etc-log.jugem.jp

統合が終わったらまたまたそのファイルを解凍してください。

ファイルをつっこむ

GOTURNのトラッキングをさせたいプログラムの直下に
先ほど統合・解凍した「goturn.caffemodel」と
最初に回答したファイル内に入っていた「goturn.prototxt」
をつっこみます。
f:id:moyoi:20190429153517j:plain

これでトラッキング方法「GOTURN」ができるようになると思います。

Spyderをアップデートする

Spyderのアップデートが来たのでアップデートします。
だだそれだけ
f:id:moyoi:20190429145011j:plain

なお、私はSpyderをAnaconda経由で入れました

アップデート方法

1「Anaconda Promptを起動」

2「Anaconda全体を更新」

このコマンドを入力します

conda update anaconda

3「Spyderを更新」

このコマンドを入力します

pip install --upgrade spyder

以上です。ありがとうございました。

おまけ

import cv2
import numpy as np
import time
import random

#テキスト表示関数の宣言
def i_print(str1,x,y,size,color):
    cv2.putText(img, str1, (x, y), cv2.FONT_HERSHEY_SIMPLEX,size, color, size, cv2.LINE_AA)

capture = cv2.VideoCapture(0)#ウェブカメラと通信を開始する(個々の番号でカメラが変わる)
camera_opened = capture.isOpened()

#変数宣言
stert=0
state=0
num = random.randint(0, 2)
pat=["GUU","CHOKI","PAA"]

while camera_opened:#カメラが起動したら
    ret, img = capture.read()#ウェブカメラから1フレームを読み込む
    
    #各画像処理
    hsvim = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    lower = np.array([0, 48, 80], dtype = "uint8")
    upper = np.array([20, 255, 255], dtype = "uint8")
    skinRegionHSV = cv2.inRange(hsvim, lower, upper)
    blurred = cv2.blur(skinRegionHSV, (2,2))
    ret,thresh = cv2.threshold(blurred,0,255,cv2.THRESH_BINARY)
    
    #輪郭線の取得
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    contours = max(contours, key=lambda x: cv2.contourArea(x))
    
    #輪郭線を描画
    hull = cv2.convexHull(contours)
    cv2.drawContours(img, [hull], -1, (0, 255, 255), 2)
    
    #輪郭線を囲む長方形のサイズを取得
    rect = cv2.minAreaRect(contours)
    (cx, cy), (width, height), angle = rect
    wariai=int(abs(width-height))
    
    i_print(str(int(width))+','+str(int(height))+','+str(wariai),0,25,1,(255,0,0))
    
    #現在の手の状態を判定
    if wariai>100:
        state=1
    elif height<300 and width<300:
        state=0
    else :
        state=2
    i_print(pat[state],0,50,1,(255,0,0)) 
    
    #Sキーの押下を待機
    if cv2.waitKey(33) ==ord('s'):
        stert=2
        time_sta = time.time()
    time_end = time.time()
    
    #カウントダウン、勝負結果等の表示
    if stert>=1:
        if time_end- time_sta >10:
            stert=0
            i_print("Press S to start",50,250,2,(255,0,0)) 
        if time_end- time_sta >4 and stert==1:
            i_print(str(pat[num]),250,150,2,(0,0,255)) 
            if num==state:
                i_print("AIKO",200,250,3,(0,255,0)) 
            elif state == 0 and num == 1 or state == 1 and num == 2 or state == 2 and num == 0:
                i_print("YOU WIN",100,250,3,(0,0,255)) 
            else :
                i_print("YOU LOSE",100,250,3,(255,0,0)) 
        elif time_end- time_sta >4:
            random.seed()
            num = random.randint(0, 2)
            stert=1
        elif time_end- time_sta >1:
            i_print(str(4-int(time_end- time_sta)),250,250,5,(0,0,255)) 
        else :
            i_print("START",100,250,5,(0,0,255)) 
    else :
        i_print("Press S to start",50,250,2,(255,0,0))   
        
        
    i_print("Press ESC to close",0,475,1,(255,0,0)) 
    #画面更新
    cv2.imshow("KAMERA DE JYANKEN", img)
    
    #ESCキーで終了
    if cv2.waitKey(33) ==27:
        break
capture.release()
cv2.destroyAllWindows()

BF5はプレイを始めるまでが戦いだった

さて、先日RTX2060を購入し、NVIDIAのキャンペーンで念願のバトルフィールド5を無料でゲットすることができました。

しかし

いざ遊ぼうと思うと色々問題が発生し、遊び始めるのに半日かかってしまったので、今回はもうそんな人がいなくなることを願い、そのことについて書いていこうと思います。

インストールが完了しない

ゲームをダウンロードするためにまずOriginをインストールする必要があります。
まあこれは何の問題もなかったです。
しかし問題はここから・・
BF5はデータを23%までダウンロードすることでシングルプレイのストリーモードがプレイできるようになるのですが、なぜかゲームが起動できない。というかエラーを吐いてダウンロードが止まってしまう。

エラーの内容は「VC++ runtime redistributable package が正しくインストールされていません。セットアップを続行できません。(1601)」というもの

結果的に言うとvisual studioの「C++によるゲーム開発」というワークロードをインストールするとできました。

直し方

1.visualstudioのツールから「ツールと機能を取得」を選択
f:id:moyoi:20190417064336p:plain

2.「C++によるゲーム開発」を選択してインストール
f:id:moyoi:20190417064340j:plain

3.再起動で完了

その解決策にたどり着いた経緯ですが、
まず出てきたエラーをそのまま検索してみて出てきたこちら↓の公式の解決法
https://help.ea.com/ja-jp/help/origin/origin/your-vc-runtime-package-has-not-installed-correctly-error-troubleshooting/
を試しましたが解決せず
いろいろ考えた末、visual studioC++ が関係しているっぽかったのでとりあえず「C++によるゲーム開発」をインストールしたら解決したという感じです。
ダメもとでやったのですが、まさかの正解で驚きました。

起動はしたけど…

さて、無事ゲームのダウンロードが完了していざゲームを起動してみると・・・

あれれ?
f:id:moyoi:20190417063758p:plain
なんかひたすら瓦礫を見せられていて一向にゲームが始めれられません。

これの解決策ですが
特定のソフトのスタートアップを無効にすることで解決できました。

直し方

1.スタートで「システム」と検索し出てきた「システム構成」を起動
f:id:moyoi:20190417063752p:plain

2.起動したソフトの「サービス」タブを選択
左下の「Microsoftのサービスをすべて隠す」にチェックを入れて
右下の「すべて無効」をクリック
そして画面下の「OK」をクリックして再起動
f:id:moyoi:20190417063757j:plain


この作業後にもう一度BF5を起動してみると…
f:id:moyoi:20190417064029p:plain

このようなメニュー画面になると思います。

ちなみにですが、
先ほどの作業でいくつかのサービスの自動起動を無効にしてしまったため、PC起動時にめちゃくちゃエラーを吐くと思います。
これが嫌な方は「すべて無効」ボタンではなく、一つずつサービスを無効にしていき原因となっているサービスを絞って
そのサービスのみを無効にしてください。

私の場合は「AsusGameFirstServis」という本来ゲームを快適にプレイするためのソフトが悪さをしていたようで
こいつを無効にしたら無事起動できるようになりました。

Novonestの簡易水冷を導入してみた

今回はパソコンのCPUクーラーを水冷に取り替えたのでそれについて書いていこうと思います。

アマゾンで購入したこちら↓のCPUクーラーに付け替えました。値段はまあまあ安いって感じです。

前のクーラーのスペック等々

前使ってたのがこちら↓

デザインがかっこよくて割と好きでした。
なにもしない状態でこんな感じです。
f:id:moyoi:20190316111506j:plain

最高が35度位ですね。
イクラで遊んでいてこんな感じ。
f:id:moyoi:20190316111549j:plain

グラボのほうに負荷がかかっているので正直そんなに熱くなりません。
でも以前紹介した「stick fight」をやっていると時々CPUの温度が70度超えましたよ~っていう警告がよく出ます。

簡易水冷CPUクーラーに変える

ということで付け替えて配線して、いざ電源オン
f:id:moyoi:20190316114039j:plain

おおー
f:id:moyoi:20190316114235j:plain

あーゲーミングっぽいですね~
にしても真っ青w

うーん、前よりちょっとうるさいかな?
ファンの音はそこまで気になりませんがポンプの音がビミョーに気になります。
まあ許与範囲ですけど

さて、自分にとって音はあんまり重要じゃありません。問題は冷えるかどうかです。

通常時
f:id:moyoi:20190316112027j:plain

イクラ
f:id:moyoi:20190316112537j:plain

んんんー
あんまかわんないですね。

前のCPUクーラーでやってませんでしたがCinebench20でしっかりCPUに負荷をかけてみました。
f:id:moyoi:20190316113420j:plain

64℃~65℃らへんで安定ってかんじですかね
まあたしかに、普段使いしていると前より
「CPUの温度が70℃超えましたよー」
という警告を見なくなった気がします。

あ、そういえばですがいいことがありました。
水冷はラジエーターでCPUの熱を直接ケース外に放出できますが、
そのおかげでPCケース正面があったかくなってちょっとした暖房みたいになりました。
f:id:moyoi:20190316115201j:plain
あー、あったけぇ

まとめ

えー、話をまとめますとあんまり変わらなかったです。
しかしながら高負荷でも70℃を超えることはほとんどないので前よりはちょっとはよくなったのかもしれません。
私はCPUをオーバークロックしてるので空冷よりは安心ですね。

ちなみに私の場合OCすると4GHzのCPUが4.4GHzで動きました。
f:id:moyoi:20190316115810j:plain

AQUOSのなめらか倍速表示がどれほどバッテリーを消費するか実験してみた

どうもお久しぶりです。
今回は、前に書いた当ブログのPVの半分のアクセスを閉めている記事、
moyoi-memo.hatenablog.com
で話した「なめらか倍速表示」についてどれほどバッテリーを消費するか実験して見ましたのでそれについて書いていきます。

実験1「YouTube

端末はAQUOS R compact、電池を100%まで充電後、画面の明るさと音量を最大(スピーカーに接続した状態)で、なめらか倍速表示機能がONになっている状態とOFFになっている状態で、電池残量が49%になるまでそれぞれ実験しました。

結果

なめらか倍速表示
左が「OFF」    右が「ON」

f:id:moyoi:20190106203938p:plainf:id:moyoi:20190106204003p:plain
↑OFF  実験1の結果  ON↑

はい。ほとんど変わりませんでした。強いて言うととONのほうが若干電池の減りが早いです。
おそらく、動画の場合はFPSが動画に依存するため、わざわざ倍速表示する必要がなくOFFの状態と変わらなくなっているのだと思います。

実験2「Twitter

実験1のように動画を流しただけではほとんど変化が見られなかったので、実験2ではなめらか倍速表示の良さが出るスクロールの動作を行ってみます。AQUOSには「スクロールオート」という自動でスクロールを行ってくれる便利機能がついているのでそれを使い、ひたすらTwitterのタイムラインをスクロールさせます。

端末はAQUOS R compact、電池を100%まで充電後、画面の明るさ最大で、なめらか倍速表示機能がONになっている状態とOFFになっている状態で、電池残量が49%になるまで(他のことをしていたら49%を見逃してしまいました)それぞれ実験しました。

結果

なめらか倍速表示
左が「OFF」    右が「ON」

f:id:moyoi:20190109081747p:plainf:id:moyoi:20190106203911p:plain
↑OFF  実験2の結果  ON↑

気づいた方もいると思いますが、OFFのほうのグラフを見ると色々おかしいです。
申し訳ありませんでした。ほっておいたらいつの間にかディスプレイが消えちゃってました。
とはいっても、またしても大きな変化は見られませんでした。

実験1,2の結果まとめ

はい。全然変化がありませんでした。
全体の結果のグラフを「Battery Mix」というアプリから持ってきました。

f:id:moyoi:20190109083342p:plain
実験1,2のまとめグラフ
うーん、やっぱりあんまかわんないですね。
これはまさかの勘違いっていうやつでしょうか。いやそんなことないはずです。
という事で次の実験は一日使ってみてどうなるかを調べていきます。

実験3「1日使って比較」

端末はAQUOS R compact、電池を100%まで充電後、普通に1日使ってみます。
画面の明るさやBluetoothなどは適当です。

結果

全てのアプリになめらか倍速表示機能を適応した状態で1週間ほど使用してみましたが以前と比べて電池の持ちが悪くなったという感覚はありませんでした。

結果のまとめ

結果、ほとんど違いはありませんでした。
うーん、改善されたんですかね
前の状況のテストは行っていなかったので比べようがないのですが、
とりあえず『なめらか倍速表示機能はバッテリーの使用量にはあまり影響しない』
という事がわかりました。
これであのぬるぬる感をいつでも楽しめます。
やったぜ

格安3Dプリンター「Ender-3 Pro」を買ってみた

ついに買っちゃいました。3Dプリンター
今回購入したのは「Ender-3 Pro」というやつで、Amazonでポチりました。

最初はこちら↓のもう少し安いプリンターを買おうとしていたのですが、いつの間にか値上がりしていたので、どうせならと思い、フレームがアルミでしっかりしていそうな「Ender-3 Pro」を購入しました。
ついでにキャンペーン中だったので、白いPLAフィラメントも0.5㎏もらいました。

組み立て

この3Dプリンターは組み立て式なのでちょっと手間がかかります。

箱はこんな感じ。結構でかいです。
f:id:moyoi:20190111122325j:plain

中身はこんな感じ。ちゃんとしてますね。でもキッツキツに入っているので取り出すのが少し大変でした。
f:id:moyoi:20190111122436j:plain

全部出してこんな感じ。
f:id:moyoi:20190111123034j:plain

なんかペンチまでついてきました。ただし、レンチ等はもちろん安物だったので、すぐになめて使用不能になってしまいました。
f:id:moyoi:20190111122841j:plain

12ステップしかないので簡単に組み立てられます。

f:id:moyoi:20190111123145j:plainf:id:moyoi:20190111123141j:plain


という事で約1時間ほどで完成しました!
いやはや、かっこいいですね~
f:id:moyoi:20190111123410j:plain

調節とテストプリント

組み立てが終わったので次は調節をしていきます。

各軸の調節

Y軸のベルトがすこーし緩いと感じたのでちょっと張らせました。
そしてZ軸の送りネジの動きが悪かったので、ここ↓のねじを緩めました。
f:id:moyoi:20190117052052j:plain

ベットの水平出し

どうやらコピー用紙を挟んでやるのが一般的らしいですが、すごくやりにくかったので私はテストプリントをさせながら少しずつ調節していき、うまくいくところを探しました。
ちなみに水平になってないとこんな感じになってしまいます。
f:id:moyoi:20190111124618j:plain

という事でちゃんとプリントできるようになったのでいざ、テストプリント!
ノズルとベットの加熱には大体2分位かかり、温まるとすぐにプリントが始まります。
付属したSDカード内にテストプリント用の犬のデータが入っていましたが、どうやら何時間もかかるらしいので、今回はネットで拾ってきたよさげなモデルを使用します。
モデルを持ってきたら「ultimaker cura」と言うソフトでGchordに変換します。
このソフトで積層の厚さや密度、サポート材等の設定をすることができます。今回は特に設定を変えないで初期設定のままプリントしてみます。

テストプリントの結果

見てくださいよこれ、めちゃくちゃいい感じですよ。
細かい部分もしっかりと出来ています。

f:id:moyoi:20190119210649j:plainf:id:moyoi:20190119210809j:plainf:id:moyoi:20190119210844j:plain

色々作ってみた

今後作ってみたものを随時アップしていこうと思います。

改良

格安プリンターにはどんどん改良していけるという利点があります。
今回購入した3Dプリンターの公式サイトでも改良の仕方がまとめてあるページがあります。
m-all3dp-com.cdn.ampproject.org
では、今回は操作盤のカバーを作ってみます。
さっきのページに3Dモデルがあるのでダウンロードして早速印刷。
操作盤のカバーは途中でフィラメントが終わっちゃったのでフィラメントの色が2色になっちゃいました。

f:id:moyoi:20190119211300j:plainf:id:moyoi:20190119211325j:plain

ちなみにフィラメントの交換は前のフィラメントの末尾に新しいフィラメントを押し付けながらフィラメント送り器に取り込ませるだけでできました。
ついでに箱に同封されていた防塵用のチューブも付けました。

改良後

こんな感じです。
f:id:moyoi:20190117052501j:plain

まあ、そんなに変わったわけではないですね。
公式サイトにこのほかたくさんの改良方法が載っているので今後手を出していきたいと思います。
また改良したら随時更新していこうと思いますのでよろしくお願いします。

ラズパイ起動時にプログラムを自動実行させる

いやはや、私の苦労は一体なんだったのでしょうか。
数日間できないできないと戦っていた「プログラムの自動実行」。詳しい方に聞いたら一瞬で出来ちゃいました。それもめちゃくちゃ簡単に。
ということで今回は「ラズパイ起動時にプログラムを自動実行させる方法」について書いていこうと思います。

ステップ1「なんか開く」

私はソフトウェア系はあんまりやってないので適当ですが勘弁してください。
という事でターミナルに
「sudo leafpad /etc/rc.local」
と入力します。
するとテキストエディターが開きます。
f:id:moyoi:20190115064158j:plain

ステップ2「書く」

開いたテキストエディターの一番下に「exit 0」と書いてあると思いますのでその上に起動したいプログラムの種類とフルパスを書き込みます。私の場合はデスクトップにあるbolvider.pyというpythonファイルを実行したかったので
「python3 /home/pi/Desktop/bolvider.py」
と記入しました。
f:id:moyoi:20190115064240j:plain

ステップ3「再起動」

再起動すると上手くいっていればプログラムが自動実行されます。
再起動したらCPU使用率が上がった↓

f:id:moyoi:20190115064618j:plainf:id:moyoi:20190115064623j:plain
なお、デスクトップでは何も表示されないのでご注意を。
上手くいかない場合はおそらくステップ2で書き込んだ内容が間違っています。
私もはじめ、
python /home/pi/Desktop/bolvider.py」
と書き込んでうまくいきませんでしたが、python3と記入したところ無事起動しました。まあ、ターミナルに書き込んでちゃんと起動するか調べてから実際にファイルに書き込んだほうがいいかもしれませんね。

pythonだけのときはエラーが出てるのがわかります。(python3の時も出ていますがこれはプログラム本体のエラーです)
f:id:moyoi:20190115064753j:plain

【画像認識】OpenCV初心者がネジ識別プログラムを作ってみた

今回は部活でのうっとうしいネジ分けから解放されるべく第一歩として、OpenCVで「ネジ識別プログラム」を作ってみたので、それについて書いていこうと思います。

開発環境

今回はanaconda3を入れるといっしょについてくるSpyderという開発環境にOpenCVを入れてプログラムしました。

spyderの画面
spyder
自動整形がないのが残念ですが割と使いやすかったです。

プログラム

とりあえず今回作った(大半コピペ)プログラムを張っておきます。しかし、初めてのOpenCV という事もあり、しっかり覚えておきたいので今回は細かく説明していこうと思います。そのため、プログラム中のコメント等はすべて削除しています。
↓今回のプログラム

import cv2
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon

cam = cv2.VideoCapture(1)
_,img = cam.read()

lookUpTable = np.empty((1,256), np.uint8)
for i in range(256):
    lookUpTable[0,i] = np.clip(pow(i / 255.0, 0.5) * 255.0, 0, 255)
img_gamma = cv2.LUT(img, lookUpTable)

img_gray = cv2.cvtColor(img_gamma, cv2.COLOR_BGR2GRAY)
img_blur = cv2.GaussianBlur(img_gray, (5,5), 0)
_, img_binary= cv2.threshold(img_gray, 130, 255, cv2.THRESH_BINARY_INV)

contours = cv2.findContours(img_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

def draw_contours(ax, img, contours):       
    ax.imshow(img)
    ax.axis('off')
    for i, cnt in enumerate(contours):
        cnt = np.squeeze(cnt, axis=1)
        ax.add_patch(Polygon(cnt, color='b', fill=None, lw=2))
        ax.plot(cnt[:, 0], cnt[:, 1], 'ro', mew=0, ms=2)
        ax.text(cnt[0][0], cnt[0][1], i, color='b', size='20')

fig, ax = plt.subplots(figsize=(6, 6))
draw_contours(ax, img_gamma, contours)

for i, cnt in enumerate(contours):
    rect = cv2.minAreaRect(cnt)
    (cx, cy), (width, height), angle = rect
    rect_points = cv2.boxPoints(rect)
    ax.add_patch(Polygon(rect_points, color='g', fill=None, lw=2))
    
    if width<height:
        kei=int(width)
        nag=int(height)
    else:
        kei=int(height)
        nag=int(width)
    print('番号:',i)
    print('縦:',kei,'横',nag)       
    L = 0
    if 44<=kei<=52:
        M = 3
    elif 55<=kei<=65:
        M = 4
    else:
        M = 0
    if M == 3 and 100>nag>80 or M == 4 and 110>nag>100:
        L = 8
    elif M == 3 and 78 >= nag >= 67 or M == 4 and 100 >= nag > 70:
        L = 5
    if M == 0:
        print('認識できませんでした')
    else:
        print('径:','M',M)
    if L == 0:
        nag = 11*nag/100-3
        L = int((nag + 4) / 5) * 5
    if M != 0:
        print('長さ:',L,'mm')

plt.show()

画像認識用のカメラとライトについて

プログラム解説の前に画像認識用のカメラとライトについて説明します。
今回は友人から借りたウェブカメラを使って画像認識していきます。
画像認識の方法より、白と黒のコントラストが重要になってくるため、一定の明るさで画像を撮る必要があります。そのため、簡単な撮影用の小道具を作りましたので紹介します。

撮影用の台
撮影用の何か
こんな感じでペットボトル飲料の上下を切りとってそこに蓋をしてハイパワーLEDと、穴をあけてウェブカメラをつけました。
撮影用の台の内部
撮影用の何かの内部
ちなみにLEDはUSBのバスパワーでつけています。
LED電源及びウェブカメラのUSB
LED電源及びウェブカメラのUSB

プログラム解説

では、1行目から解説していきます。

import cv2
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon

ここは、ただライブラリ等を入れているだけなので省略


#VideoCapture オブジェクトを取得
cam = cv2.VideoCapture(1)
#一コマ分の画像を取得してimgに代入
_,img = cam.read()

cv2.VideoCapture(1)の()の中の数字ですが、0だとパソコンの内臓カメラの画像になったので、おそらく指定するカメラの番号だと思います。


#ガンマ処理を行って画像を明るく
lookUpTable = np.empty((1,256), np.uint8)
for i in range(256):
    lookUpTable[0,i] = np.clip(pow(i / 255.0, 0.5) * 255.0, 0, 255)
img_gamma = cv2.LUT(img, lookUpTable)

撮影した画像は私の使っているウェブカメラだと少し画像が暗いのでガンマ処理を行って明るくします。
どの程度明るくするかは、lookUpTable[0,i] = np.clip(pow(i / 255.0, 0.5) * 255.0, 0, 255)の「0.5」の部分を変更することで行えます。


#画像を白黒画像にする
img_gray = cv2.cvtColor(img_gamma, cv2.COLOR_BGR2GRAY)
#画像を少しぼかす
img_blur = cv2.GaussianBlur(img_gray, (5,5), 0)
#画像を完全な白と黒の画像(二値画像)に
_, img= cv2.threshold(img_blur, 130, 255, cv2.THRESH_BINARY_INV)

画像認識の下処理として画像を完全な白と黒の画像にしなければなりません。さらにその下処理としてまずはカラー画像を白黒(グレーも含む)にします。
その後、細かいノイズを処理するために画像をぼかします。ちなみにぼかし具合はimg_blur = cv2.GaussianBlur(img_gray, (5,5), 0)の「(5,5)」の値を変えることで変更できます。
そして、最後に画像を完全な白と黒の画像(二値画像)にして下処理は終了です。


#二値画像から輪郭を検出
contours = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

画像imgの黒い背景から白い物の輪郭を検出します。
検出した輪郭はcontoursにリストとして代入されます。


fig, ax = plt.subplots(figsize=(6, 6))    
ax.imshow(img_gamma)
ax.axis('off')
for i, cnt in enumerate(contours):
    cnt = np.squeeze(cnt, axis=1)
    # 輪郭の点同士を結ぶ線を描画する。
    ax.add_patch(Polygon(cnt, color='b', fill=None, lw=2))
    # 輪郭の点を描画する。
    ax.plot(cnt[:, 0], cnt[:, 1], 'ro', mew=0, ms=2)
    # 輪郭の番号を描画する。
    ax.text(cnt[0][0], cnt[0][1], i, color='b', size='20')

img_gammaの上に輪郭の線を書きます。
これと、この下のプログラムは参考サイトのほとんどそのままなので、詳しい説明はそちらのほうを見てください。


for i, cnt in enumerate(contours):
    # 輪郭に外接する回転した長方形を取得する。
    rect = cv2.minAreaRect(cnt)
    (cx, cy), (width, height), angle = rect
    # 回転した長方形の4点の座標を取得する。
    rect_points = cv2.boxPoints(rect)
    # 回転した長方形を描画する。
    ax.add_patch(Polygon(rect_points, color='g', fill=None, lw=2))

ネジを囲む長方形も描画します。


#取得した長方形の縦横の長さを比べて、長いほうをnag,短いほうをkeiに代入
 if width<height:
        kei=int(width)
        nag=int(height)
    else:
        kei=int(height)
        nag=int(width)
 #取得した長方形の番号をコンソール画面に表示します。
    print('番号:',i)
 #取得した長方形の縦横の長さをコンソール画面に表示します。
    print('縦:',kei,'横',nag)       
 #取得した縦横の値をからネジの径や長さを割り出します。
    L = 0
    if 44<=kei<=52:
        M = 3
    elif 55<=kei<=65:
        M = 4
    else:
        M = 0
    if M == 3 and 100>nag>80 or M == 4 and 110>nag>100:
        L = 8
    elif M == 3 and 78 >= nag >= 67 or M == 4 and 100 >= nag > 70:
        L = 5
    if M == 0:
        print('認識できませんでした')
    else:
        print('径:','M',M)
    if L == 0:
        nag = 11*nag/100-3
        L = int((nag + 4) / 5) * 5
    if M != 0:
        print('長さ:',L,'mm')

ここは完全オリジナルのプログラムで、
ひたすら画像認識させて縦横の長さの傾向を調べ
そこからぶりぶり計算してネジの径や長さを割り出せるようにしました。


#画像を表示します。
plt.show()

ここで画像を表示します。

感想とか

今回、初めて画像認識をしてみましたが、OpenCV が便利すぎて正直めちゃくちゃ楽だったです。
私の中で画像認識ブームが到来してきました。

今現在、画像認識した結果をArduinoを間に挟んでLCDに表示しようとしているのですが、こっちのほうが難しいですね。
LCD表示できるようになったらまた記事を書くので、どうぞお待ちください。

ESP32で遊んでみた~uPyCraftを使ってLチカ編~

前回はESP32にプログラムを書き込むためにuPyCraftをインストール&初期設定をしたので、今回は実際にプログラミングをしていきたいと思います。

f:id:moyoi:20181112143557j:plain

まずは接続

まず初めにESP32とuPyCraftを接続します。
おそらく、右のオレンジの部分の鎖アイコンの「Connect」を押せばつながると思いますが、もしつながらなかった場合は前回の記事の初期設定をやり直してみてください。
ちなみに、ESP32とuPyCraftが接続されると画面下に
>>>
と表示されます。

upycraft接続完了の画面
接続されたらこうなります

ESP32でLチカに挑戦

ESP32とuPyCraftの接続が完了したら、早速Lチカに挑戦してみましょう。
有難いことに例が標準で入っているのでそのプログラムを使ってみます。

f:id:moyoi:20181113151131p:plain

今回はこの中の「blink.py」を使います。
↓一応プログラムを張っておきます。

#hardware platform: FireBeetle-ESP32
#Result: Blink
#The information below shows blink is unavailble for the current version.
#IO0 IO4 IO10 IO12~19 IO21~23 IO25~27
#Except the connection between IO2 and onboard LED, other pins need to connect to external LEDs. 

import time
from machine import Pin
led=Pin(2,Pin.OUT)        #create LED object from pin2,Set Pin2 to output

while True:
  led.value(1)            #Set led turn on
  time.sleep(0.5)
  led.value(0)            #Set led turn off
  time.sleep(0.5)

led=Pin(2,Pin.OUT) とありますが、2番ピンは基板上のLEDと初めからつながっているので、今回はLED等はつなぎません。
では、書き込んでいきましょう。
書き込みは右のオレンジの部分の三角マークの「DownloadAndRun」を押してください。
書き込みが完了するとすぐに基板の上のLEDが光りだすと思います。

ピンからもしっかりと出力されているかLEDをさして試してみましょう。
ピンの位置はAmazonに貼ってあったやつで探します。

f:id:moyoi:20181114055945j:plain

画像では下のほうにUSBのコネクタがある感じなので、2番ピンは右の下から5番目。GNDは右の一番上を使います。

無事に点灯しました。
ちなみにですが、プログラムの上のコメントに「IO0 IO4 IO10 IO12~19 IO21~23 IO25~27のピンは現在のバージョンでは利用できない」などと書いてあるのですが、試しに使ってみたら問題なく使えたのでよくわかりませんでした。

という事で今回はここまでです。
次回はセンサーの値を読んでみようと思います。しかし、テストが近くなってきたので更新がかなり遅れてしまうかもしれません、ご了承ください。


↓次の記事はこちら↓
申し訳ありません。現在作成中です。

ESP32で遊んでみた~uPyCraftインストールと初期設定編~

今日は奮発してAmazonでESP32を購入しましたので、それについて何回かに分けて書いておこうと思います。

↓購入したESP32↓

使用したIDE

このマイコンArduino IDEを使ってプログラムを書き込むこともできますが、今回はPythonを勉強したかったので「uPyCraft」というMicroPythonを使ったIDEを使います。

uPyCraftのダウンロードおよび初期設定方法

まず、ここから本体をダウンロードしてください。
ここ→ About · GitBook

uPyCraftのアイコン画像
uPyCraftのアイコン
ダウンロードした蛇のアイコンの.exeファイルを開くとまず、フォントをインストールしろと言われ、デスクトップにフォントファイルが作成されuPyCraftが起動します。(作成されたフォントファイルをインストールしても何も変わらないので無視してOK)
するとアップデートを促すウィンドウが出てくると思うのでOKを押してください。
ダウンロードが完了するとアップデート前の.exeファイルがあったところと同じ場所に最新のバージョンの.exeファイルがダウンロードされていると思いますので、古い.exeファイルは消してしまって結構です。

ドライバのインストール

初め、サブ機として使っているノートパソコンを使ってESP32に接続を試みたのですが、接続しようとするとソフトが固まってしまって一向に接続できませんでした。しかし、メインのデスクトップpcでは問題なく接続できたので何が問題か探ってみると、ドライバーが入っていなかったことが原因であったことがわかりました。
おそらくこのドライバは私が過去に自分で入れたものなので新たにインストールする必要がありますので、

↓こちら↓
jp.silabs.com

からファイルをダウンロードして展開し、適切なインストーラーを起動してインストールをしてください。

ESP32との接続

upycraftの画面
upycraftの画面
ソフトを起動しただけではESP32とはまだつながらないので初期設定をします。
まず、右上のメニューバーの中の「Tools」の中の「Serial」を開いた状態で、ボードのケーブルを抜き差しして出てくるCOM番号を選択してください。
すると初期設定をするウィンドウが出てくるので指示に従って初期設定をしてください。
初期設定が完了するともうESP32にプログラムを書き込める状態となります。

次回は早速ESP32にプログラムを書き込んで遊んでみようと思います。

↓次の記事はこちら↓
moyoi-memo.hatenablog.com

PC版″荒いスマブラ″こと「Stick Fight: The Game」が楽しい

皆さん、スマブラこと大乱闘スマッシュブラザーズはご存じでしょうか。
たくさんの有名ゲームキャラクターたちがそれぞれの必殺技を駆使して戦う戦闘ゲームで、相手を吹っ飛ばしたときの爽快感はなんとも言えないものです。
しかしながらスマブラは、専用のゲーム機がないとプレイできません。
更に、マップも限られているので、ずっとプレイしているとマップに飽きてきてしまうかもしれません。
しかし私は、そんな悩みを解消する最高のゲームを見つけました。

(↓スナイパーでヘッドショットの図)
f:id:moyoi:20181109062901p:plain




↓Stick Fight: The Gameの購入はこちらから↓
store.steampowered.com



Stick Fight: The Gameとの出会い

私はスマブラを持っていなかったのですが、ある日自宅に友人が3人来たとき、4人でマルチプレイをしようと言うことになりました。
しかし、手元には2人でのマルチプレイが限界なゲームしかなかったため、steamで4人で遊べて安いゲームを探していました。
すると、4人で遊べて、なおかつ500円で買えてしまう「Stick Fight: The Game」を発見しました。
早速購入、ダウンロードを行いゲームを起動してプレイしてみると、
思った以上に楽しい。
キャラクターは色が違うだけでなんの特徴もありませんが、キャラクターを選ぶ手間がなく、皆平等に出来ますし、ゲームも非常に単純でテンポがよく、友人たちで楽しくプレイすることが出来ました。

ゲームの内容とか操作方法とか

ゲームの内容としては、2Dのマップ上でただひたすらプレイヤー同士で殴りあったり、ランダムに降ってくる武器で撃ったり刺したりして、最後の一人になるまで戦うといった非常に単純なものです。
武器の種類は、一般的な銃からあり得ないような威力の銃。また、槍や剣などがあります。
マップは初期状態で80ほど、さらにエディター機能もあるので、
自分でマップを作ったり、他のプレイヤーの作成したフィールドで遊ぶこともできます

(↓エディター画面)
f:id:moyoi:20181109063807p:plain

操作方法も非常に簡単で、マウスで攻撃と防御と体の向きの調節、キーボードで左右上下の移動や武器を投げたりできます。
マルチプレイをする場合は、ゲームパッドを繋げるだけで簡単にプレイできます。
ただし、ゲームパッドによっては体の向きの調節が難しく、相手に銃口をうまく向けられなかったりしますのでご注意下さい。
また、オンラインプレイも簡単には出来て手軽に世界のプレイヤーとゲームをすることができます。ゲーム内でのチャットも可能なので、簡単なコミュニケーションを取ることも可能です。

(↓オンラインプレイのエントリールーム)
f:id:moyoi:20181109063155p:plain

ちなみにゲームは日本語には対応していませんが、読めなくても全く問題なくプレイできるので安心してください。

最後に、このゲームは結構重いです。
パソコンの性能ががそれなりにないとカックカクになってしまうと思うので、パソコンのスペックと相談して購入してください。
過去に私の低スぺサブノート(下にレビュー記事を張ってあります)に入れてプレイしてみたらカックカクでパソコンがめちゃくちゃ熱くなってしまいました。

moyoi-memo.hatenablog.com



ということで、是非ともあなたも「Stick Fight: The Game」で思いっきり暴れちゃいましょう!

Core m3ってどうなの?~NECのLAVIE(NM350/G)を半年使ってみて~

今回は、私が愛用しているサブノートpcのLAVIE(NM350/G)について、使い始めてから半年がたったのでレビューを書こうと思います。
f:id:moyoi:20181025160344j:plain
(↑エンブレムシールはメインPCのCPUに付いてきたi7のに付け替えてネタにしていましたが剥がれてしまったのでまた買います)

値段やら性能やら

このパソコンは10万ちょっとぐらいで家電量販店で購入しました。
簡単に性能を紹介しますと
CPU:Intel Core m3-7Y30
メモリ:4G
ストレージ:SSD 119G
OS:windows10 64bit
といった感じです。
自宅にCore i7 6700K搭載のメイン自作デスクトップPCがあるので、持ち運び用という事で性能は控えめです。
(デスクトップPCのことはまた今度書きたいと思います。)

性能に関して

このPCでする作業は、調べ物をしたり、簡単なプログラミングをしたり動かしたりといった簡単なことなので性能はまあ十分ですね。
3DCADも割とストレスなく動かせました。
しかし、昔重めのゲーム(下に記事を張っておきます)を入れてみたときは、一応動きましたがPCがめちゃくちゃ熱くなりました。まあ、ファンレス設計なのでしょうがないですね。

moyoi-memo.hatenablog.com


電池の持ちも、朝フル充電にしておけば、家に帰るまで充電は必要がない程度には持ちます。

その他

まず、大きさに関してですが、コンパクトで非常にいい感じです。
重量も軽く、自転車で移動する私にとってはとてもいいノートPCだと思います。厚さも割とあるので、パンパンのカバンに突っ込んでも安心感があります。

最後に物足りない点ですが、今のところ特にありません。
強いて言いますと、なんだか音がこもることや、画面がもう少し開いたらよかった、といったことだけです。
あ、でも最近、なぜかファイル等を新規作成しようとすると固まってしまう謎の症状が出始めました。まあこれはアップデート等でいつか治ると思ますが。(治りました。)


私的には最高のノートPCですね。Core m3は初めてだったのでどんな感じか気になっていたのですが、結構いい感じです。
あとは、DVD,CDドライブがついていなかったのが少し痛いくなるかなと思っていましたが、DVDやCDはあまり使わないので外付けで十分ですね。

という事でLAVIE(NM350/G)は結構使えるヤツだったので手ごろなノートPCをお求めの方は一度考えてみてはいかかでしょうか。

500円で、骨伝導?イヤホンを買ってみた話

私は普段自転車で40分ほどかけて通学しているのですが、その時間がもったいなくてしょうがありませんでした。この時間を有効活用できたらいいのに...。しかし、そんな日々を過ごしていた私にうってつけの商品をネットで見つけました。その名も「骨伝導イヤホン」
いやまあ、前からこういうイヤホンがあることは知っていたのですが結構高くて手が出せなかったのです。
しかし、なんとこの商品は500円ほどで買えてしまい、ついでにBluetooth
これは買うしかない。

そして約1ヶ月後。ついに届きました。
f:id:moyoi:20181024115257j:plain
おお、いいフォルム。あとめっちゃ軽い。
早速耳に装着してみるとあんまり安定感がないです。しかし頭を振っても落ちることはなさそう。
では、電源を入れてみます。
「パワーオン」とアナウンスの声が。結構音が割れてますね。
あと、すっとザーザーとかピーピーとかの雑音が聞こえます。まあ、500円なのでこれくらいは我慢します。
さて、スマホにつないでみましょう。どうやら起動した時点でペアリングモードに入るようなので早速ペアリングします。
しかし、スマホBluetooth設定を見てみると。あれ?
f:id:moyoi:20181024120756j:plain
なんかおかしいですが問題なくつながりました。
さて、早速ネットラジオでも流して聞いてみましょう。
んんんんーー…
何だろう、骨を伝ってきている感じはしません。一度外してみると結構音がもれてますね。んん?これは?
f:id:moyoi:20181024142036j:plain
何だか穴が開いています。マイクかとも思いましたがマイク用の穴は下に空いているので違いそう。
耳を近づけるとなんだかここから音が出ている気もします。
これは怪しい。

という事で開けてみました。
f:id:moyoi:20181024142423j:plain
あれ、なんだか骨伝導できそうな部品がはいってますね。
f:id:moyoi:20181024142612j:plain
試しに大音量でネットラジオを流してみると振動しているような気もします。
試しにもう一度耳に装着して耳をふさいでみると

ちょっとだけ聞こえる。

確かに普段とは違う音が聞こえます。これが骨伝導なのでしょうか。
まあ、ちゃんとしたもので聞いたことがない私にはわかりませんでした。
しかしながら、イヤホンとしてはしっかりと機能してくれましたし、なんといっても500円なので十分な性能なのではないでしょうか。

でも今度はしっかりしたものを買いたいですね。