ナルシーNote

2020年12月からC#、2021年2月からPythonを51歳で始めました。学んだことを備忘録として残してます。そろそろN88BASICは卒業しようかな😱

<C#>Listの不要なデータを削除してソートする

 ログファイルから実績数を調べるときに、 LINQを使ったら簡単でしたので紹介します。

 編集したい内容は、

  • 合否判定がPASSのもの
  • 重複したデータは削除する(残すのは最後のデータ)
  • 日時でソート

 というものです。

ログファイルの内容

  • 日時
  • シリアル
  • 合否判定

ログファイルはこんな感じ

f:id:Cars_Narcy:20210526124843p:plain

logファイル

こんなファイルが複数あります。  

 

ファイルからListに入れるところは省略して、

プログラムで入れてみました。

 

プログラムはこんな感じ

List<List> allLists = new List<List>();
{
    allLists.Add(new List { "2021/06/01 09:00:00", "21610001", "PASS" });
    allLists.Add(new List { "2021/06/01 09:03:00", "21610003", "FAIL" });
    allLists.Add(new List { "2021/06/01 09:05:00", "21610003", "FAIL" });
    allLists.Add(new List { "2021/06/01 09:10:00", "21610003", "PASS" });
    allLists.Add(new List { "2021/06/01 09:11:00", "21610003", "PASS" });

    allLists.Add(new List { "2021/06/01 09:02:00", "21610002", "PASS" });
    allLists.Add(new List { "2021/06/01 09:04:00", "21610004", "PASS" });
    allLists.Add(new List { "2021/06/01 09:06:00", "21610005", "PASS" });
    allLists.Add(new List { "2021/06/01 09:07:00", "21610006", "PASS" });
    allLists.Add(new List { "2021/06/01 09:09:00", "21610007", "PASS" });

};

//正常品とシリアルのダブりを除いて日時でソート
IEnumerable <List> targets = allLists
                                    .Where(x => x[2] == "PASS" )
                                    .GroupBy(x => x[1])
                                    .Select(x => x.Last())
                                    .OrderBy(x => x[0]);
foreach (var oneline in targets)
{
    foreach (var item in oneline)
        Console.Write(item + ",");
    Console.WriteLine();
}
    

 

 実行結果

2021/06/01 09:00:00,21610001,PASS,
2021/06/01 09:02:00,21610002,PASS,
2021/06/01 09:04:00,21610004,PASS,
2021/06/01 09:06:00,21610005,PASS,
2021/06/01 09:07:00,21610006,PASS,
2021/06/01 09:09:00,21610007,PASS,
2021/06/01 09:11:00,21610003,PASS,
    

 すごいですね。

見やすいように改行してますけど、実質1行でできちゃいました。

IEnumerable  targets = allLists
                                    .Where(x => x[2] == "PASS" )
                                    .GroupBy(x => x[1])
                                    .Select(x => x.Last())
                                    .OrderBy(x => x[0]);

 

ご使用に関しては自己責任でよろしくお願い申し上げます。

2020年12月に無料のpaizaラーニングでC#を受講しました。

コメントでアドバイスをいただけると幸いです。

 

paizaラーニングはわかりやすかったです。

ありがとうございます。

paiza.jp

<Python>Raspberry Pi でシフトレジスタ74HC595を使う

Raspberry Pi でシフトレジスタ74HC595を使うサンプルです。

 

回路図はこんな感じです。

f:id:Cars_Narcy:20210403134709p:plain

回路図

 こちらのライブラリーを使わせていただきました。

github.com

こんなに便利な情報がいつでも手に入るなんてありがたいです。

素人でも使えました。

本当にありがとうございます。

 

まずはインストールします。

pip3 install git+https://github.com/marsminds/shiftr_74HC595.git

 

プログラムはこんな感じ。

リストpatternsの中身を順番に出力します。

# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
from shiftr_74HC595.shiftr_74HC595 import ShiftRegister
from time import sleep

#数字を8bitバイナリーリストにする
def list_bin(byte, degit):
    _high = 1 #GPIO.HIGH
    _low = 0  #GPIO.LOW
    bits=[]
    for i in range(degit):
        set_bit = _high if byte & (1 << i) else _low
        bits.append(set_bit)
    return bits

if __name__ == '__main__':

    # GPIO.setmode(GPIO.BOARD)
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)

    shift_register = ShiftRegister(data_pin=21, latch_pin=20, clock_pin=19)

    patterns = [1,2,4,8,0x10,0x20,0x40,0x80,0x00,0x55,0xaa,0x55,0xaa,0x00]
    try:
        while True:
            for i in patterns:
                print (format(i, '02x'), end = "=")
                print (i)
                shift_register.setOutputs(list_bin(i,8))
                shift_register.latch()
                sleep(0.5)
    except KeyboardInterrupt:
        shift_register.setOutputs(list_bin(0,8))
        shift_register.latch()
        print ("Ctrl-C - quit")
        GPIO.cleanup()
    

実行するとLEDが点滅します。

抵抗内臓LEDを使用すると配線がすっきりします。 

 

f:id:Cars_Narcy:20210403135728j:plain

(左側に写っている基板は関係ありません)

 

ご使用に関しては自己責任でよろしくお願い申し上げます。


2021年2月に無料のpaizaラーニングでPythonを受講しました。
コメントでアドバイスをいただけると幸いです。

 

paizaラーニングはわかりやすかったです。
ありがとうございます。

paiza.jp

 

<Python>Raspberry Pi でLCDを使う 秋月AE-AQM0802+PCA9515

Raspberry PiLCDを使うサンプルです。

 

秋月電子通商さんで下記のものを購入しました。

akizukidenshi.com

 

Raspberry Pi のGPIO端子に合わせたピン配置となってますので、

直接GPIOにさすこともできます。

f:id:Cars_Narcy:20210321074524j:plain

接続場所

f:id:Cars_Narcy:20210321074559j:plain

取付例

これだと配線図もいらないですね。

 

参考にしたコードはここです。

WiringPi-Pythonを使ってAQM0802A / ST7032i LCD表示 - Qiita

  • カタカナへの変換

I2C 16×2 LCDで日本語(カタカナ)を表示する(pythonプログラムあり) | 空飛ぶラズベリーパイ

 

こんなに便利な情報がいつでも手に入るなんてありがたいです。

素人でも使えました。

本当にありがとうございます。

 

 参考にしたコードをちょこっと変更しました。

内容はさっぱりわかりませんけどね~😅

lcd_aqm0802a.py
# -*- coding:utf-8 -*-
import wiringpi as wp
import time

class LCD_AQM0802A:

    def __init__(self, i2c_addr):
        self.i2c = wp.I2C()
        self.fd = self.i2c.setup(i2c_addr)
        self._init()

    def _init(self):
        self.i2c.writeReg8(self.fd, 0x00, 0x38) # function set: 8 bit, 2 line
        self.i2c.writeReg8(self.fd, 0x00, 0x39) # function set: 8 bit, 2 line, IS=1
        self.i2c.writeReg8(self.fd, 0x00, 0x14) # internal OSC freq
        self.i2c.writeReg8(self.fd, 0x00, 0x70) # contrast set
        self.i2c.writeReg8(self.fd, 0x00, 0x56) # Power/ICON/Constrast
        self.i2c.writeReg8(self.fd, 0x00, 0x6c) # Follower control
        time.sleep(0.2)      # wait time > 200 ms
        self.i2c.writeReg8(self.fd, 0x00, 0x38) # function set: 8 bit, 2 line, IS=0
        self.i2c.writeReg8(self.fd, 0x00, 0x06) # Entry mode set
        self.i2c.writeReg8(self.fd, 0x00, 0x0c) # Display on/off
        self.clear()                            # Clear display

    def set_contrast(self, contrast):
        """ Set contrast (0 - 15). """
        if contrast < 0:
            contrast = 0
        if contrast > 0x0f:
            contrast = 0x0f
        self.i2c.writeReg8(self.fd, 0x00, 0x39)
        self.i2c.writeReg8(self.fd, 0x00, 0x70 + contrast)

    def clear(self):
        """ Clear display and return to home position. """
        self.i2c.writeReg8(self.fd, 0x00, 0x01) # clear display
        time.sleep(0.01)   # wait time > 1.08 ms
        self.i2c.writeReg8(self.fd, 0x00, 0x02) # return home
        time.sleep(0.01)
    
    def set_entry_mode(self, increment, shift):
        mode = 0x04
        if (increment): mode = mode + 2
        if (shift): mode = mode + 1
        self.i2c.writeReg8(self.fd, 0x00, mode)

    def set_cursor(self, y, x):
        """ set cursor location (address counter)."""
        if x < 0: x = 0
        if y < 0: y = 0
        ddram_addr = y * 0x40 + x
        self.i2c.writeReg8(self.fd, 0x00, 0x80 + ddram_addr) # set DDRAM address

    def print(self, str, wait = 0):
        for c in str:
            self.i2c.writeReg8(self.fd, 0x40, ord(c))
            if (wait > 0): time.sleep(wait)

    def katakana(self, text):
        list1a = u"「。、」ヲ・ィァェゥォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜"
        list1b = u"アァイィウゥエェオォカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミ"
        list2a = u"ガギグゲゴザジズゼゾダヂヅデドバビブベボ"
        list2b = u"ザシジスズセゼソゾタダチヂッツナニヌネノ"
        list3a = u"パピプペポ"
        list3b = u"ナニヌネノ"
        
        text_changed = ""
        for l in text:
            if list1a.find(l) >= 0:#カタカナを変換
                text_changed += list1b[list1a.find(l)]
            elif list2a.find(l) >= 0:#濁音を清音+濁点に
                text_changed += list2b[list2a.find(l)]
                text_changed += u"マ"
            elif list3a.find(l) >= 0:#半濁音を清音+半濁点に
                text_changed += list3b[list3a.find(l)]
                text_changed += u"ミ"
            else:#その他の文字はそのままにする
                text_changed += l
        return text_changed

上のコードをlcd_aqm0802a.pyに保存して、下のコードを適当な名前で保存すればLCDが使えます。

GPIOやI2Cを初めて使う方はインストールが必要です。

バックライトも点けてみました。

import RPi.GPIO as GPIO 
import time
from lcd_aqm0802a import LCD_AQM0802A
if __name__ == '__main__':
    
    lcd = LCD_AQM0802A(0x3e)  #addr
    
    GPIO.setmode(GPIO.BCM)    
    GPIO.setup(4,GPIO.OUT)   #Backlight
    
    # show characters in 2 lines
    lcd.set_cursor(0, 0)
    lcd.print(lcd.katakana("ナルシーNote"))
    lcd.set_cursor(1, 0)
    lcd.print('Sample')
    time.sleep(2)

    GPIO.output(4,GPIO.HIGH) #Backlight
    
    #set contract
    contracts = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0]
    for num in contracts:
        lcd.set_contrast(num)
        time.sleep(0.05)
    time.sleep(2)
    
    # LCD clear
    lcd.clear()

    # ticker
    lcd.set_entry_mode(True, True)
    lcd.set_cursor(0, 8)
    lcd.print('cars-narcy.hatenablog.com', 0.3)
    
    lcd.clear()
    GPIO.output(4,GPIO.LOW) #Backlight   
    GPIO.cleanup()   

 

ご使用に関しては自己責任でよろしくお願い申し上げます。


2021年2月に無料のpaizaラーニングでPythonを受講しました。
コメントでアドバイスをいただけると幸いです。

 

paizaラーニングはわかりやすかったです。
ありがとうございます。

paiza.jp

<C#>文字列をテキストファイルから読む

設定ファイルのサンプルです。

テキストファイルをディクショナリに入れて変数のように使用してみました。

'設定ファイルのサンプル
りんご=apple
ばなな	= banana	'こめんと

こちらがコードです。

ClassSettings.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace SampleSettings
{
    class ClassSettings
    {

        public Dictionary<string, string> Settings = new Dictionary<String, String>();

        public string Setting(string skey)
        {
            if (Settings.ContainsKey(skey)) 
            { 
                return Settings[skey];
            }
            else
            {
                return "";
            }
        }

        public bool LoadSettings(string filename)
        {
            //設定ファイルをDictionaryに入れる

            string fullPath = Path.Combine(
                AppDomain.CurrentDomain.SetupInformation.ApplicationBase, filename);

            //ファイルを読み込む
            string sAllData = "";
            if (!LoadFile(fullPath, ref sAllData))
            {
                Console.WriteLine("ファイルが読めません" + fullPath);
                return false;
            }

            //設定をDictionaryに入れる
            string[] sLines = sAllData.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            foreach (var sLine in sLines)
            {
                var sBuf = sLine.Replace("\t", "");                 //TABを削除
                if (sBuf.IndexOf("'") >= 0)
                {
                    sBuf = sBuf.Substring(0, sBuf.IndexOf("'"));    //コメント削除
                }
                if ((sLine.Length > 0) && (sLine.IndexOf("=") > 0)) //設定行なら
                {
                    string[] sValues = sBuf.Split('=');
                    if (!Settings.ContainsKey(sValues[0].Trim()))
                    {
                        Settings.Add(sValues[0].Trim(), sValues[1].Trim());
                    }
                }
            }
            return true;
        }

        private static bool LoadFile(string sFileName, ref string sReadData)
        {
            //テキストファイルを変数に入れる

            StreamReader sr = null;
            try
            {
                if (File.Exists(sFileName))
                {
                    // sr = new StreamReader(sFileName, Encoding.GetEncoding("Shift_JIS"));
                    sr = new StreamReader(sFileName, Encoding.GetEncoding("UTF-8"));
                    sReadData = sr.ReadToEnd();
                }
            }
            catch (Exception)
            {
                return false;
            }
            finally
            {
                if (sr != null)
                {
                    sr.Close();
                }
            }
            return true;
        }
    }
}

 

使い方

using System;
using System.Collections.Generic;

namespace SampleSettings
{
    class Program
    {
        static void Main(string[] args)
        {
            var cs = new ClassSettings();
            if (!cs.LoadSettings("Settings.txt"))
            {
                return;
            }

            Console.WriteLine("①1つずつ表示");
            Console.WriteLine("{0}{1}", cs.Settings.Count, "個の設定があります");
            string str = "りんご";
            Console.WriteLine("[{0}={1}]", str, cs.Setting(str));
            str = "ばなな";
            Console.WriteLine("[{0}={1}]", str, cs.Setting(str));
            str = "いちご";//設定がない
            Console.WriteLine("[{0}={1}]", str, cs.Setting(str));

            Console.WriteLine("②まとめて表示");
            foreach (KeyValuePair<string, string> kvp in cs.Settings)
            {
                Console.WriteLine("[{0}={1}]",kvp.Key,kvp.Value);
            }

            Console.ReadLine();//Enterキーを押したら終了
        }
    }
}

 実行画面 

f:id:Cars_Narcy:20210319063747p:plain

実行画面

 

ご使用に関しては自己責任でよろしくお願い申し上げます。

2020年12月に無料のpaizaラーニングでC#を受講しました。

コメントでアドバイスをいただけると幸いです。

 

paizaラーニングはわかりやすかったです。

ありがとうございます。

paiza.jp

<Python>Raspberry Pi でLCDを使う Longruner LK51

Raspberry PiLCDを使うサンプルです。

 

アマゾンで下記のものを購入しました。

Longruner ディスプレイ R3 Mega2560適応 2004 LCD ディスプレイ モジュール IIC/I2C/TWI ブルースクリーン パネル拡張 ボード 4ピン ジャンパーワイヤーが付き LK51

価格: ¥1,299

VKLSVAN 10個セット 双方向ロジックレベル変換モジュール 4チャンネル 3V~5V IIC I2C ロジックレベル変換器

 価格:¥660(10個入り)

  

表示サンプル

f:id:Cars_Narcy:20210403124458p:plain

表示サンプル

双方向ロジックレベル変換モジュールを使ってこんな風に配線しました。

f:id:Cars_Narcy:20210403123756p:plain

回路図

 

参考にしたコードはこちら。

http://osoyoo.com/driver/i2clcda.py

  • カタカナへの変換

I2C 16×2 LCDで日本語(カタカナ)を表示する(pythonプログラムあり) | 空飛ぶラズベリーパイ

 

こんなに便利な情報がいつでも手に入るなんてありがたいです。

素人でも使えました。

本当にありがとうございます。

 

あとで自分で使いやすいようにClassにしておきました。

 

lcd_lk51.py
# -*- coding:utf-8 -*-
import smbus
import time

class LCD_LK51:
    LINE_1 = 0x80 # LCD RAM address for the 1st line
    LINE_2 = 0xC0 # LCD RAM address for the 2nd line
    LINE_3 = 0x94 # LCD RAM address for the 3rd line
    LINE_4 = 0xD4 # LCD RAM address for the 4th line
    
    # Define some device constants
    CHR = 1 # Mode - Sending data
    CMD = 0 # Mode - Sending command

    BACKLIGHT  = 0x08  # On
    #BACKLIGHT = 0x00  # Off

    LCD_ENABLE = 0b00000100 # Enable bit

    # Timing constants
    E_PULSE = 0.0005
    E_DELAY = 0.0005

    #Open I2C interface
    #bus = smbus.SMBus(0)  # Rev 1 Pi uses 0
    bus = smbus.SMBus(1) # Rev 2 Pi uses 1

    def __init__(self, i2c_addr, lcd_width):
        # I2C device address
        self.i2c_addr  =  i2c_addr       
        # Maximum characters per line
        self.lcd_width = lcd_width
        self._init()
        
    def _init(self):
        # Initialise display
        self.lcd_byte(0x33,self.CMD) # 110011 Initialise
        self.lcd_byte(0x32,self.CMD) # 110010 Initialise
        self.lcd_byte(0x06,self.CMD) # 000110 Cursor move direction
        self.lcd_byte(0x0C,self.CMD) # 001100 Display On,Cursor Off, Blink Off 
        self.lcd_byte(0x28,self.CMD) # 101000 Data length, number of lines, font size
        self.lcd_byte(0x01,self.CMD) # 000001 Clear display
        time.sleep(self.E_DELAY)
    
    def clear(self):
        self.lcd_byte(0x01, self.CMD)
        
    def lcd_byte(self, bits, mode):
        # Send byte to data pins
        # bits = the data
        # mode = 1 for data
        #        0 for command
        
        bits_high = mode | (bits & 0xF0) | self.BACKLIGHT
        bits_low = mode | ((bits<<4) & 0xF0) | self.BACKLIGHT
        
        # High bits
        self.bus.write_byte(self.i2c_addr, bits_high)
        self._lcd_toggle_enable(bits_high)

        # Low bits
        self.bus.write_byte(self.i2c_addr, bits_low)
        self._lcd_toggle_enable(bits_low)

    def _lcd_toggle_enable(self, bits):
        # Toggle enable
        time.sleep(self.E_DELAY)
        self.bus.write_byte(self.i2c_addr, (bits | self.LCD_ENABLE))
        time.sleep(self.E_PULSE)
        self.bus.write_byte(self.i2c_addr, (bits & ~self.LCD_ENABLE))
        time.sleep(self.E_DELAY)

    def print(self, message,line):
        # Send string to display

        message = message.ljust(self.lcd_width," ")
        self.lcd_byte(line, self.CMD)

        for i in range(self.lcd_width):
            self.lcd_byte(ord(message[i]),self.CHR)
    
    def katakana(self, text):
        list1a = u"「。、」ヲ・ィァェゥォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜"
        list1b = u"アァイィウゥエェオォカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミ"
        list2a = u"ガギグゲゴザジズゼゾダヂヅデドバビブベボ"
        list2b = u"ザシジスズセゼソゾタダチヂッツナニヌネノ"
        list3a = u"パピプペポ"
        list3b = u"ナニヌネノ"

        text_changed = ""
        for l in text:
            if list1a.find(l) >= 0:   # カタカナを変換
                text_changed += list1b[list1a.find(l)]
            elif list2a.find(l) >= 0: # 濁音を清音+濁点に
                text_changed += list2b[list2a.find(l)]
                text_changed += u"マ"
            elif list3a.find(l) >= 0: # 半濁音を清音+半濁点に
                text_changed += list3b[list3a.find(l)]
                text_changed += u"ミ"
            else:#その他の文字はそのままにする
                text_changed += l
        return text_changed
        

使い方

# -*- coding:utf-8 -*-
import time
from lcd_lk51 import LCD_LK51
if __name__ == '__main__':   
    lcd = LCD_LK51(0x27,20)#addr=0x27,width=20

    try:
        while True:
            lcd.print(lcd.katakana("ナルシーNote"),lcd.LINE_1)
            lcd.print("Sample",lcd.LINE_2)
            lcd.print("https://cars-narcy.",lcd.LINE_3)
            lcd.print("hatenablog.com/",lcd.LINE_4)
            time.sleep(1.0)
            lcd.clear()
            time.sleep(1.5)
    except KeyboardInterrupt:
        pass

    lcd.clear()
    print ("end")

 

ご使用に関しては自己責任でよろしくお願い申し上げます。

2021年2月に無料のpaizaラーニングでPythonを受講しました。
コメントでアドバイスをいただけると幸いです。

 

paizaラーニングはわかりやすかったです。

ありがとうございます。

paiza.jp

 

<Python>文字列をテキストファイルから読む

設定ファイルのサンプルです。

テキストファイルをディクショナリに入れて変数のように使用してみました。

 

settings.txt

# 設定ファイルのサンプル
item1 = バナナ #TABは消す item2 = りんご #より後ろはコメント扱い item3 = みかん


こちらがコードです。

# coding: utf-8
import os

class Settings:
    ___settings = {"filename":""}
    
    def __init__(self, filename = "settings.txt"):
        self.___filename = filename
        self.___settings["filename"] = filename
        
    def settings(self, itemname):
        if itemname not in self.___settings:
            return ""
        else:
            return self.___settings[itemname]
        
    def loadsettings(self):
        cwd = os.getcwd() #実行中の場所
        cwd_f = cwd + "/" + self.___filename
        print(cwd_f)
        if os.path.isfile(cwd_f) == True:       
            # 他でFileShare.Read で開いていても読める
            with open(self.___filename, encoding='shift-jis') as f:
            #with open(self.___filename, encoding='utf-8') as f:
                test_data = f.read()
        else:
            print ("ふぁいるがないよ~!")
            return (False)

        if len(test_data) > 0 :
            lines = test_data.split('\n')
            for line in lines:
                s = line.replace("\t", "")  #TABは消す
                if "#" in s:                #より後ろはコメント
                    csv = s.split("#")
                    s = csv[0]
                if "=" in s:       
                    values = s.split("=")
                    if values[0].strip() not in self.___settings:
                        self.___settings[values[0].strip()] = values[1].strip()
        return (True)
    

if __name__ == '__main__':
    app = Settings("settings.txt")           
    if app.loadsettings():
        print ("あいてむ1は" + app.settings("item1"))
        print ("あいてむ2は" + app.settings("item2"))
        print ("あいてむ3は" + app.settings("item3"))
        print ("あいてむ4は" + app.settings("item4"))
    print("End")

 

ご使用に関しては自己責任でよろしくお願い申し上げます。

 

2021年2月に無料のpaizaラーニングでPythonを受講しました。

コメントでアドバイスをいただけると幸いです。

 

paizaラーニングはわかりやすかったです。
ありがとうございます。

paiza.jp