<python>arduinoがつながるポートを自動で見つける

はじめに

今回のエントリは以下のエントリの続きです.
poolbooyer.hatenablog.jp
見る順番に関してはどちらが先でも問題はないと思いますが、新規で追加した機能の部分しか記述しないので順番通りで読むのをお勧めします.

portを探すのって地味にめんどい

arduinoに関わらず、様々なデバイスとシリアル通信するときに必ず必要になるのが接続しているポートを特定する作業です.繋ぎっぱなしだったら一回プログラム書くときにそこを直書き(?)してしまえば特に問題はありませんがそんなことほぼないです(よね?).

面倒なことはpythonにやらせよう

今回やること

  • osのデバイス情報を取得
  • pythonを使ってportを取得
  • 取得したportに接続する

今回新しく触れたもの

  • OSライブラリ

実際にやってみよう

実際に作成したコード

#coding:utf-8

#システムのインポート
import sys
sys.path.append('/Library/Python/2.7/site-packages')
#シリアル通信のインポート
import serial
from serial.tools import list_ports
#OS関連のインポート
import os
import io
#tkinterのインポート
import tkinter
from tkinter import messagebox

#シリアル設定
#前回は直書きしてました
#ser=serial.Serial("/dev/cu.usbmodem1421",9600)

#ウィンドウ生成
top=tkinter.Tk()
top.title("serial sample")
top.geometry("400x300")
#top.iconbitmap("led.ico")

#シリアル通信オブジェクトの生成
ser= serial.Serial()
ser.bsudrate=9600
ser.timeout=0.1

#アプリケーションクラスの作成
class Application(tkinter.Frame):
    def __init__(self,master=None):
        super().__init__(master)
        self.pack()
        self.create_widgets()

    #ボタンの作成
    def create_widgets(self):

        #検索ボタンの生成
        #ここで繋がってるポートを探すボタンを作る
        self.hi_there=tkinter.Button(self)
        self.hi_there["text"]="serch"
        self.hi_there["command"]=self.serch_device
        self.hi_there.pack(side="top")

        #LED点灯用ボタン
        self.hi_there=tkinter.Button(self)
        self.hi_there["text"]="LED ON"
        self.hi_there["command"]=self.tx_on
        self.hi_there.pack(side="top")

        #LED消灯用ボタン
        self.hi_there=tkinter.Button(self)
        self.hi_there["text"]="LED OFF"
        self.hi_there["command"]=self.tx_off
        self.hi_there.pack(side="top")

        #シリアル通信終了用ボタン
        self.hi_there=tkinter.Button(self)
        self.hi_there["text"]="close connection"
        self.hi_there["command"]=self.close
        self.hi_there.pack(side="top")

        #アプリケーション終了ボタン
        self.quit=tkinter.Button(self,text="Exit",command=self.master.destroy)
        self.quit.pack(side="bottom")

    #検索を行う
    def serch_device(self):

          #/dev配下にあるファイルリストの取得
          files=os.listdir('/dev')
          #usbデバイスが見つかった時の処理
          #macではtty.usbmodem以下の数値が変化するので検索する検索内容をターゲットに記述
          target="tty.usbmodem"
          #前方一致をやった結果をdevnameに格納
          devname=[data for data in files if target in data]
          if len(devname)!=0:
              #見つかったことを示すダイアログボックスを作成
              found()
              #serialオブジェクトのポート情報を書き換え
              ser.port='/dev/'+str(devname[0])
              #serial通信の開始
              ser.open()
          #usbデバイスが見つからなかった時の処理
          else:
              #繋がらなかったことを示すダイアログボックスを作成
              not_found()
    #点灯用ボタンの動作の定義
    def tx_on(self):
        ser.write(bytes("n",'utf-8'))

    #消灯用ボタンの動作の定義
    def tx_off(self):
        ser.write(bytes("f",'utf-8'))

    #シリアル通信終了用ボタンの動作の定義
    def close(self):
        ser.close()
#見つからなかった時のメッセージボックス
def not_found():
    messagebox.showerror("error!!","device not found")
#見つかった時のメッセージボックス
def found():
    messagebox.showinfo("find!!","device is found")

app=Application(master=top)
#ウィンドウの生成
app.mainloop()

これでできます.
ちなみに完全Mac用です.
windows用も今後作成しようかなと思っています.

<ptyhon>pythonでarduinoをいじくる

ここ二日間唐突にpython熱が上がってきています

今回はpythonを使ってデスクトップアプリケーションを実装してarduinoをシリアル通信を用いて操作するとこまでやりました。


arduino,pythonどちらもコードを書いたのですが、arduinoに関しては特になんの変哲も無いしシリアル通信をするだけのコードなので省略します

pythonでデスクトップアプリケーションを実装するためには色々ライブラリがあるみたいなのですが、今回はデフォルトで利用可能なtkinterを使用しました
理由としては今回の作成でのメインになるのはそっちではなくarduinoとの通信だからっていうのが大きいです。
ということで、作成したコードの流れは以下の通りです

import tkinter
import sys
sys.path.append('/Library/Python/2.7/site-packages')
import serial

#シリアル設定
ser=serial.Serial("/dev/cu.usbmodem1421",9600)

#ウィンドウ生成
top=tkinter.Tk()
top.title("serial sample")
top.geometry("400x300")

#アプリケーションクラスの作成
class Application(tkinter.Frame):
    def __init__(self,master=None):
        super().__init__(master)
        self.pack()
        self.create_widgets()

    #ボタンの作成
    def create_widgets(self):
        #LED点灯用ボタン
        self.hi_there=tkinter.Button(self)
        self.hi_there["text"]="LED ON"
        self.hi_there["command"]=self.tx_on
        self.hi_there.pack(side="top")

        #LED消灯用ボタン
        self.hi_there=tkinter.Button(self)
        self.hi_there["text"]="LED OFF"
        self.hi_there["command"]=self.tx_off
        self.hi_there.pack(side="top")

        #シリアル通信終了用ボタン
        self.hi_there=tkinter.Button(self)
        self.hi_there["text"]="close connection"
        self.hi_there["command"]=self.close
        self.hi_there.pack(side="top")

        #アプリケーション終了ボタン
        self.quit=tkinter.Button(self,text="Exit",command=self.master.destroy)
        self.quit.pack(side="bottom")

    #点灯用ボタンの動作の定義
    def tx_on(self):
        ser.write(bytes("n",'utf-8'))

    #消灯用ボタンの動作の定義
    def tx_off(self):
        ser.write(bytes("f",'utf-8'))

    #シリアル通信終了用ボタンの動作の定義
    def close(self):
        ser.close()


app=Application(master=top)
#ウィンドウの生成
app.mainloop()

大体はコメントに書いたので特に追記することはないかなと思っています
#今回ははてな記法使えた
強いていいえば、シリアル通信するときに文字をバイト文字列に変形するためにbytesを使っています(on,offの頭文字を使うとどっちもoなのでnとfで信号を変えています)

実際に実行するとこんな画面になります
f:id:poolbooyer:20180616022821p:plain

pythonコードに加えてarduinoのスケッチを以下のリンクを参考にして作成しました
そうするとarduinoにつないだLEDの制御ができました

参考資料
qiita.com

<JavaScript>Javascriptで画像を動的に切り替え

JavaScriptです

 

やること

・ボタンを押されたら画像を切り替える

 

要件

・フロントで動かす

・画像の情報が変わっても対応が簡単になるように

・ボタンをクリックしたことをトリガーにして

 

っていうのを作りました。

 

使用したソースコード


            <img id="img" style="height: 300px; width: 300px;" alt="hoge" >
            <a name="yasai.jpg" class="samp" onclick="changeimg(0)">hoge<a>
            <a name="hoge.png" class="samp" onclick="changeimg(1)">hoge<a>
            <script type="text/javascript">
var changeimg=function(hoge) { //ボタン上の要素を全て取得 var a = document.getElementsByClassName('samp'); //imgの状態を取得 var img = document.getElementById('img'); //imgの画像を指定(変更) img.setAttribute("src", a[hoge].name); }
</script>

//はてな記法使ってハイライトしようと思ったら編集画面の切り替えができなくて断念しました

 

このコードでやってることの説明

var a = document.getElementsByClassName('samp');

 aにsampクラスのelementの内容を全て格納 

var img = document.getElementById('img');

imgにidがimgのelementの内容を全て格納

img.setAttribute("src", a[hoge].name);

imgタグのsrc情報を書き換える(この時はaタグのhoge番目のname要素に)

 

以上 メモ