2016年12月28日水曜日

Raspberry Pi B + python3 + flask + i2c + PWM まず LCD その2

今回は、前回の続きです。
前回の Flask の Web アプリから入力した文字列を、I2C 接続された LCD に表示させます。

i2c 関係のプログラムを追加します。
i2c_lcd.py です。
前回の「pwm_flask」の下、「pwm_flask.py」と同じ場所に置きます。
ソースはこれで clone できます。
$ git clone git@bitbucket.org:nagasako/pwm_flask.git

ディレクトリの構造はこのようになります。
pwm_flask/
├── i2c_lcd.py
├── pwm_flask.py
├── static
│   └── style.css
└── templates
    ├── base.html
    └── input_text_for_lcd.html

以前は、root でなければ実行できませんでした。
現在は、root でなくても i2c にアクセスできるので、ウェブアプリにしてもそのまま実行できます。

i2c_lcd.py
#!/usr/bin/env python
# coding: UTF-8
'''
$ sudo apt-get install python-smbus i2c-tools

comment out this line in /etc/modprobe.d/raspi-blacklist.conf
blacklist i2c-bcm2708

add the following lines to /etc/modules
 i2c-dev
 i2c-bcm2708
and then reboot.

search all addr.
$ sudo i2cdetect -y 1
'''

import smbus
import time
import datetime


class st7032i:
    def __init__(self, addr=0x3e, ch=1, contrast=0x20):
        try:
            self.addr = addr
            self.ch = ch
            self.bus = smbus.SMBus(ch)
            self.contrast = contrast
            self.reset()
            self.enable = True
        except:
            self.enable = False

    def reset(self):
        contrast_h = 0x70 | (self.contrast & 0x0f)
        contrast_l = 0x54 | ((self.contrast >> 4) & 0x03)
        self.bus.write_i2c_block_data(
            self.addr, 0, [0x38, 0x39, 0x14, contrast_h, contrast_l, 0x6c])
#         // ST7032 Initial Program Code Example For 8051 MPU(8 Bit Interface) の初期化サンプルの通り
#         // Function Set : 8bit bus mode, 2-line mode,normal font,normal instruction mode
#         LCD_write(LCD_RS_CMD, 0b00111000, fd);      // 0x38
#         // Function Set : extension instruction mode
#         LCD_write(LCD_RS_CMD, 0b00111001, fd);      // 0x39
#         // Internal OSC frequency(extension instruction mode)
#         LCD_write(LCD_RS_CMD, 0b00010100, fd);      // 0x14
#         // Contrast set(extension instruction mode) コントラスト値下位4bit設定
#         LCD_write(LCD_RS_CMD, 0b01110000 | (LCD_CONTRAST & 0xF), fd); // 0x78 = 0x70 + 0x8
#         // Power/ICON/Contrast set(extension instruction mode) コントラスト値上位2bit設定
#         LCD_write(LCD_RS_CMD, 0b01011100 | ((LCD_CONTRAST >> 4) & 0x3), fd); // 0x5c + 0
#         // Follower control。internal follower on,
#         LCD_write(LCD_RS_CMD, 0b01101100, fd);      // 0x6c

        time.sleep(0.25)
        self.bus.write_i2c_block_data(self.addr, 0, [0x0c, 0x01, 0x06])
#         // Function Set。normal instruction mode。
#         // LCD_write(LCD_RS_CMD, 0b00111000, fd);   // 0x38
#         // Display On
#         LCD_write(LCD_RS_CMD, 0b00001100, fd);      // 0x0c
#         // Clear Display
#         LCD_write(LCD_RS_CMD, 0b00000001, fd);      // 0x01
#         // Entry Mode Set
#         LCD_write(LCD_RS_CMD, 0b00000110, fd);      // 0x06
        time.sleep(0.05)

    def clear(self):
        if self.enable:
            self.bus.write_i2c_block_data(self.addr, 0, [0x01])

    def mov_to(self, row=0, col=0):
        if self.enable:
            self.bus.write_i2c_block_data(self.addr, 0, [0x80 + 0x40 * row + col])

    def put_str(self, the_str):
        if self.enable:
            self.bus.write_i2c_block_data(self.addr, 0x40, list(map(ord, the_str)))


if __name__ == '__main__':
    try:
        my_lcd = st7032i(0x3e, 1)
        if True and my_lcd.enable:
            while True:
                time_str = datetime.datetime.now().strftime("%H:%m:%S")
                date_str = datetime.datetime.now().strftime("%y/%m/%d")
                my_lcd.clear()
                my_lcd.mov_to(0, 0)
                my_lcd.put_str(date_str)
                my_lcd.mov_to(1, 0)
                my_lcd.put_str(time_str)
                print(date_str + ' ' + time_str)
                time.sleep(1)
        # if False and my_lcd.enable:
        #     light_channel = 0
        #     adc = SpiAdc(light_channel)
        #     if adc is not None and my_lcd.enable:
        #         # Define delay between readings
        #         delay = 1
        #         while True:
        #             # Read the light sensor data
        #             light_level = adc.readChannel()
        #             # light_volts = adc.convertVolts(light_level, 2)

        #             # Print out results
        #             # print("Light: {} ({}V)".format(light_level,light_volts))
        #             # print("%4d %1.2f" % (light_level, light_volts))
        #             the_str = "    " + str(light_level)
        #             my_lcd.mov_to(0, 0)
        #             my_lcd.put_str(the_str[-4:])
        #             # Wait before repeating loop
        #             time.sleep(delay)

    except:
        print("Error accessing default I2C bus")

pwm_flask.py は一部修正です。
#!/usr/bin/env python
# coding: UTF-8
from flask import Flask, request, redirect
from flask import url_for, render_template, flash
# from flask import session, g, abort
from i2c_lcd import st7032i
import datetime


DEBUG = True
SECRET_KEY = 'something_secret_pwm_flask'
USERNAME = 'admin'
PASSWORD = 'adminpass'

app = Flask(__name__)
app.config.from_object(__name__)
# app.run(host='0.0.0.0', port=5000)


@app.route('/')
def input_text_for_lcd():
    return render_template('input_text_for_lcd.html')


@app.route('/send_text', methods=['POST'])
def send_text():
    date_str = datetime.datetime.now().strftime("%y/%m/%d")
    time_str = datetime.datetime.now().strftime("%H:%m:%S")
    msg_text = request.form['msg_text']
    print('send_text msg_text=', msg_text)
    my_lcd = st7032i(0x3e, 1)
    my_lcd.clear()
    my_lcd.mov_to(0, 0)
    my_lcd.put_str(time_str)
    my_lcd.mov_to(1, 0)
    if msg_text:
        my_lcd.put_str(msg_text)
    flash('New entry was successfully posted "' + msg_text + '" at ' + date_str + ' ' + time_str)
    return redirect(url_for('input_text_for_lcd'))


if __name__ == '__main__':
    app.run()

実行はこう。python3 でも動きます。
$ export FLASK_APP=pwm_flask.py
$ python -m flask run --host='0.0.0.0'

プログラム中に「app.run(host='0.0.0.0')」とすれば、他のパソコンからアクセスできるはずなのですが、うまくいかなかったので、export を使う方式にしています。
文字列出力にある「list(map(ord, the_str))」は、python3 の仕様変更のため list が必要になっています。



0 件のコメント:

コメントを投稿