putixの日記

ガジェット好き。iPad mini とオンボロPC を使ってblog更新しています。

GPIO5(raspberry pi その15)

はじめての電子工作ステップ50
(日経linux 2014年11月号)

■ステップ30(DCモーターを動かす)

f:id:putix:20141021215722j:plain
TA7291P
http://akizukidenshi.com/catalog/g/gI-02001/

import RPi.GPIO as GPIO
import time


def forward():
    print "forward"
    GPIO.output(17, True)
    GPIO.output(27, False)
    time.sleep(5)

def back():
    print "back"
    GPIO.output(17, False)
    GPIO.output(27, True)
    time.sleep(5)

def stop():
    print "stop"
    GPIO.output(17, False)
    GPIO.output(27, False)
    time.sleep(5)


GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
GPIO.setup(27, GPIO.OUT)

stop()
forward()
stop()
back()
stop()

GPIO.cleanup()


■ステップ31(グラフィックスLCDで表示)

f:id:putix:20141022022514j:plain
TG12864B-02WWBV
http://akizukidenshi.com/catalog/g/gP-04167/
http://www.geocities.jp/zattouka/GarageHouse/micon/Arduino/GLCD/GLCD.htm
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1176342811


・128x64の黒白(2色)のbmpファイルを用意

f:id:putix:20141022170606j:plain
・sudo apt-get install imagemagick
・convert step31.bmp step31.pbm
・sudo python step31.py

>||
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time


# コマンドの発行
def command(value, mode):
    GPIO.output(pinRS, mode)

    for i in range(len(pinDB)):
        GPIO.output(pinDB[i], (value >> i) & 0x01)

    GPIO.output(pinE,True)
    GPIO.output(pinE,False)


# ページの設定(縦アドレス0~7)
def setPage(value):
    command(0xb8 | (value & 0x07), False)


# カラムの設定(横アドレス0~63)
def setColum(value):
    command(0x40 | (value & 0x3f), False)


# 8ビットのデータを書き込む
# 書込んだ後、カラムアドレスは自動的に次へ移動する
def writeData(value):
    command(value, True)


# ディスプレイのICチップを選択
def selectIC(value):
    # 1=左側ディスプレイのIC1チップ  2=右側ディスプレイのIC2チップ
    if(value == 1):
        GPIO.output(pinCS1, True)
        GPIO.output(pinCS2, False)
    else:
        GPIO.output(pinCS1, False)
        GPIO.output(pinCS2, True)


# 初期化
def init():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(pinRS,  GPIO.OUT)
    GPIO.setup(pinE,   GPIO.OUT)
    GPIO.setup(pinCS1, GPIO.OUT)
    GPIO.setup(pinCS2, GPIO.OUT)
    for i in pinDB:
        GPIO.setup(i, GPIO.OUT)

    GPIO.output(pinRS,  False)
    GPIO.output(pinE,   False)
    GPIO.output(pinCS1, False)
    GPIO.output(pinCS2, False)
    for i in pinDB:
        GPIO.output(i, False)

    time.sleep(0.03)
    for i in [1, 2]:
        selectIC(i)
        command(0xc0, False) # Display start line コマンド
        command(0x3f, False) # Display On コマンド


# 画面クリア
def cls():
    for i in [1, 2]:
        selectIC(i)

        for j in range(9):
            setPage(j)
            setColum(0);

            for k in range(65):
                writeData(0x00)


# pbmデータを画面に転送
def putPBM():
    f = open("step31.pbm", "rb")

    # 改行スキップ
    for i in range(2):
        c = ' '
        while c != '\n':
            c = f.read(1)

    # 配列に読み込み
    img = [[0 for y in range(64)] for x in range(128)]
    for y in range(64):
        for x in range(0, 128, 8):
            c = ord(f.read(1))
            for b in range(0, 8):
                img[x+b][y] = (c >> (7-b)) & 0x01

    # 画面に描画
    for y in range(0, 64, 8):
        for x in range(128):

            if(x > 63):
                selectIC(2)
                xx = x - 64
            else:
                selectIC(1)
                xx = x

            setPage(y / 8)
            setColum(xx)

            chr = 0x00
            for i in range(8):
                chr |= img[x][y + i] << i

            writeData(chr)


pinRS  = 14
pinE   = 15
pinCS1 = 17
pinCS2 = 18

pinDB = 8 * [0]
pinDB[0] = 7
pinDB[1] = 8
pinDB[2] = 9
pinDB[3] = 10
pinDB[4] = 11
pinDB[5] = 22
pinDB[6] = 23
pinDB[7] = 24

init()
cls()
putPBM()

GPIO.cleanup()
||<
xy座標のアドレスの計算が難しく、
一時バッファに格納してから表示するようにしています。
それでもものすごく大変でしたよ・・・。

■ステップ33(A/D変換器で電圧を読み取る)
■ステップ34(センサーで温度測定)
MCP3002
http://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-0AWK
LM35DZ
http://akizukidenshi.com/catalog/g/gI-00116/

・gpio load spi
gcc -o step33 step33.c -lwiringPi
・sudo ./step33

>||
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>

unsigned int readMCP3002(void)
{
    unsigned char data[2];
    data[0] = 0x60;
    data[1] = 0x00;

    wiringPiSPIDataRW(0x00, &data, 2);
    return ((data[0] & 0x03) << 8) + data[1];
}

int main(void)
{
    unsigned int v1;
    float v2;

    if(wiringPiSPISetup(0x00, 3200000) < 0)
    {
        printf ("wiringPiSPISetup failed");
        return EXIT_FAILURE;
    }

    for(;;)
    {
        v1 = readMCP3002();
        v2 = 3.3 * (float)v1 / 1024.0;

        printf("v1=%d, v2=%f\n", v1, v2);
        sleep(5);
    }

    return EXIT_SUCCESS;
}
||<

ステップ34は、配線CH0とCH1を逆にして
ソースを流用すればOKでした。
v2を100倍した値が温度になります。

出力結果(ステップ34)
>||
1=80, v2=0.257812 c=25.781250
v1=80, v2=0.257812 c=25.781250
v1=78, v2=0.251367 c=25.136719
v1=77, v2=0.248145 c=24.814453
v1=77, v2=0.248145 c=24.814453
v1=76, v2=0.244922 c=24.492188
v1=83, v2=0.267480 c=26.748047 # センサーを指でつまむ
v1=89, v2=0.286816 c=28.681643 # 28度
v1=92, v2=0.296484 c=29.648438
v1=93, v2=0.299707 c=29.970703
v1=94, v2=0.302930 c=30.292971
v1=89, v2=0.286816 c=28.681643 # 離した後
v1=85, v2=0.273926 c=27.392578
v1=83, v2=0.267480 c=26.748047
||<
pythonのspiはc言語の皮を被っただけのものだったので
テストコードもc言語で作りました。