【ラズパイ】GLCDに時刻・気温・湿度・天候情報を表示する

前回までやっていたGLCDをライブラリ化して、gitHubを更新しました。

https://github.com/takishita2nd/GLCD

このGLCDライブラリを使ってGLCDに時刻、気温、湿度、天候情報を表示させたいと思います。

まず、温度、湿度を表示させるために、AM2320周りもライブラリ化しました。

import time
import smbus

i2c = smbus.SMBus(1)
address = 0x5c

def GetTemp():
    loop = True
    block = []
    while loop:
        try:
            i2c.write_i2c_block_data(address, 0x00,[])
            i2c.write_i2c_block_data(address, 0x03,[0x02, 0x02])

            time.sleep(0.05)

            block = i2c.read_i2c_block_data(address, 0, 4)
            loop = False
        except IOError:
            pass
    temp =  block[2] << 8 | block[3]
    return format(temp / 10)

def GetHum():
    loop = True
    block = []
    while loop:
        try:
            i2c.write_i2c_block_data(address, 0x00,[])
            i2c.write_i2c_block_data(address, 0x03,[0x00, 0x02])

            time.sleep(0.05)

            block = i2c.read_i2c_block_data(address, 0, 4)
            loop = False
        except IOError:
            pass
    hum =  block[2] << 8 | block[3]
    return format(hum / 10)

天候データはopenWeatherのWebAPIを利用します。

https://openweathermap.org

openWeatherにした理由は、今のGLCDが半角アスキー文字しか表示できないので、どうしても英語で表示させる必要があります。

なので、海外の英語のAPIを利用させて貰いました。

アクセス回数を絞れば無料で利用できます。

import json
import urllib.request

weather = ""
temp_min = 0
temp_max = 0
temp = 0

def RequestAPI():
    global weather
    global temp_max
    global temp_min
    global temp

    url = 'http://api.openweathermap.org/data/2.5/weather?lat=XXX&lon=XXX&units=metric&appid=XXXXXXXX'
    req = urllib.request.Request(url)
    with urllib.request.urlopen(req) as res:
        body = json.load(res)
        weather = body['weather'][0]['main']
        temp_min = body['main']['temp_min']
        temp_max = body['main']['temp_max']
        temp = body['main']['temp']

def GetWeather():
    return weather

def GetTemp():
    return temp

def GetTempMin():
    return temp_min

def GetTempMax():
    return temp_max

個人情報を含んでいるので、クエリパラメータは書き換えてあります。

これらを使って、GLCDに表示させます。

import RPi.GPIO as GPIO
import time
import datetime
import calendar
import GLCD
import AM2320
import Weather


def __main__():
    GLCD.PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
    GLCD.GLCDInit()
    GLCD.GLCDDisplayClear()

    roop = 10 * 60 * 60
    try:
        while True:
            if roop >= 10 * 60 * 60:
                Weather.RequestAPI()
                weather = Weather.GetWeather()
                temp = Weather.GetTemp()
                roop = 0

            GLCD.GLCDPuts(1, 0, "Date :")
            GLCD.GLCDPuts(10, 8, datetime.datetime.now().strftime('%Y:%m:%d %A'))
            GLCD.GLCDPuts(1, 16, "Weather :")
            GLCD.GLCDPuts(10,24, weather)
            GLCD.GLCDPuts(10,32, "Temp : " + format(temp) + 'C')
            GLCD.GLCDPuts(1, 40, "Time : " + datetime.datetime.now().strftime('%H:%M:%S'))
            GLCD.GLCDPuts(1, 48, "Humidity    : " + AM2320.GetHum() + '%')
            GLCD.GLCDPuts(1, 56, "Temperature : " + AM2320.GetTemp() + 'C')

            roop += 1
            time.sleep(0.1)
    except KeyboardInterrupt:
        GLCD.GLCDDisplayClear()
        GPIO.cleanup()

__main__()

フーフーって聞こえているのは、AM2320に息を吹きかけています。

なんか良い感じだぞ。

配線の見た目をなんとかすれば、そのままインテリアとして使えるかもしれない。

【C#】【ピクロス】【ALTSEED】解析パターン14

前回までの状況はこちら。

最新ソースはこちら。(gitHub)

https://github.com/takishita2nd/Picross

次はここを処理します。

ここは縦の数字がすでに3が塗られているので、上の空いているマスに1マス、下の空いているマスに2マスを塗ることができます。

なので、赤く囲んだ部分は塗れると言うことですね。

これを実装します。

考え方としては、まだ確定していないマスと数字を抽出し、順序関係が一致かつ、数字とマスが一致した場合、そこを塗る、という感じでいきますか。

        // 解析パターンその14
        // 数字と空いているマスを照合して塗る
        private void pattern14()
        {
            // Row
            pattern14Row();
            // Col
            pattern14Col();
        }

        private void pattern14Row()
        {
            int row = 0;
            foreach (var rowlist in rowNumbers)
            {
                if (rowlist.IsAnalyzed())
                {
                    row++;
                    continue;
                }

                // 有効な数字を取り出す
                List<AnalyzeData> aData = new List<AnalyzeData>();
                foreach(var data in rowlist.AnalyzeDatas)
                {
                    if (data.IsAnalyzed())
                    {
                        continue;
                    }
                    aData.Add(data);
                }

                // 対象となるマスを抽出する
                List<List<BitmapData>> bitmapLists = extractTargetBitmapListsCol(row);
                bitmapLists.Reverse();

                // 数字とマスを照合する
                if (bitmapLists.Count != aData.Count)
                {
                    row++;
                    continue;
                }

                AnalyzeData maxData = null;
                int remi = 0;
                for(int i = 0; i < aData.Count; i++)
                {
                    if (maxData == null)
                    {
                        maxData = aData[i];
                    }
                    else
                    {
                        if(maxData.Value < aData[i].Value)
                        {
                            remi = i;
                        }
                    }
                }
                if(maxData != null)
                {
                    if (bitmapLists[remi].Count == maxData.Value)
                    {
                        foreach (var b in bitmapLists[remi])
                        {
                            b.Paint();
                        }
                        maxData.Analyzed();
                    }
                }
                row++;
            }
        }

extractTargetBitmapListsCol()の処理も少し修正しています。

実行結果はこうなりました。

ここまで複雑なロジックを組み合わせていくと、過去の問題が解けなくなっているとか十分あり得るので、その確認が大変です。

なんかもっといい確認方法を考えないといけないかもしれない。

何か方法を考えます。

【ダイエット】実践していることその1、体重計を買うべし

まぁ、まだ自分もダイエット半ばですので、偉そうなことは言えないのですが、

確実に言えるのは、本気で痩せたいなら体重計を買うべし、です。

そもそもの話、体重計に乗って、体重の変化を数字で確認しなければ、痩せたかどうかが分からないじゃ無いですか。

正直言って、これができるかできないかでダイエットに対する本気度がバレてしまうと思います。

そして、体重計を買ったら、毎日体重計に乗って、体重を記録しましょう。

できれば毎日同じタイミングでの計測が良いです。

1日でも時間によって変わりますし、食前食後でも言わずもがなですね。

オススメは朝起きて、トイレに行った直後、です。

オイラはトイレの出口から見えるところに体重計を置いて、朝起きる→トイレに行く→体重計に乗るという導線を作っています。

あと、体重計は自動的に記録してくれるものが非常に便利です。

自分で記録しなくても、アプリとかで確認できる物が良いですね。

オススメはやっぱりfitbitの体重計です。

WiFi経由でスマートフォンのアプリにデータを転送し、いつでもアプリで確認することができます。

あとは、体組成計なども計測できるものもあり、それがあれば体のデータが細かく調べられます。

まぁ、なんであれ、毎日続けられる方法を選んでください。

これ、一番大事。

毎日続けることが重要です。

fitbit Versa2を1週間使用して気が付いたこと

fitbit Versa2の開封記事をこちらに書いたのですが。

1週間使ってみて、気がついたことをまとめました。

高低差が分かるようになった。

高低差が分かるので、例えば何階分の階段を上ったか、というのも記録されるようになりました。

ランニング記録にランニングルートが記録されるようになりました。

おそらく、スマホ端末側のGPS情報を使用しているのでしょうが、ランニングルートも記録されるようになりました。

個人情報を含むのでスクショは取れませんが。

今まではアディダスアプリを使って記録していましたが、これも不要になりますね。

ウォッチフェイスを変更できる。

まぁ、スマートウォッチだから当然だわな。

エクササイズを自動的に認識してくれる。

認識自体はいままでのトラッカーでもできましたが、

例えばランニング中に信号待ちで停止した場合、それも認識してタイマーを止めてくれます。

そして、信号が青になって走り出すと、それも認識してタイマーを再開してくれます。

謎アプリStrava

なんか、エクササイズを行うと、自動的にこのアプリが動作して、何かしてくれるみたいなんですが、いまだに何もしてくれていません。

これ、何なんですかね?

こう見て見ると、やっぱり今までのInspireHRよりも遙かにパワーアップしていますね。

使用していて楽しいです。

いろんなデータが溜まっていき、それを眺めて、また明日も頑張ろうって思えます。

【LARAVEL】【ダイエット支援】グラフのデータ間隔を指定する

前回までの状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/diet-mng

このプログラムはこちらのリンク先で運用中です。

https://taki-lab.site:8443

さて、こちらのグラフなんですが、

現状は最近の10日間のデータをグラフに表示させているのですが、

実際、もっと昔のデータもグラフに出したいじゃないですか。

なので、これをやります。

UIとしては、右下のところに日毎、週毎、月毎のリンクを作成して、それでグラフの切り替えをやっていこうと思います。

まずはフロント部分。

            <div class="command">
                <ul>
                    <li><a @click="onClickDay">day</a></li>
                    <li><a @click="onClickWeek">week</a></li>
                    <li><a @click="onClickMonth">month</a></li>
                </ul>
                <ul>
                    <li><a @click="onClickInput">クイック入力</a></li>
                    <li><a href="/weight">詳細</a></li>
                </ul>
            </div>

こんな感じでリンクを作ります。

フロントの処理はこちら。

        onClickDay: function() {
            this.contents.interval = 1;
            this.graphUpdate();
        },
        onClickWeek: function() {
            this.contents.interval = 7;
            this.graphUpdate();
        },
        onClickMonth: function() {
            this.contents.interval = 30;
            this.graphUpdate();
        },

クリックするリンクでデータ間隔を数字で設定して、APIのパラメータとして与えます。

ではAPIの処理。

    /**
     * グラフ用データを取得する
     */
    public function graph(Request $request)
    {
        return response()->json(['datas' => $this->weightManagement->getGraphData(Auth::user(), $request->contents["interval"])]);
    }
    public function getGraphData($user, $interval, $days = 10)
    {
        $datetimes = [];
        for($i = 0; $i < $days ; $i++) {
            $datetimes[] = date('Y-m-d', strtotime('today - '.($i * $interval).' day'));
        }

        return $user->WeightManagements()
                    ->whereIn(DB::raw('date_format(datetime, "%Y-%m-%d")'), $datetimes)
                    ->get();
    }

実行結果はこちら。

日毎

週毎

月毎

データが少ないからあまり違いがわかりませんが、表示はちゃんと変わってます。

【ナナオン】ガチのバンドリーマーがナナオンをプレイして見た結果。

プレイ開始から2週間ぐらい経過しましたか。

今は、

戦力としてはまずまずで、マルチでもガチプレイヤー共のルームにも入ることができます。

ここまでプレイして見た感想ですが、

見た目とは裏腹に

結構ガチ向けの音ゲー

っていう感じがしました。

例えるならガルパがちょっとぬるま湯で、ナナオンはちょっと熱めの湯って感じです。

譜面がかなりテクニカルな腕前が必要で、HARDレベルでも簡単にフルコンさせてもらえません。

ゲーセンで他のプレイヤーのプレイ画面見て研究している人達の気持ちが分かる。

ガルパは直感である程度攻略できるけど、

ナナオンは譜面を覚えて攻略法を研究しないと難しい

と思いました。

あと、

麗華様嫁にください。

【北海道大戦】人口データを作成・読み込ませる

前回までの状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/HokkaidoWar

北海道大戦では、人口がそのまま戦力値として使用したいと思っています。

なので、人口データを入力します。

こちらに掲載されている人口データを参照しました。

https://uub.jp/cty/hokkaido.html

EXCELマクロを修正して、出力Jsonに人口データを含めます。

あとは、プログラム本体側を修正し、人口データを読み込ませるようにします。

たいした修正では無いので、詳細はgitHubを参照してください。

実行結果はこんな感じになりました。

たぶん、一番人口が少ない音威子府。

そして、一番多いのは、言わずもがな札幌市。

ちなみに、一番人口の少ない市は歌志内市。

【給付金で買った物】ジンギスカンセット

いつか買いたいと思っていた。

カセットコンロ+ジンギスカン鍋。

カセットコンロは比較的安いイワタニ製のものを買いました。

そして、ガスもイワタニ製です。

お鍋は安定のキャプテンスタッグ製のものを購入しました。

このお鍋、鋳物なのですが、シーズニング不要の物でして、最初に洗剤で洗って錆止め剤を落とし、水気を切って、自然乾燥させて、周りに油を塗れば使用できる状態になります。

お手入れもスキレットと同じように扱えばOK。

そして、肝心のお肉はと言うと、

行者ニンニク入りの味付けラムです。

こちらは楽天で購入しました。


とにかく、おうちで本格的なジンギスカンを食べたかったのです。

ところで、行者ニンニクって道外では聞いたこと無いなぁ。

行者ニンニクの認知度ってどれくらいなんですか?

iMac(2015)をどうしようか問題

そういえば、うちにあるiMacがほとんど使われないまま机の上に鎮座しているという事実に気がついてしまった。

購入当時は、iOSのプログラミングを勉強しようと思って、10万円程度で購入しました。

CPUは催促では無かったですが、当時はそこそこのもの。第4世代のCorei5だったと思う。

一時はメインPCとして使用していましたが、結局メモリが8GBしかないことに不満があり、ノートPC(Windows、SSD、メモリ16GB)を購入して以来はほとんど使用していないままテーブルの上に存在していました。

SSDに慣れてしまったら、HDDには戻れません。

しかも結構ディスプレイが大きいのよ。

で、iMacを退かしたら、広いスペースができました。

これは・・・

ディスプレイもう一個買っちゃう?

今のメインPC、メモリ32GBだからディスプレイ余裕で一個追加できるよぉ。

なんなら4枚まで追加できるよぉ。

とりあえず、今のディスプレイと同じ大きさのディスプレイを購入しました。

12000円。

そして、最終的にiMacをどうするか問題に行き着く。

iOSのプログラミングって、そんなにやる機会って無いよね。

売るとしたら、どれくらいするんだろう?

2~3万ぐらい出るかな?

調べてみます。

【ラズパイ】【温湿度計】温湿度計AM2320を使用する。

さて、GLCDもある程度やり尽くしたので、新しいデバイスを使用することにしました。

温湿度計AM2320です。

設置。

配線はこんな感じ。

このデバイスはI2Cバスを使用して温湿度を取得することができます。

I2Cバスってなんぞや?ということなんですが、SDL/SDAの2ピンを使ってデータを送受信できるみたいです。

具体的には、SDLにクロック信号と組み合わせてSDAにデータを送信して・・・

って難しいことを考えなくても、ラズパイにはI2Cに対応したモジュール・ライブラリがあるんです。

ちょっと設定を弄るんですけどね。

こちらのサイトを参考にさせて頂きました。

https://qiita.com/twinoze/items/c960eea23c57e342ea4b

先人の知恵を借りるのは大事。

sudo raspi-config

でコンフィグメニューが出るので、

これでI2Cが有効になります。

i2cdetect -y 1

5cと表示できれば認識しているとのことです。

が、100%認識できるかというと、大体50%ぐらいの確立で認識できないケースがありました。

バスリピータを使えば回避できるとのことですが、こう何度も発注を繰り返すと送料が高く付いてしまうので、プログラム側で回避することにしました。

このようにサンプルコードを作成しました。

import time
import smbus

i2c = smbus.SMBus(1)
address = 0x5c

loop = True
block = []
while loop:
    try:
        i2c.write_i2c_block_data(address, 0x00,[])
        i2c.write_i2c_block_data(address, 0x03,[0x00, 0x04])

        time.sleep(0.05)

        block = i2c.read_i2c_block_data(address, 0, 6)
        loop = False
    except IOError:
        pass

hum = block[2] << 8 | block[3]
temp = block[4] << 8 | block[5]

print('hum : ' + format( hum/10) + ' %Rh')
print('temp: ' + format(temp/10) + ' digC')

smbusというライブラリを使えば、I2Cバスへのアクセスが簡単になります。

タイミングチャートとか意識する必要なく、全部ライブラリでやってくれます。

やるべきことは、

  • 初期化
  • ファンクションコード0x03にスタートアドレスとレジスタ数を書き込み
  • データを読み取り

これだけ。

これはデータシートにある、

この部分に合致しています。

そして、I2Cにアクセスできない場合がある問題はtry/catch処理で回避させました。

エラーが発生したら、アクセスが成功するまで再試行を繰り返します。

これで100%アクセスに成功できます。

さて、次回はこれをライブラリ化させてGLCDに表示させましょうか。