Python §83 : シリアル通信(送信受信を別々のプログラムで実行) | hitochan007のブログ(Pythonの勉強ブログ)

hitochan007のブログ(Pythonの勉強ブログ)

★Pythonの勉強記録を中心に●pomera DM200、●パソコン、●グルメ、●愛犬(トイプードル) などについてのブログです


ブログランキング参加しました。下のバナーをポチッとしていただけると助かります。↓

Python ブログランキングへ



通信関係のバックナンバーです。

§79.通信リアルタイムモニター 構想段階
§80.シリアル通信
§81.シリアル通信(通信ポートの自動サーチ)
§82.シリアル通信(エンコードとデコード)


■シリアル通信(送信受信を別々のプログラムで実行)■
●1.ふたつのプログラム間で通信
●2.送信側プログラム
●3.受信側プログラム
●4.1秒毎に送信する
●5.カンマを挟んで日付と時刻も送信する




●1.ふたつのプログラム間で通信


前回は、ひとつのプログラム内で送信と受信を行うテストを行いました。

今回は、送信側と受信側を別々にプログラムを作成して、それぞれを起動して、うまく動作するかどうかを試してみたいと思います。
簡単なプログラムの設計をしてみたいと思います。

①送信側: ポートをオープンしたあと、すぐに10個の数値を文字列にして送信し、ポートをクローズする
②受信側: ポートをオープンしたあと、文字列を1行ずつ読み込むように準備し、読み込んだら新しいデータを待ち続ける

期待する結果は、②のプログラムは起動したら、ずっと動き続ける(データがない場合は待機し続ける)ことです。①の送信側は、10個送信したら終了するので、何度でも起動をすれば、②のプログラムが受信してくれるという動きをすることを期待します。

これらのプログラムの動きがわかるように所々にprint()関数で、データを表示することにします。



●2.送信側プログラム


まず、送信側のプログラムです。

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
'''
(1)送信側プログラム
(2)数字を0~9までバイトデータとして送る
'''
import serial #シリアル通信モジュールをインポート
ser1 = serial.Serial(2) #送信用ポートをOpen

print ('送信用ポート番号:',ser1.portstr) #送信用ポート番号を確認
print('送信テスト')
for i in range(10):
moji0=str(i) #文字列を変数の格納。
moji1=str(i)+'\r\n' #文字列の最後は改行文字を入れる
moji2=moji1.encode('utf-8') #文字列をバイト型に変換
print(moji2)
ser1.write(moji2) #エンコードしたデータを送信する

syntax2html


5行目 前回と同様 serialモジュールをインポートします
6行目 ポート番号は予め調べておきます。今回は2番(これはCOM3を意味します)
10行目 10個の整数を生成します。
11行目 文字列に変換
12行目 改行コードを忘れずに入れます(受信のときにreadline()が使えるようにするためです)
13行目 encode関数を使って、バイト型に変換します(Python3からバイト型になりました)
15行目 write()関数を使って、送信します。

このコードでは、一気に10個送信してしまうので、実は受信側を先に走らせて待機しなければなりません。

とりあえず実行してみます。


実行結果

Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:15:05) [MSC v.1600 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
送信用ポート番号: COM3
送信テスト
0
1
2
3
4
5
6
7
8
9
>>>


0から9までの整数を文字列化して、送信しました。
もちろん、受信側を用意していないので、データは垂れ流しです。(むなしい!)


●3.受信側プログラム


先に受信側を作るべきでした。

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
'''
(1)まずはポートのopenからはじめる
(2)送信テスト バイト型にして送る
(3)受信テスト バイト型で受信して、通常の文字列に変換する
'''
import serial #シリアル通信モジュールをインポート
ser2 = serial.Serial(3) #受信用ポートをOpen


print ('受信用ポート番号:',ser2.portstr) #受信用ポート番号を確認

print('受信テスト')


while True:
a=ser2.readline()
moji2=a.decode('utf-8')
print(moji2.strip())

ser2.close() #受信型のポートをopen

syntax2html


6行目 serialモジュールをインポートします。これは、送信プログラムと同様
7行目 ポート番号は3を設定しています。これは、パソコンの環境で異なりますので注意
15行目 while True: これは、無限ループを表します。
16行目 readline()関数で1行ずつデータを取得します。送信データに\nがついていることが重要です。
17行目 decode()関数で、受信したデータをバイト型から文字列型に変換します。
18行目 両端の空白コード(改行コードなども含む)を除去するためにstrip()関数を使います。その後表示します。
20行目 このプログラムは無限ループですので、このclose()関数は実行されませんが、一応礼儀として入れておきました。

!--
――――――――――――――――――――――――――――――――――――――――
【プログラムコード用 囲い文字】
――――――――――――――――――――――――――――――――――――――――
-->
受信テスト結果

Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:15:05) [MSC v.1600 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
受信用ポート番号: COM4
受信テスト
0
1
2
3
4
5
6
7
8
9



ちゃんと、0~9までのデータが受信されていました。さきほどのstrip()関数を使わなければ、各受信データ間が改行されてしまいます。


●4.1秒毎に送信する


さきほどの送信側と受信側のプログラムを実行すれば、わかりますが一瞬にして終わります。

9600bpsの速度で送信しますので、送信時間は0.1秒以内です。受信も同じくらいなので、表示の時間の方が遅いくらいです。

ということで、少し送受信をしていると実感が沸くように1秒間隔で送信することにします。

受信側のコードはそのままで、受信すれば即座に表示するようにします。


 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
'''
(1)送信側プログラム
(2)数字を0~9までバイトデータとして送る
'''
import serial #シリアル通信モジュールをインポート
import time
ser1 = serial.Serial(2) #送信用ポートをOpen

print ('送信用ポート番号:',ser1.portstr) #送信用ポート番号を確認
print('送信テスト')
for i in range(10):
moji0=str(i)
moji1=moji0+'\r\n' #文字列を変数の格納。文字列の最後は改行文字を入れる
moji2=moji1.encode('utf-8') #文字列をバイト型に変換
print(moji0)
ser1.write(moji2) #エンコードしたデータを送信する
time.sleep(1)

syntax2html


17行目 別にたいしたことではなく、さきほどのコードにsleep()関数を追加しただけです。

この関数を使うには、timeモジュールをインポートする必要がありますので、6行目に入れておきます。

受信の結果は、さきほどと何ら変わりなく、1秒おきに表示されることになります。




●5.カンマを挟んで日付と時刻も送信する


次にデータらしくするために日付と時刻を整数のあとにカンマを挟んで送信してみます。

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
'''
(1)送信側プログラム
(2)数字を0~9までバイトデータとして送る
'''
import serial #シリアル通信モジュールをインポート
import time
format = "%Y.%m.%d %H:%M:%S"
ser1 = serial.Serial(2) #送信用ポートをOpen

print ('送信用ポート番号:',ser1.portstr) #送信用ポート番号を確認
print('送信テスト')
for i in range(1000):
t1=time.strftime(format, time.localtime())
moji0=str(i)+','+t1
moji1=moji0+'\r\n' #文字列を変数の格納。文字列の最後は改行文字を入れる
moji2=moji1.encode('utf-8') #文字列をバイト型に変換
print(moji0)
ser1.write(moji2) #エンコードしたデータを送信する
time.sleep(1)

syntax2html


7行目 日付のフォーマット文を入れています。

予想がつくと思いますが、format = "%Y.%m.%d %H:%M:%S"のうち

%Y:年
%m:月
%d:日
%H:時
%M:分
%S:秒

となっています。

13行目 現在時間の日付、時刻を文字列に格納しています。

14行目 文字列化した整数と日時データを連結しています。join()関数という便利なものがありますが、これは別の記事で取り上げたいと思います。


送信結果は以下のとおりです。実際に送信した日付と時刻が1秒毎に記録されました。
(この結果は送信時の出力ですが、もちろん受信データもまったく同じ結果です)


送信結果

Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:15:05) [MSC v.1600 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
送信用ポート番号: COM3
送信テスト
0,2015.12.25 07:34:39
1,2015.12.25 07:34:40
2,2015.12.25 07:34:41
3,2015.12.25 07:34:42
4,2015.12.25 07:34:43
5,2015.12.25 07:34:44
6,2015.12.25 07:34:45
7,2015.12.25 07:34:46
8,2015.12.25 07:34:47
9,2015.12.25 07:34:48
10,2015.12.25 07:34:49
11,2015.12.25 07:34:50
12,2015.12.25 07:34:51
13,2015.12.25 07:34:52
14,2015.12.25 07:34:53






●送信と受信を別々のプログラムにする●

今回、送信プログラムと受信プログラムを別々に作成して、動かしてみました。

通常はひとつのパソコンでこのような送受信をすることはないと思いますが、テストとしては簡単に行うことができます。

実際は、装置からのデータを取り込むことになるので、受信側のプログラムを作り込んでいくことになります。

今後は、送信側を装置のデータを複数準備して、カンマ区切り(CSV)データとして送信し、受信側の作り込みをしていきたいと思います。








Python ブログランキングへ 
クリックしてね


新しいブログをはじめました。pythonの初級者から中級者まで、役に立つ記事を掲載していますので、ご覧ください。

特にカスタム関数(ユーザー定義関数)は、便利に使えると思います。

ぜひぜひこのリンクをクリックしてください 

 Pythonを勉強して株で儲けるブログ