メモ日記

実生活やネットで経験したこと調べたことをまとめたサイト

Tips

Arduino(HiLetgo Leonardo Pro Micro)

シリアル通信でLED制御を行う(IDEからとC#から)

#define TX_LED 30

void setup() {
  // put your setup code here, to run once:
  pinMode(TX_LED, OUTPUT);

  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    int inputchar;
    inputchar = Serial.read();
    if(inputchar != -1) {
      switch(inputchar) {
        case 'a':
          digitalWrite(TX_LED, LOW);
          break;
        case 'b':
          digitalWrite(TX_LED, HIGH);
          break;
      }
    }
  }
}

動作確認はマイコンにプログラムを送った後、 IDE-ツール-シリアルポートから、シリアル通信に使うプログラムを起動。

そこでaを入力して送信するとLEDがついてbを入力して送信するとLEDが切れる。

因みに、私が使っているArduinoではRXの方を光らせようとしてもできなかった。 シリアル通信しているときにRXで設定されているLEDが光っていたため、 おそらくそういった関係で光らないのかもしれない。しらんけど。

それからC#からも制御を行うこともできた。下はそのコード。 usingのあたりは追加したもののみ載せてみた。

using System.Threading;
using System.IO.Ports;

namespace SampleSerialPort
{
    class Program
    {
        static SerialPort serialPort;

        static void Main(string[] args)
        {
            serialPort = new SerialPort();
            serialPort.PortName = "COM4";
            serialPort.BaudRate = 9600;
            serialPort.DtrEnable = true;
            serialPort.Open();

            while (true)
            {

                string senddata = Console.ReadLine();
                serialPort.Write(senddata);
                Thread.Sleep(10);
            }

        }
    }
}

これもIDEのツールに似ていて、 起動後にキーボードからaと入力するとLEDがついて、 bと入力するとLEDが消える。

COM4のところは私の環境ではArduinoと通信しているポートがCOM4のため。 それからDtrEnableについては私が使っているもので必須とのこと。 よくわからないけれど。 Thread.Sleepの値はテキトーなので変更してもいいかもしれない。 てか、いらないかも。

キーボード入力(複数)

#include "Keyboard.h"
void setup() {
  // put your setup code here, to run once:
  Keyboard.begin();

  delay(1000);

  for(int i = 0; i < 3; i++) {
    Keyboard.press('a');
    Keyboard.press('b');
    Keyboard.press('c');
    Keyboard.press('d');
    Keyboard.press('e');
    Keyboard.press('f');
    delay(50);
    Keyboard.releaseAll();
    delay(50);
    Keyboard.press('g');
    Keyboard.press('h');
    Keyboard.press('i');
    Keyboard.press('j');
    Keyboard.press('k');
    delay(50);
    Keyboard.releaseAll();
    delay(200);
  }

  for(int i = 0; i < 3; i++) {
    Keyboard.press(KEY_LEFT_CTRL);
    //Keyboard.press(KEY_LEFT_ALT);
    //Keyboard.press(KEY_LEFT_SHIFT);
    delay(50);
    Keyboard.press('1');
    Keyboard.press('2');
    Keyboard.press('3');
    Keyboard.press('4');
    Keyboard.press('5');
    Keyboard.press('6');
    delay(50);
    Keyboard.releaseAll();
    delay(200);
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

キーボード入力のキー複数版。

やはり同時入力は6キーまでらしく、delayで遅らせることでさらに増やせてるっぽい。

同時押しのほうはCtrlのあとすぐにdelayで遅らせて、 そのあと6キー同時入力する感じにしてみた。

時間取得

http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=2524

上のサイトにあったサンプル。時間を取得できるらしい。

unsigned long time;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  time = millis();
  Serial.println(time);

  delay(1000);
}

動作確認はIDE-ツール-シリアルモニタを起動すると時間がでてくる。

キーボード入力

#include "Keyboard.h"

void setup() {
  // put your setup code here, to run once:
  Keyboard.begin();

  delay(1000);

  for(int i = 0; i < 3; i++) {
    Keyboard.press('a');
    delay(50);
    Keyboard.releaseAll();
    delay(200);
  }

  for(int i = 0; i < 3; i++) {
    Keyboard.press(KEY_LEFT_CTRL);
    //Keyboard.press(KEY_LEFT_ALT);
    //Keyboard.press(KEY_LEFT_SHIFT);
    Keyboard.press('1');
    delay(50);
    Keyboard.releaseAll();
    delay(200);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}

LEDチカチカ

基盤にRX LEDとTX LEDという2つのLEDがついているのでそれらを光らせる。 ネットで調べると、 RXはD17、TXはD30をLOWにするとLEDが点灯するとのこと。

#define RX_LED 17
#define TX_LED 30

void setup() {
  // put your setup code here, to run once:
  pinMode(RX_LED, OUTPUT);
  pinMode(TX_LED, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(RX_LED, LOW);
  delay(1000);
  digitalWrite(RX_LED, HIGH);
  digitalWrite(TX_LED, LOW);
  delay(1000);
  digitalWrite(TX_LED, HIGH);
}

これを書き込むと、2つのLEDが交互に点灯するようになる。

接続

Arduino IDEをインストール。 その後、PCとArduinoを接続。

私の使っているものは、 HiLetgo Leonardo Pro Microというもの使っていて、 IDE側ではLeonardoと認識するらしい。 なので、IDE-ツール-ボード-Arduino Leonardoを選択。

ポートも設定しないと書き込めないので、 IDE-ツール-シリアルポートからArduino Leonardoと表示されているものを選択。

これでIDEから書き込めるようになった。

Python

テンプレートエンジン Jinja2

インストール。

pip install Jinja2

テンプレートファイルは次の通り。sample_jinja.tpl.htmlという名前で これから作るpythonスクリプトと同じ階層に保存。

<html>
    <body>
        {# お名前の表示 #}
        こんにちは {{ name }} さん
        <hr />
        <ul>
            {# 持ち物の表示 #}
            {% for item in items %}
                <li>{{ item.name }} : {{ item.number }} {% if item.name == '鉛筆' %}本{% else %}個{% endif %}</li>
            {% endfor %}
        </ul>
    </body>
</html>

Jinja2を読み込んで、テンプレートエンジンをもとにhtmlテキストを出力するプログラム。 FileSystemLoaderの最初の引数はテンプレートファイルが入っているディレクトリを指定。 get_templateはテンプレートファイルの名前を指定。

from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('./', encoding='utf8'))
tpl = env.get_template('sample_jinja.tpl.html')

items = []
items.append({'name':'時計', 'number':1})
items.append({'name':'鉛筆', 'number':5})
items.append({'name':'ノート', 'number':1})

html = tpl.render({'name':'太郎', 'items':items})
print(html)

実行結果は次の通り。

$ python sample_jinja2template.py 

<html>
    <body>

        こんにちは 太郎 さん
        <hr />
        <ul>


                <li>時計 : 1 個</li>

                <li>鉛筆 : 5 本</li>

                <li>ノート : 1 個</li>

        </ul>
    </body>
</html>

テキストと数値、ループの処理とif文の処理のサンプル。if文は無理やり入れた感はあるけれど。

付けたしで、文字列のHTMLタグを有効にしたい場合は {{ tagstr | safe }}のように {{}}のなかでsafeを付ける。この例ではtagstrの中にhtmlタグが含まれている。

Jsonファイル読込

読込用のファイルは下の通り。sample_jsonfile.jsonという名前で保存した。 これから作るpythonスクリプトと同じ階層に。

{
    "title":    "users",
    "data":     null,
    "user_list":    [
        {
            "name":    "Suzuki",
            "age":      20,
            "flag":     true
        },
        {
            "name":     "Sato",
            "age":      22,
            "flag":     false
        }
    ]
}

プログラムは次の通り。

### Jsonファイル読込
import json

with open('./sample_jsonfile.json') as f:
    jsn = json.load(f)
    print('-------------------------------')
    print('そのまま表示')
    print(jsn)
    print('-------------------------------')
    print('キーを取得')
    for jsn_key in jsn:
        print(jsn_key)
    print('-------------------------------')
    print('値を取得')
    for jsn_value in jsn.values():
        print(jsn_value)
    print('-------------------------------')
    print('特定のキーの値を取得')
    print(jsn["title"])
    print(jsn["data"])
    print(jsn["user_list"])
    print('-------------------------------')
    print('リストの子要素を取得')
    for user in jsn["user_list"]:
        print(user["name"])
        print(user["age"])
        print(user["flag"])

実行結果は次の通り。

$ python sample_readjson.py 
-------------------------------
そのまま表示
{'title': 'users', 'data': None, 'user_list': [{'name': 'Suzuki', 'age': 20, 'flag': True}, {'name': 'Sato', 'age': 22, 'flag': False}]}
-------------------------------
キーを取得
title
data
user_list
-------------------------------
値を取得
users
None
[{'name': 'Suzuki', 'age': 20, 'flag': True}, {'name': 'Sato', 'age': 22, 'flag': False}]
-------------------------------
特定のキーの値を取得
users
None
[{'name': 'Suzuki', 'age': 20, 'flag': True}, {'name': 'Sato', 'age': 22, 'flag': False}]
-------------------------------
リストの子要素を取得
Suzuki
20
True
Sato
22
False

ファイルマッチング(glob)

import glob

result = glob.glob('*.py')
print(result)

カレントディレクトリのパターンにマッチングしたファイル名がそのままresult変数にリストとして格納される。

コマンドライン引数(argparse)(count)

import argparse

if __name__=='__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("square", type=int,
        help="display a square of a given number")
    parser.add_argument("-v", "--verbosity", help="increase output verbosity",
        action="count", default=0) 
    args = parser.parse_args()

    answer = args.square**2
    if args.verbosity >= 2:
        print("the square of {} equals {}".format(args.square, answer))
    elif args.verbosity >= 1:
        print("{}^2 == {}".format(args.square, answer))
    else:
        print(answer)

実行結果は次の通り。

$ python sample_argparse4.py 2 -vv

the square of 2 equals 4

$ python sample_argparse4.py 2 -v

2^2 == 4

$ python sample_argparse4.py 2 

4

Vオプションの数で表示が変わる。

Argparse チュートリアル

コマンドライン引数(argparse)(choices)

import argparse

if __name__=='__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("square", type=int,
        help="display a square of a given number")
    parser.add_argument("-v", "--verbosity", help="increase output verbosity",
        type=str, choices=["zero", "one", "two"]) 
    args = parser.parse_args()

    answer = args.square**2
    if args.verbosity == "two":
        print("the square of {} equals {}".format(args.square, answer))
    elif args.verbosity == "one":
        print("{}^2 == {}".format(args.square, answer))
    else:
        print(answer)

実行結果は次の通り。

$ python sample_argparse3.py 2 --verbosity two

the square of 2 equals 4

$ python sample_argparse3.py 2 --verbosity one

2^2 == 4

$ python sample_argparse3.py 2 --verbosity zero

4

文字列でもいけた。公式のサンプルでは数値だったので。

Argparse チュートリアル

コマンドライン引数(argparse)(action="store_true")

import argparse

if __name__=='__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("square", type=int,
        help="display a square of a given number")
    parser.add_argument("-v", "--verbose", help="increase output verbosity",
        action="store_true")    # store_trueはargs.verboseにTrue or Falseが格納されるようにする
    args = parser.parse_args()

    answer = args.square**2
    if args.verbose:
        print("verbosity turned on")
        print("The square of {} equals {}".format(args.square, answer))
    else:
        print(answer)

実行結果は次の通り。

$ python sample_argparse2.py  2 --verbose

verbosity turned on
The square of 2 equals 4

$ python sample_argparse2.py  2

4

squareには整数が格納されるように、type=intで指定。

store_trueでtrueまたはfalseがargs.verboseに格納されている。

Argparse チュートリアル

コマンドライン引数(argparse)

import argparse

if __name__=='__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("echo", help="echo")
    args = parser.parse_args()

    if args.echo:
        print(args.echo)

実行結果は次の通り。

$ python sample_argparse.py abcde

abcde

parser = argparse.ArgumentParser()でパーサーの準備。parser.add_argument(...)でオプションの追加。 args = parser.parse_args()でargsに入力値を格納。 あとはif文でオプション毎の処理を追加していくというのが一連の流れ。

args.echoの中に引数の文字列が入っている。デフォルトでstr型。 --helpの文字列は自動で生成される。

Argparse チュートリアル

コマンドライン引数

import sys

if __name__=='__main__':
    argvs = sys.argv
    argc = len(argvs)

    print(argvs)
    print(argc)

実行結果は次の通り。

$ python sample_argv.py aaa

['sample_argv.py', 'aaa']
2

sys.argvにリストで格納されている。

ファイルへ書き込む

write_text = '''
aaa
bbb
ccc
'''

with open('newfile.txt', mode='w', newline='\n', encoding='utf-8') as f:
    f.write(write_text)

ここでは改行をLF(UNIX系)、文字コードをutf-8に指定している。 プログラムを実行した場所と同じところにnewfile.txtというファイルができていて、 なかを開くとwrite_textの内容が書き込まれている。

ファイルを読み込む

with open('sample_markdown.py') as f:
    read_text = f.read()
    print(read_text)

ここで読み込んでいるのは下のサンプルコード。読み込んだものをそのまま画面出力へ。

MarkdownをHTMLへ変換する

Pythonを使って、MarkdownをHTMLへ変換したときのメモです。

pip経由でmarkdownをインストール。

pip install markdown

extensions=['tables']という指定をしないと、表が作成されない。 他にもエクステンションが用意されているらしいので、調べる必要があるかもしれない。


import markdown

markdown_text = '''
# h1

## h2 

本文

本文2行目

|タイトル1 |タイトル2 |
|---      |---|
|あああああ|アアアアア|
|いいいいい|イイイイイ|
|ううううう|ウウウウウ|
'''

md = markdown.Markdown(extensions=['tables'])
html_text = md.convert(markdown_text)
print(html_text)

実行結果は次の通り


<h1>h1</h1>
<h2>h2</h2>
<p>本文</p>
<p>本文2行目</p>
<table>
<thead>
<tr>
<th>タイトル1</th>
<th>タイトル2</th>
</tr>
</thead>
<tbody>
<tr>
<td>あああああ</td>
<td>アアアアア</td>
</tr>
<tr>
<td>いいいいい</td>
<td>イイイイイ</td>
</tr>
<tr>
<td>ううううう</td>
<td>ウウウウウ</td>
</tr>
</tbody>
</table>

仮想環境作成

Pythonの仮想環境を作るときのコマンド。パソコン環境はDebian(WSL)上にPython3をインストールしている。 同時にVirtualenvもインストール済み。

作業用のディレクトリを作成してその中へ移動後、次のコマンド。


virtualenv --no-site-packages .
source ./bin/activate

1行目はここに仮想環境を作るという意味。 2行目のコマンドを打つと、作った仮想環境のpythonのバイナリが実行できるようになる。

macbookを使っていたときは、1行目のコマンドは次のようにして、pythonのバージョンを指定していた。


virtualenv --no-site-packages -p python3.5 .

3.9.4

virtualenv -p python3.9 .

--no-site-packagesが廃止されたそうで。 デフォルトでそんな感じの動作をするようになったらしい。しらんけど。

ソースコードからインストール

3.9.4(mac)

./configure --prefix=/インストールフォルダ/ --with-openssl=/usr/local/opt/openssl/ --enable-optimizations
make 
make install

インストールフォルダはuserのディレクトリ以下にテキトーにフォルダを作ってそこを指定 user/Python-3.9.4とか

with-opensslを指定する。パスはbrewでインストールしたopensslのパスを指定した。 opensslがうまくいっているかは、pythonをインストールしたあとにimport sslとして、 エラーがでなければok

./python3.9 -m pip install --upgrade pip

上はpipのアップグレード。インストールしたpython3.9のbinディレクトリに移動して、 そこで実行したもの。

C

strcmp

文字列の比較をする

  • 第一引数 < 第二引数 の場合は-1 (第一引数が第二引数より先)
  • 第一引数 > 第二引数 の場合は1 (第一引数が第二引数より後)
  • 第一引数 == 第二引数 の場合は0

ソースは次の通り。

#include <stdio.h>
#include <string.h>

int 
main(void) {
    printf("%d\n", strcmp("aaa", "bbb"));
    printf("%d\n", strcmp("bbb", "aaa"));
    printf("%d\n", strcmp("ccc", "ccc"));
}

出力結果

-1
1
0

ロケール設定

ロケールの設定は、プログラムのコメントにも書いた通り、 locale -aの出力結果に含まれているものから転記する。

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int 
main(int argc, char *argv[]) {
    struct lconv *conv;

    /* setlocaleのロケール設定はlocale -aコマンドの中からそのまま転記 */
    setlocale(LC_ALL, "ja_JP.utf8");

    conv = localeconv();

    printf("数値形式小数点文字: %s\n", conv->decimal_point);
    printf("数値形式整数部セパレータ: %s\n", conv->thousands_sep);
    printf("\n");

    printf("国際通貨記号: %s\n", conv->int_curr_symbol);
    printf("現地通貨記号: %s\n", conv->currency_symbol);
    printf("\n");

    printf("通貨形式小数点文字: %s\n", conv->mon_decimal_point);
    printf("通貨形式整数部セパレータ: %s\n", conv->mon_thousands_sep);
    printf("\n");

    printf("負でない通貨値の符号: %s\n", conv->positive_sign);
    printf("負の通貨値の符号: %s\n", conv->negative_sign);
    printf("\n");

    printf("国際通貨の少数桁数: %d\n", conv->int_frac_digits);
    printf("通貨形式の少数桁数: %d\n", conv->frac_digits);

    return EXIT_SUCCESS;
}

コンパイルは次の通り。

cc -Wall -O2 -std=c11 sample_2.c -o sample_2.out

実行結果は次の通り。

数値形式小数点文字: .
数値形式整数部セパレータ: ,

国際通貨記号: JPY
現地通貨記号: ¥

通貨形式小数点文字: .
通貨形式整数部セパレータ: ,

負でない通貨値の符号:
負の通貨値の符号: -

国際通貨の少数桁数: 0
通貨形式の少数桁数: 0

参考URL C言語関数辞典 - localeconv

Hello world

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

int 
main(int argc, char *argv[]) {
    printf("Hello world!\n");

    return EXIT_SUCCESS;
}

コンパイルは次の通り。

cc -Wall -O2 -std=c11 sample_1.c -o sample_1.out

Java

javapackager

javapackagerを使うとjarファイルからexe形式の実行ファイルを作ることができる。

これがなぜ必要かというと、現在のjavaはjreをユーザーにインストールさせず、 配布する側がコンパクトなjreを同梱させて配布するようにしているらしく、 そのため必要とのこと。なので、jreの配布ということもおこなっていないらしい。

なので、右下にjava updateの通知とかもでなくなる。

それで、このjavapackagerというツールを使って、jarファイルをexe化したので、 そのときに行ったコマンドをメモ。コマンドは次の通り。

自分用のわかりやすさのために複数行になっているけれど、実際は1行。

javapackager -deploy -native image -outdir dist 
-srcdir . -srcfiles MyApp-jar-with-dependencies.jar 
-appclass my.app.MyApp 
-name MyApp -title MyApp -outfile MyApp.exe 

nativeオプションでexeを指定するとインストーラーができあがるらしいが、 自分の環境で行うとwindows defenderのエラーが起きた。そのためimageで行った。 imageでは、そのまま実行ファイルがフォルダにできあがる。自分としては理想な形なのでこちらを採用。

outdirオプションで指定したフォルダ直下にMyAppというフォルダが出来上がり、その中に、 exeファイル等々が展開されている。その中のruntimeフォルダの中にjava.dllといったような、 重要そうなファイルもある。

最後にjarファイルの名前から推測できるかもしれないけれど、 自分がjarファイルを作るときは、mavenのプラグインを使って、 1つのjarにすべて詰め込む形で作っている。

JSON

書き方のサンプル

jsonファイルについてまとめます。

JSONはデータ定義言語のことです。サンプルとしては次のようになります。


{"name": "suzuki"}

決まりとしては次のようなものがあります。

  • 文字コードはUTF-8固定
  • エスケープ文字が使える。
  • 文字列は""で囲む。''はNG。
  • nullを使用
  • 真偽値はtrue false
  • {}を子要素としてもつことができる。階層構造。
  • []で配列をつくることができる。
  • 要素はカンマで区切る。ただ、最後の要素の後にカンマは付けられない。

上記を踏まえてもう一つサンプル。


{
    "title":    "users",
    "data":     null,
    "user_list":    [
        {
            "name":    "Suzuki",
            "age":      20,
            "flag":     true
        },
        {
            "name":     "Sato",
            "age":      22,
            "flag":     false
        }
    ]
}

"flag": falseのあとに,を付けたりするとエラーになる。上のリストの最後の文はこれを言いたかった!!

パソコン

Linux(debian)のデフォルトロケールの変更

私の環境はWSLというウィンドウズ上でDebianを使っていて、 次のコマンドでロケールを変更した。

sudo dpkg-reconfigure locales

コマンドを打つと、Configuring localesというCUIの設定画面に移る。 十字キーで移動して、スペースキーで選択。エンターキーで決定のような操作。 1つ目の画面はシステムで使えるロケールの設定で、 2つ目の画面はデフォルトのロケールの設定。

設定後は、次のコマンドでロケールの確認が行える。

locale -a

echo $LANG

1つ目は、システムで有効化されているロケールの一覧。 2つ目は、デフォルトのロケール。

画面再起動問題

自作パソコンで、CPU、マザーボード、メモリ、グラボを交換した後、 しばらく使っていると、画面が点滅するようになった。 デュアルディスプレイ環境でどちらの画面も点滅、 ディスプレイが再起動してる感じではなかった。


結果として、電源ユニットを容量が大きいものに交換したら治った。

おそらく、グラフィックボードにうまく電源が供給されていなくて、 それによってそのパーツが再起動のような状態になったと思う。 グラフィックは補助電源のようなものはないけれども、交換前は グラボをさしてないので、そのあたりで急に電源容量が増えたためそうなったと思う。

PostgreSQl

psqlログイン

psql -U postgres

データベースを指定する場合

psql -U postgres -d データベースの名前

psqlを終了させる

\q

psqlでデータベース一覧を確認

\l

データベース作成

create database testdb;

データベース削除

drop database testdb;