ラベル Python の投稿を表示しています。 すべての投稿を表示
ラベル Python の投稿を表示しています。 すべての投稿を表示

2014年5月18日日曜日

Raspberry pi で Hydroponic に挑戦 (9) ポンプコントロール

今日は 午前中 水耕栽培の培養液を循環させるポンプをコントロールするタイマー機能をプログラムに追加。
Python time module の 詳細は 15.3. time — Time access and conversions を参照。


ママチャックの希望で 昼と夜、二種類ポンプの間欠頻度を設定できるようにした。

Linux上のwxPythonのCombo Box では フォントサイズが変えられないバグが有る。本当はもっと大きなフォントにしたいのだが・・・・・・
ポンプコントロールのハードウェアはリレーなどの 部品を中国に発注済。後日部品入手後、組み込むことにする。

午後は床下に潜り込んで Cat5 ケーブルをデッキ下まで引き回す。

2014年5月17日土曜日

Raspberry pi で Hydroponic に挑戦 (8) データ保存

Hydroponic controller プログラムに データ保存機能を追加。


pH と温度データを CSV形式で保存


保存したデータを Libre Office で開いて、グラフ化してみた。

2014年5月11日日曜日

Raspberry pi で Hydroponic に挑戦 (7) wxpython で GUIプログラミング

今週末は wxpython を利用して、Python のGUI プログラミングに初挑戦。
ママチャックでも簡単に使えるようにするにはやはりGUI にするしかないからね。
まずは Raspberry pi に wxpython をインストール。
Raspberian のターミナルから sudo apt-get update してから sudo apt-get install python-wxgtk2.8 とタイプする。途中インストール続行を訪ねてくるので Y と入力。

今まではVisual Basic でしか GUIプログラミングの経験がなかったのでずいぶん勝手が違う。
wxpython の基本情報は python-izm を参考にする。
プログラミング上必要になるRGBカラーコードは The Other RGB Color Chart を参照。
Visual Basic では コントロールオブジェクト配列は簡単に作成できて 配列インデックスで簡単に参照できたのだが wxpython ではそう簡単ではない。 複数の Widgets を一つのハンドラーで扱う方法は wxPython: Binding Multiple Widgets to the Same Handler を参考にする。
Event driven プログラミングで自動計測制御するには絶対必要になるタイマーコントロールも Visual Basic では タイマーコントロールアイコンをフォーム上に配置すればすむ。wxpython では 同じような wx.Timers というWidget があるのだが、どうもこのタイマーは Class の中でしか使用できないらしい。wxPython: Using wx.Timers を参考にする。
Python でのDate とTime の扱いは Python Date & Time を参考
MassageDialog 表示後の処理は Getting started with wxPython を参考にする。

まる2日かけて何とかpHと温度の測定、pHのキャリブレーションができるようになった!


Android タブレット Asus MeMO Pad HD7 にも VNC viewer をインストールし、
タブレットからも Raspberry pi 上の GUIプログラムにアクセスできるようにした。

2014年4月26日土曜日

Raspberry pi で Hydroponic に挑戦 (5) MinipH I2C pH interface から Rawデータ取得

今日は MinipH I2C pH Interface board をRaspberry pi に繋いで pH のRaw データを取得することを目指す。このボードを使用した Arduino のサンプルプログラムはネット上にあるのだが、Raspberry pi、Python 上で使用するサンプルプログラムが見つからない。そこでこのボードで使用している A/Dコンバータ MCP3211 を使用したPython のサンプルプログラムを探してみるが、これも全く見つからない。困ったなぁ。自力でコードを書かなければ・・・・・・・
3枚のインターフェースボードを入手したのだが、そのうちの2枚が同じアドレスのため一つのI2Cバス上では2枚までしか使用できない。とりあえずは2枚のインターフェースボードを使用することにし、残りの一枚は別のアドレスのボードに交換してもらうよう製作者に依頼する。


2枚のボードを繋ぐ。

このインターフェースボードは I2C プロトコルでRaspberry pi と通信を行う。Raspberry pi はすでに I2C セットアップを済ませてあるので、sudo i2cdetect -y 1 とタイプし、2枚のボードのアドレスが認識されることを確認する。


アドレスは 0x4c と 0x4e

Raspbian には SMBus (System Management Bus) という I2Cのサブセット通信プロトコルが用意されているので、このプロトコルを使用して I2C 機器と通信を行う。
1枚のボードに pHプローブシュミレータを繋ぎ、 pH を 4,7,10 と変化させて、データを読み取るSMBusコマンドをいくつか試してみる。データは取得できるのだが、どれもpH の変化に対応していない。困ったなぁ。
そこで、A/Dコンバータ MCP3211 のデータシート と SMBus Protocol Summary を見比べてみる。すると MCP3211 の12bit データは Upper Data Byte、Lower Data byte の順に送り出されるのに対して、 SMBus プロトコルで i2c_smbus_read_word_data() はLower Data byte、 Upper Data byte の順に読み込まれることになっている。それなら i2c_smbus_read_word_data() でデーターを読み、その 16bit データーの上位バイトと下位バイトを入れ替えれば良いはずだ。そこで ネット上にある バイトを入れ替えるプログラムを参考に Python でコードを書いてみる。


############################################################
#                                                          #
#    Read pH data from 2 MinipH I2C pH interface boards   #
#                                                          #
############################################################

import smbus
import time

bus = smbus.SMBus(1)
pH_address = [0x4c, 0x4e]

def readRawpH(address):
    raw_word= bus.read_word_data(address, 1)
    swapped_word = swap_bytes(raw_word)
    
    return swapped_word

def swap_bytes(word):
    byte_low = word & 0x00FF
    byte_high = (word & 0xFF00) >> 8
    swapped_high = byte_low << 8
    swapped_word = swapped_high + byte_high

    return swapped_word   

while True:
    for ad_index in range(len(pH_address)):
        i = 0
        raw_ph = 0
        while i < 100:
            raw_ph += readRawpH(pH_address[ad_index])
            time.sleep(0.01)
            i += 1
        raw_ph = raw_ph / 100
        print'Sensor#%d: %d,' % (ad_index,raw_ph), 
    time.sleep(1)
    print



このプログラムを走らせてみると、


pH4の時 Rawデータ は約1000、 pH7で約2000、pH10で約3000 となった。pH0 で 0, pH14 で 4095(12bit) とすればおおよそ合っているようだ。

2014年4月20日日曜日

Raspberry pi で Hydroponic に挑戦 (4) DS18B20 温度センサー

さて、いよいよ Hydroponic に使用する温度センサーをRaspberry pi に繋いでみよう。今回使用するのは DS18B20 という デジタル温度センサー、 1-Wire バスを使用して Raspberry pi と通信する。このセンサー一つ一つに固有の64bit コードが書き込まれているので、一つのバスに幾つもの温度センサーを繋ぐことができるのだ。
Arduino では 別にこのセンサーアドレスを調べるプログラムをインストールしなければならなかったが、Raspbian には すでにこの1-Wire 温度センサーのデーターを読み込むライブラリが用意されているので、Adafruit's Raspberry Pi Lesson 11. DS18B20 Temperature Sensing に従って、3本のセンサーをBread board に繋ぎ、アドレスを調べる。



000005cd2b5e、000005cd67f7、000005cd2b5e が3本のセンサーのアドレス。
22625(22.625℃)が センサー000005cd2b5e の温度。

Lesson 11 に従って、 Python 上でプログラミング。このプログラムは Root 権限がないと動かない。パパチャックは Raspbian に付属の IDLE という Python 開発環境 でプログラミング しているのだが、 デスクトップ上の IDLE アイコンをダブルクリックして起動すると、Root権限が無いためこのプログラムは動かない。
そこで、Raspbian デスクトップから LXTerminal を起動し、sudo idle とタイプして IDLE にRoot権限を与えて起動する必要がある。
Lesson 11 のプログラムは一つのセンサーから温度データーを読むプログラムなので、それを 先ほど取得したセンサーアドレスを使用して3つのセンサーから同時に温度データーを読み込むように改良。

以下がプログラムコード

#######################################################
#                                                     #
#    Read Temperature data from 3 DS18B20 sensors     #
#                                                     #
#######################################################

import os
import time

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

device_address = ['000005cd2b5e', '000005cd67f7', '000005cda0da'] #Sensor addresses
device_prefix = '/sys/bus/w1/devices/28-'
device_suffix = '/w1_slave'

def read_temp_raw(address_index):
    device_file = device_prefix + device_address[address_index] + device_suffix
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines

def read_temp(adrs_index):
    lines = read_temp_raw(adrs_index)
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw(adrs_index)
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos+2:]
        temp_c = float(temp_string) / 1000.0
        #temp_f = temp_c * 9.0 / 5.0 + 32.0
        return temp_c
 
while True:
    for ad_index in range(len(device_address)):
        print'Sensor#%d: %05.2f C,' % (ad_index, read_temp(ad_index)),
    time.sleep(1)
    print