「技術」カテゴリーアーカイブ

【ダイエット支援】食事管理機能を検討する。

ダイエット支援ツールは以下のリンク先で運用中です。

https://taki-lab.site:8443

ダイエット支援ツールに食事管理機能を追加したいと思います。

ダッシュボードはこんな感じにしようと思います。

三栄要素をレーダーチャートで表示させます。

Chart.jsを調べたらこんな感じのチャートが表示出来るみたいです。

また、この画面からデータ入力も出来るようにしたいと思います。

詳細画面はこんな感じ。

日付毎に三栄要素とカロリーを一覧表示。

さらに編集画面へのリンクを用意します。

編集画面はこんな感じ。

朝昼晩毎に、食事と栄養素とカロリーを表示します。

入力、編集も可能にします。

その他、ちょっとFitBitアプリの機能っぽいものに仕上げたいと思います。

じゃあ、次回から取りかかりますか。

【ラズパイ】スイッチを動かしてみる。

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

前回はスイッチをはんだ付けして、ブレッドボードに取り付けました。

今回はこのスイッチを動かしてみます。

import RPi.GPIO as GPIO
import time

X_p = 0
Y_p = 0
Z_p = 0
A_p = 0
B_p = 0
C_p = 0
D_p = 0

def PinsInit(x, y, z, a, b, c, d):
    global X_p
    global Y_p
    global Z_p
    global A_p
    global B_p
    global C_p
    global D_p

    X_p = x
    Y_p = y
    Z_p = z
    A_p = a
    B_p = b
    C_p = c
    D_p = d

    GPIO.setup(X_p, GPIO.OUT)
    GPIO.setup(Y_p, GPIO.OUT)
    GPIO.setup(Z_p, GPIO.OUT)
    GPIO.setup(A_p, GPIO.IN)
    GPIO.setup(B_p, GPIO.IN)
    GPIO.setup(C_p, GPIO.IN)
    GPIO.setup(D_p, GPIO.IN)

    GPIO.output(X_p, GPIO.HIGH)
    GPIO.output(Y_p, GPIO.HIGH)
    GPIO.output(Z_p, GPIO.HIGH)

def SW_Sample():
    col = 1
    swState = [0] * 12
    while True:
        if col == 1:
            GPIO.output(X_p, GPIO.LOW)
            GPIO.output(Y_p, GPIO.HIGH)
            GPIO.output(Z_p, GPIO.HIGH)
        elif col == 2:
            GPIO.output(X_p, GPIO.HIGH)
            GPIO.output(Y_p, GPIO.LOW)
            GPIO.output(Z_p, GPIO.HIGH)
        else:
            GPIO.output(X_p, GPIO.HIGH)
            GPIO.output(Y_p, GPIO.HIGH)
            GPIO.output(Z_p, GPIO.LOW)

        # 1押下
        if swState[1] == 0 and col == 1 and GPIO.input(D_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(D_p) == 0:
                print("push 1")
                swState[1] = 1
        # 1押下戻し
        elif swState[1] == 1 and col == 1 and GPIO.input(D_p) == 1:
            print("release 1")
            swState[1] = 0
        # 2押下
        if swState[2] == 0 and col == 2 and GPIO.input(D_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(D_p) == 0:
                print("push 2")
                swState[2] = 1
        # 2押下戻し
        elif swState[2] == 1 and col == 2 and GPIO.input(D_p) == 1:
            print("release 2")
            swState[2] = 0
        # 3押下
        if swState[3] == 0 and col == 3 and GPIO.input(D_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(D_p) == 0:
                print("push 3")
                swState[3] = 1
        # 3押下戻し
        elif swState[3] == 1 and col == 3 and GPIO.input(D_p) == 1:
            print("release 3")
            swState[3] = 0
        # 4押下
        if swState[4] == 0 and col == 1 and GPIO.input(C_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(C_p) == 0:
                print("push 4")
                swState[4] = 1
        # 4押下戻し
        elif swState[4] == 1 and col == 1 and GPIO.input(C_p) == 1:
            print("release 4")
            swState[4] = 0
        # 5押下
        if swState[5] == 0 and col == 2 and GPIO.input(C_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(C_p) == 0:
                print("push 5")
                swState[5] = 1
        # 5押下戻し
        elif swState[5] == 1 and col == 2 and GPIO.input(C_p) == 1:
            print("release 5")
            swState[5] = 0
        # 6押下
        if swState[6] == 0 and col == 3 and GPIO.input(C_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(C_p) == 0:
                print("push 6")
                swState[6] = 1
        # 6押下戻し
        elif swState[6] == 1 and col == 3 and GPIO.input(C_p) == 1:
            print("release 6")
            swState[6] = 0
        # 7押下
        if swState[7] == 0 and col == 1 and GPIO.input(B_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(B_p) == 0:
                print("push 7")
                swState[7] = 1
        # 7押下戻し
        elif swState[7] == 1 and col == 1 and GPIO.input(B_p) == 1:
            print("release 7")
            swState[7] = 0
        # 8押下
        if swState[8] == 0 and col == 2 and GPIO.input(B_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(B_p) == 0:
                print("push 8")
                swState[8] = 1
        # 8押下戻し
        elif swState[8] == 1 and col == 2 and GPIO.input(B_p) == 1:
            print("release 8")
            swState[8] = 0
        # 9押下
        if swState[9] == 0 and col == 3 and GPIO.input(B_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(B_p) == 0:
                print("push 9")
                swState[9] = 1
        # 9押下戻し
        elif swState[9] == 1 and col == 3 and GPIO.input(B_p) == 1:
            print("release 9")
            swState[9] = 0
        # *押下
        if swState[10] == 0 and col == 1 and GPIO.input(A_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(A_p) == 0:
                print("push *")
                swState[10] = 1
        # *押下戻し
        elif swState[10] == 1 and col == 1 and GPIO.input(A_p) == 1:
            print("release *")
            swState[10] = 0
        # 0押下
        if swState[0] == 0 and col == 2 and GPIO.input(A_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(A_p) == 0:
                print("push 0")
                swState[0] = 1
        # 0押下戻し
        elif swState[0] == 1 and col == 2 and GPIO.input(A_p) == 1:
            print("release 0")
            swState[0] = 0
        # #押下
        if swState[11] == 0 and col == 3 and GPIO.input(A_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(A_p) == 0:
                print("push #")
                swState[11] = 1
        # #押下戻し
        elif swState[11] == 1 and col == 3 and GPIO.input(A_p) == 1:
            print("release #")
            swState[11] = 0

        col += 1
        if col > 3:
            col = 1
def __main__():
    GPIO.setmode(GPIO.BCM)
    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:
            SW.PinsInit(21, 22, 23, 24, 25, 26, 27)
            SW.SW_Sample()
            time.sleep(0.1)
    except KeyboardInterrupt:
        GLCD.GLCDDisplayClear()
        GPIO.cleanup()

__main__()

思った以上に長くなった。

まずピン設定ですが、X,Y,Zに繋がるピンが出力用、A,B,C,Dに繋がるピンが入力用になります。

そして、X,Y,ZはHIGHで初期化します。

サンプル処理では、whileの無限ループの中で、

X=LOW、Y=HIGH、Z=HIGH

X=HIGH、Y=LOW、Z=HIGH

X=HIGH、Y=HIGH、Z=LOW

を繰り返します。

その中で、A~Dの中にLOWの信号があれば、X,Y,ZのLOW出力の状態とA~DのLOW入力の状態を

この表に当てはめて、押下されたボタンを特定します。

ただ、無限ループで動いているので、普通に信号だけを見ていると、ものすごい数の入力をプログラムが検出してしまうので、スイッチの状態を保持し、その値と変化があるか、ということを確認する必要があります。

また、物理スイッチが入ったとき、信号が一瞬の短い間、HIGH/LOWを繰り返すような信号になります。

これをチャタリングといいます。

何も対策していないと、スイッチ1回しか押していなくても、プログラムは数回スイッチを押したと判断してしまうことがあります。

なので、それを回避するために、スイッチの検出を行った後、50ミリ秒後にもう一度信号を確認、信号に変化が無ければスイッチオンとする、という風にする必要があります。

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

pi@raspberrypi:~/RaspiDisplayMonitor $ python3 main.py
push 1
release 1
push 2
release 2
push 3
release 3
push 4
release 4
push 5
release 5
push 6
release 6
push 7
release 7
push 8
release 8
push 9
release 9
push *
release *
push 0
release 0
push #
release #
push 1
push #
release 1
release #
push 2
push 8
release 8
push 9
release 9
release 2

同時押しも動きましたね。

これで基本的な動きは出来ました。

次回は、これをモジュール化して今までのプログラムと組み合わせていましょう。

【C#】【ピクロス】【ALTSEED】解析結果をファイルに出力する

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

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

https://github.com/takishita2nd/Picross

今回からは、デバッグ作業をよりやりやすくするために、過去問を一括して解いて正しく解析できているかを確認する仕組みを作っていきます。

そのためには、解析結果をファイルに出力して、照合対象となるデータを作成する必要があります。

なので、以下の様なコードを作成しました。

    class FileAccess
    {
        private const string _outputfile = "output.dat";
        public static void Output(BitmapData[,] bitmapDatas, int row, int col)
        {
            if (File.Exists(_outputfile) == true)
            {
                File.Delete(_outputfile);
            }

            using (var stream = new StreamWriter(_outputfile, true))
            {
                for(int r = 0; r < row; r++)
                {
                    for(int c = 0; c < col; c++)
                    {
                        if(bitmapDatas[r, c].IsPainted())
                        {
                            stream.Write(1);
                        }
                        else
                        {
                            stream.Write(0);
                        }
                    }
                    stream.Write("\r\n");
                }
            }
        }

解析済みのデータbitmapDatasを受け取り、それをファイルに出力します。

色塗りの部分は1、マスク部分は0となるイメージです。

このデータが、

こんな感じになります。

問題データを

こんな感じで用意して、

解析結果データを、

こんな感じで作成しました。

数字で問題と解答が結びついているイメージです。

さて、これで必要な準備が出来ました。

毎回、ピクロスネタをやるとコーディングに膨大な時間を使ってしまうので、今回はサックリやって、続きは次回やります。

【ラズパイ】スイッチを設置して使用できるようにする。

次は、スイッチを繋げてみます。

購入したのはスイッチが12個付いている簡易的なキットです。

この基板に部品を設置して、はんだ付けします。

ダイオード。

向きに注意。

向きを間違えると動きません。

黒い印が付いている方がカソードになります。

基板に向きがきちんと書かれているので、それに従って配置します。

抵抗。

で、これがスイッチ。

はんだ付け完了。

ブレッドボードに設置。

さらに配線も接続します。

もうこれ以上部品を設置するのは不可能ですね。

ちなみに、配線は以下の様になっています。

12SWとあるのが、今回追加したスイッチモジュールです。

スイッチが押されたかの確認は、

X=LOW、Y=HIGH、Z=HIGH

X=HIGH、Y=LOW、Z=HIGH

X=HIGH、Y=HIGH、Z=LOW

の状態を繰り返し、そのときのA,B,C,Dの出力状態(押されたときにLOWになる)を確認します。

XYZとABCDの組み合わせはこんな感じです。

回路はこんな感じ。

これを見たところ、おそらく、スイッチを押していないときは、▼から入ってきた入力がそのままA~Dに流れていく(HIGH)のでしょう。

そして、X~YがLOWの時にスイッチを押すと、▼の入力がスイッチの方へ流れていくので、その結果、A~DがLOWとなるのでは、と思います。

まぁ、この回路を流用すれば、自分で部品を調達してスイッチ回路を組むことも可能でしょう。

次回はこれを動かすためのプログラムコードを作成します。

【北海道大戦】マップと都市をリンクする

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

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

https://github.com/takishita2nd/HokkaidoWar

前回はマップ同士のリンクを作成しました。

ここ、もうちょっと改良します。

すぐ終わります。

マップのプロパティにUp、Down、Left、Rightを追加してそこから隣接するマップを取得させましょう。

    class Map
    {
        public Map Up { 
            get {
                var field = Singleton.GetFieldMap();
                return field.GetMap(_x, _y - 1);
            }
        }

        public Map Down
        {
            get
            {
                var field = Singleton.GetFieldMap();
                return field.GetMap(_x, _y + 1);
            }
        }

        public Map Left
        {
            get
            {
                var field = Singleton.GetFieldMap();
                return field.GetMap(_x - 1, _y);
            }
        }

        public Map Right
        {
            get
            {
                var field = Singleton.GetFieldMap();
                return field.GetMap(_x + 1, _y);
            }
        }
    class FieldMap
    {
        public Map GetMap(int x, int y)
        {
            if(x < 0 || x >= MaxX || y < 0 || y >= MaxY)
            {
                return null;
            }
            else
            {
                return _map[x, y];
            }
        }

これでだいぶ扱いやすくなったはず。

動作結果は前回と同じ。

で、ここからが今回の本題。

マップと都市のリンクを作成します。

マップから所属する都市を取得できるようにします。

まぁ、やっていることは簡単ですが。

    class Map
    {
        public void SetCity(City city)
        {
            _city = city;
        }

        public City GetCity()
        {
            return _city;
        }
    class City
    {
        public City(string name, Point[] points, int population)
        {
            _name = name;
            _population = population;
            _maps = new List<Map>();
            var r = Singleton.GetRandom();
            _color = new asd.Color((byte)r.Next(0, 255), (byte)r.Next(0, 255), (byte)r.Next(0, 255));

            var fieldMap = Singleton.GetFieldMap();

            foreach (var p in points)
            {
                Map m = new Map(p.x, p.y, _color);
                m.SetCity(this);
                _maps.Add(m);
                fieldMap.SetMap(m);
            }
        }

マップに都市を設定する所を追加、マップの生成と一緒に自分自身のオブジェクトを設定する、というようにしました。

で、これを検証するために、選択した都市と隣接する都市の色を変えようと思います。

        private List<City> GetLinkedCities()
        {
            List<City> cities = new List<City>();
            foreach (var m in _maps)
            {
                if (m.Up != null)
                {
                    var c = m.Up.GetCity();
                    if (cities.Contains(c) == false && c != this)
                    {
                        cities.Add(c);
                    }
                }
                if (m.Down != null)
                {
                    var c = m.Down.GetCity();
                    if (cities.Contains(c) == false && c != this)
                    {
                        cities.Add(c);
                    }
                }
                if (m.Left != null)
                {
                    var c = m.Left.GetCity();
                    if (cities.Contains(c) == false && c != this)
                    {
                        cities.Add(c);
                    }
                }
                if (m.Right != null)
                {
                    var c = m.Right.GetCity();
                    if (cities.Contains(c) == false && c != this)
                    {
                        cities.Add(c);
                    }
                }
            }
            return cities;
        }
        public void OnMouse(asd.Vector2DF pos)
        {
            foreach (var m in _maps)
            {
                if(m.IsOnMouse(pos))
                {
                    var info = Singleton.GetInfomationWindow();
                    info.ShowText(pos, _name + "\r\n" + _population.ToString());
                    // test
                    var cities = GetLinkedCities();
                    foreach (var c in cities)
                    {
                        c.linkedCity();
                    }
                }
            }
        }
        //test
        private void linkedCity()
        {
            foreach(var m in _maps)
            {
                m.linkedMap();
            }
        }
    class HokkaidoWar
    {
        public void Run()
        {
            while (asd.Engine.DoEvents())
            {
                FieldMap fieldMap = Singleton.GetFieldMap();
                fieldMap.unlinkMap();

List.Contains(Obj)を使用すると、Listの中にObjと同じ物があるかを確認できます。

自分の都市の隣接する都市なので、自分自身は含めていません。

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

【Laravel】【ダイエット支援】グラフをもっと簡潔に【完成】

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

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

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

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

https://taki-lab.site:8443

前回からあれこれ考えたのですが、

3つのデータを1つのグラフに表示させようというのがよろしくないという結論になりました。

リンクのクリックでグラフを体重、体脂肪率、BMIで切り替えるようにしました。

たいした修正では無いので、ソースは書きませんが、gitHubのソースコードを参照してもらえればと思います。

ついでに軸の設定も変えました。(最大値と最小値)

かなりスッキリして見やすくなったかな。

やっぱりグラフは多くて2つまでかな、と思います。

さて、体重記録機能はほぼ完了しました。

次は・・・食事記録かな・・・。

【ラズパイ】【GLCD】倉田ましろを書いてみる。

こちらのネームクリップの絵がシンプルなデザインなので、この絵を表示させてみたいと思いました。

https://bang-dream.com/goods/1883

InkScapeで画像からトレースして線を書いて、

ドット絵ナニカのサイトで64×64ドットの画像に変換してExcelで出力。

http://dot-e-nanika.com

これを8×8に区分けして、16進数のドットパターンデータに変換(手作業)。

Array = [
    [
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
        0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x20, 0x20,
        0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    ],
    [
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
        0x20, 0x10, 0x08, 0x04, 0x02, 0x82, 0x81, 0x40,
        0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x03, 0x00,
        0x80, 0x41, 0x3B, 0x20, 0x20, 0x20, 0x20, 0x40,
        0x40, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    ],
    [
def drowMashiro():
    for page in range(8):
        for addr in range(64):
            if addr < 32:
                SelectIC(1)
                SetPage(page)
                SetAddress(addr + 32)
            else:
                SelectIC(2)
                SetPage(page)
                SetAddress(addr - 32)
            WriteData(mashiro.Array[page][addr])

で、表示できました。

なかなか良い感じに映っております。

【北海道大戦】マップデータを管理する

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

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

https://github.com/takishita2nd/HokkaidoWar

さて、現状マップデータの管理は、都市オブジェクトの中に所属するマップが格納されていると言う状態で、マップ同士の横のつながりがありません。

このままでは「隣接するマップ」を取り出すことが出来ないので、整理して管理したいと思います。

マップデータは横44マス、縦35マスで構成されているので、二次元配列にするのが最適でしょう。

なので、このデータを管理するクラスを作成し、シングルトンで使用します。

    class FieldMap
    {
        public int MaxX { get { return 44; } }
        public int MaxY { get { return 35; } }

        private Map[,] _map;
        public FieldMap()
        {
            _map = new Map[44, 35];
        }

        public Map GetMap(int x, int y)
        {
            return _map[x, y];
        }

        public void SetMap(Map map)
        {
            _map[map.X, map.Y] = map;
        }

    class Singleton
    {
        private static FieldMap _map = null;
        public static FieldMap GetFieldMap()
        {
            if (_map == null)
            {
                _map = new FieldMap();
            }
            return _map;
        }

で、都市オブジェクトからマップオブジェクトを作成する際に、このクラスにマップオブジェクトも保持させます。

        public City(string name, Point[] points, int population)
        {
            _name = name;
            _population = population;
            _maps = new List<Map>();
            var r = Singleton.GetRandom();
            _color = new asd.Color((byte)r.Next(0, 255), (byte)r.Next(0, 255), (byte)r.Next(0, 255));

            var fieldMap = Singleton.GetFieldMap();

            foreach (var p in points)
            {
                Map m = new Map(p.x, p.y, _color);
                _maps.Add(m);
                fieldMap.SetMap(m);
            }
        }

たぶん、これだけでOKのはずなので、うまく管理出来ているか、テストコードで確認したいと思います。

マウスカーソルのあるマップの隣にあるマップの色を変化させます。

    class City
    {
        public void OnMouse(asd.Vector2DF pos)
        {
            var fieldMap = Singleton.GetFieldMap();
            foreach (var m in _maps)
            {
                if(m.IsOnMouse(pos))
                {
                    var info = Singleton.GetInfomationWindow();
                    info.ShowText(pos, _name + "\r\n" + _population.ToString());
                    // test
                    fieldMap.onMouse(m);
                }
            }
        }
    class FieldMap
    {
        // Test
        public void onMouse(Map map)
        {
            for(int x = 0; x < MaxX; x++)
            {
                for(int y = 0; y < MaxY; y++)
                {
                    if(_map[x,y] != null)
                    {
                        _map[x, y].unlinkedMap();
                    }
                }
            }
            if(map.X > 0)
            {
                if (_map[map.X + 1, map.Y] != null)
                {
                    _map[map.X + 1, map.Y].linkedMap();
                }
            }
            if (map.X < MaxX)
            {
                if (_map[map.X - 1, map.Y] != null)
                {
                    _map[map.X - 1, map.Y].linkedMap();
                }
            }
            if (map.Y > 0)
            {
                if (_map[map.X, map.Y - 1] != null)
                {
                    _map[map.X, map.Y - 1].linkedMap();
                }
            }
            if (map.Y < MaxY)
            {
                if (_map[map.X, map.Y + 1] != null)
                {
                    _map[map.X, map.Y + 1].linkedMap();
                }
            }
        }
    class Map
    {
        // Test
        public void linkedMap()
        {
            var changeColor = new asd.Color(200, 200, 200);
           _geometryObj.Color = changeColor;
        }

        public void unlinkedMap()
        {
            _geometryObj.Color = _color;
        }

うまくいけていると思います。

【ラズパイ】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()の処理も少し修正しています。

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

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

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

何か方法を考えます。