プログラミング素人のArduino

技術屋の末端。プログラミングは専門外。 電気回路も専門外です。 コードに間違いなど見つけられたら、気軽にコメントください。 VC#始めました。

Visual Studioでpython

Raspberry Piの "Pi" はpythonの "pi" だとか…
ラズパイでプログラミングするためにpythonを使おうと思います。
ラズパイ上でコーディングするのは大変なので、windows上にpythonの環境を構築します。
windows上でコードを作成しラズパイに転送し実行することを目指します。

実はVisual Studiopythonプログラミングができるらしいです。
↓はVisual StudioでのPython設定がインストール済んだところですが。
ここまでは、Visual Studiopython プロジェクトを選択することで、インストールできます。
f:id:s51517765:20170915194134j:plain

ここで、簡単なプログラムを書いて実行してみると、何かErrorになっています。
実は、python本体はインストールされていないようです。
pythonの環境はインストールされたが、python自体はインストールされていないということみたいです、ややこしい。)
f:id:s51517765:20170915194237j:plain

一番上のLink ”Download and Install Python”を選択すると、
このような画面が現れて、pythonのインストールができます。
64bitのPCなのになぜか32bitですがいいのだろうか?
f:id:s51517765:20170915194321j:plain

これでも、まだpythonは動きません。

Visual Studioのメニュウーの 表示¥その他のウィンドウ¥Python Environmentsで Custum を選択しCustumを開き、環境を設定します。
f:id:s51517765:20170915194812j:plain

このような感じで、pythonのpathを設定します。
f:id:s51517765:20170915203306j:plain
applyします。

Python Environmentsで新しく作られた環境を、”Make this the default environment for new project ”をクリックします。
これで、Visual Studioを再起動すると、pythonが使えるようになります。

Visual Studioでpyhthonを開発することで、Debug modeのブレイクポイントも使うことができますし、
予測入力も使うことができます。

ライブラリのインストールはPython Environmentsからpipを選択し、検索します。
f:id:s51517765:20170915210908j:plain

これでひととおり使えそうです。

ちょっと、簡単なプログラムを作ってみましたが、

import datetime

をわすれて、datetime classを使おうとすると、実行して初めて、例外が発生します。

#import datetime   #ここをコメントアウトすると
print("Test_python")
for i in range(10):
    print("Test_python"+str(i))
    if i==5:
        ntime = datetime.datetime.today()  #ここで例外が発生する
        print(ntime)
        print("No = 5")

構文エラーの検知機能がないようです。
これでは、便利さが半減なので”pylint”というエラーチェックツールをインストールします。
これもpipからインストールできます。
これでも、警告の出方が中途半端な気がしますが…。

Raspberry Piでプログラミング

ラズパイ上でプログラミングをしてみます。

まず、Windows PCからリモートデスクトップ接続でラズパイに接続します。

接続できたら画面左上のラズベリーのアイコンから、プログラミング¥Python3(IDLE)を起動します。
f:id:s51517765:20170913224939j:plain
簡単なPythonプログラミングをします。
pythonとはC言語C#のようなプログラミング言語の一つで、今流行りの言語です。
「パイソン」と読みます。
Linuxには標準でインストールされています。
pythonには2と3がありますが、3を使用します。
これらには互換性がないので注意です。

n=0
for i in range(10):
   n=n+i
   print(n)

上のような簡単なプログラムを作成し”test.py” としていったん保存します。
pythonでは”インデント”が重要で、ここでは n=n+i と print(n)をforからさげて、揃えます。

「ctlr + alt + t」でLX Terminalを起動します。

$pwd

で現在のフォルダを確認します。

/home/pi

↑が、LX Terminalが示しているカレントフォルダで、”test.py”を保存した場所と同じようです。
※$があるときは入力を示し、ないときは表示された内容を示します。(もしかしてこういうことか?)

$python3 test.py

と入力すると、Python3でコンパイルされ実行されます。
↓のようにPrint結果が表示されます。

0
1
3
6
10
15
21
28
36
45

このプログラムは、for文でprintを繰り返す簡単なものです。
しかし、リモートデスクトップ接続上では、動作が遅いので、今後はWindows上でファイルを作成しラズパイに転送して実行する方法を検討します。

Raspberry Pi Zero Wにリモートデスクトップで接続する

以下を参考にWin10PCからリモートデスクトップ接続します。
qiita.com

まず、画面左上にあるコマンドプロンプトのようなアイコン"LX Terminal"を開きます。
(写真省略w)
もしくは「Ctlr+Alt+T」というショートカットがあります。

ここで、

$ip -f inet addr

または

$ip route

と入力しEnterします。
$はLinuxのコマンドであるということを示していて、LX Terminalには始めから表示されていますので、入力は不要です。
qiitaでも、人によって$をつけていたりなかったりですね。

英語が読めなくてもなんとなく、xxx.xxx.xxx.xxxのようなものが見つかります。
これが、ラズパイのIPです。
qiita.com

これをアクセス元のWin10でコマンドプロンプトから

ping xxx.xxx.xxx.xxx

TTL=64 とでればOKです。
f:id:s51517765:20170909172601j:plain
これで、Win PCからラズパイがネットワーク的に見えていることが確認できています。
自宅など通常同じネットワークにあるPCであれば、最初の3桁x3の9桁は同じはずです。
(だいたい近い番号にいるので下3桁を総当たりでpingをためしても探すことはできるそうです。)

で、リモートデスクトップを試みるが…
接続できない。

qiita.com

こちらを参考にXRDPをアンインストールして、

sudo apt remove xrdp

tightvncserverをインストールし(2行は、1行ずつ計2つのコマンドを入れるということ)

sudo apt update
sudo apt install tightvncserver

再度XRDPをインストールします。

sudo apt install xrdp

$は省略したりしなかったりします(まだ自分の中で安定していない)

できた!!
f:id:s51517765:20170909175346j:plain
画面は、リモートデスクトップ接続したラズパイ上でLX terminalを立ち上げたところ。

記事は分割しましたが、ラズパイのセットアップからここまでは一気に終わらせていてだいたい3時間ぐらいかかりました。

Linux素人のRaspberry Pi Zero W

f:id:s51517765:20170909154809j:plain

遂に!ラズパイゼロを入手しました。

Arduinoで電子工作を始めるときに、ラズパイとArduinoと悩んでとっつきやすそうなAruduinoを始めてから約2年。
ラズパイはどうしてもLinuxになじみがなく、ネットワーク対応のためか価格も若干高くて抵抗が大きかったのです。
しかし、Zero(W)がでて大きく値段も下がって、しかもスターターキットなどという、Linuxのインストールを補助してくれるものまであるので、購入に踏み切りました。
なんせ、ネットワーク対応なので遊びの幅は大きく広がります。

Amazonにも本当はあるが在庫なしなので、あきばおーで購入しました。
ラズベリー・パイ Raspberry Pi Zero W Starter Kit 8GB 国内正規代理店品 | プレミアム・あきばお~

ラズパイゼロWが本来1300円ぐらいとのことなので、セットだと割高かな?とも思いましたが、
Linux素人なので簡単なのはいい、また結局周辺機器が必要であることを考えればそんなに高くもないと判断しました。
ちなみに、その辺(自宅)にころがっていたタブレット用のUSB電源では起動しなかったので電流の大きい電源は必須のようです。

これが実物。
f:id:s51517765:20170909154815j:plain

こっちは裏面。
f:id:s51517765:20170909154814j:plain

これがSDカード。Micro SDとアダプターがついてます。
よく見ると開封した形跡があります。OSを入れてくれたということですね。
f:id:s51517765:20170909154812j:plain

同封されているものを接続し、最後に電源のUSBを接続すると起動しました。
f:id:s51517765:20170909154816j:plain
ここから実際のOSのセットアップをするようです。
USBは電源のほかに1つしかないので、とりあえずキーボードだけ接続します。
(別途Amazonに発注していたUSBハブが配達ボックスがFullだったためまだ受け取れていない。)
2つのOSから選べということだと思います。
1番目にあるRaspbianを↑↓キーで選択し、Enter。
すると、インストールのアイコンがEnableになるので、"i"キーを押すとスタートします。
f:id:s51517765:20170909154817j:plain

ここから約20分でインストールが完了しました。
f:id:s51517765:20170909160524j:plain
ここで、OKの意味でEnterを押すと再起動?してデスクトップが現れました。
f:id:s51517765:20170909160624j:plain

Raspberry Pi 3 を使ってみる Wi-Fi設定
ここを参考にWifiを設定します。
ここで、キーボードでは操作できないのでマウスに変えました。
設定を日本にすると再起動するように言われますので再起動。
ログイン画面(ユーザー名を聞かれる画面)が出ないのだが、はて?
ま、いっか。

画面右上の赤いマーク(Bluetoothのとなり)をクリックして開きます。
アクセスポイントを選択して、パスワード(Pre Shard Keyと表記)を入力すると接続されました。

CoretweetによるTwitter検索の実装

すでにTwitterに投稿するアプリは作成済みですが、
s51517765.hatenadiary.jp
s51517765.hatenadiary.jp

検索機能を実装しました。

ここからはCoretweetによるTwitter接続ができている前提です。

Twitter APIについては、
GET search/tweets — Twitter Developers
この辺に書かれているらしいですが、実際のところよく解りません。
私の英語力の問題なのか?そもそもの基本的な技術力のためか?

前回同様に、こちらを参考にさせていただきました。
blog.ch3cooh.jp

Twitter上でのグローバル検索。
tokensが有効な状態で、
var result = tokens.Search.Tweets(count => 100, q => keyword);
で検索結果を取得。
検索結果を取得すると変数"result"に値が入りますが、これは配列のようになっていて、Tweet内容のほかに、ユーザー名、言語情報(日本語か英語かなど)、時刻、ロケーション(GPS情報)などが含まれています。
このなかから必要な情報を使用します。

VSのDebugモードで一時停止すると、変数"result"の中身を確認できます。
f:id:s51517765:20170819192657p:plain
このなかの「結果ビュー」を開きます。
配列のように、Tweetが並んでいてこれが↓のコードのvalueと推測できます。
さらにこの中からUserという項目があります。
f:id:s51517765:20170819192711p:plain
これがUser情報と推測できます。
さらにこのUserを開くと"Name"と"ScreenName"がほしい変数であるとわかることができます。

foreachでvalue(個別tweet)に総当たりし、
tring scrName = value.User.ScreenName
のように取得します。
(フォルダ構造もしくはClassのようにピリオド区切りですね)
これで、ユーザーID、ユーザー名、Tweetが取得できました。
↓「電子工作」の検索結果。
f:id:s51517765:20170819192719j:plain

APIでの検索は、複数文節のKeywordを指定すると単語ごとに分割されるようです。
例えば「今日の電子工作」は「今日」and「電子工作」のような扱いになります。orかもしれないし、厳密には不明。
ただし、この論理積も厳密ではなく複数を指定しても一つしか含まれていなくても検索結果として帰ってくることがあります。
厳密に行いたいときは、C#上でTextをクローリングしマッチするかどうか判断する必要があります。

      private void TweetSearch()
        {
            //グローバル検索
            string keyword = "電子工作";
            var tokens = Tokens.Create(API_Key, API_Secret, A_Token, A_TokenSecret);
            var result = tokens.Search.Tweets(count => 100, q => keyword); 
                //countは読み込み数。指定しなければDefoultの数値が入る。
            foreach (var value in result)
            {
                string scrName = value.User.ScreenName; //@User_ID
                string name = value.User.Name; //ユーザー名
                string text = value.Text; //Tweet
                textBoxStatus.AppendText("@" + scrName.ToString() + " / " + name + System.Environment.NewLine + text + System.Environment.NewLine);
            }
        }

タイムラインの取得

 private void getTimeLine()
        {            
            var tokens = Tokens.Create(API_Key, API_Secret, A_Token, A_TokenSecret);
            var home = tokens.Statuses.HomeTimeline();
            foreach (var tweet in home)
            {
              textBoxStatus.AppendText(tweet.Text.ToString() + System.Environment.NewLine);
            }
         }

ユーザー検索

        private void UserSearch()
        {
            var tokens = Tokens.Create(API_Key, API_Secret, A_Token, A_TokenSecret);
             IEnumerable<User> matchedUsers = tokens.Users.Search(q => keyword);
            foreach (var value in matchedUsers)
            {
                string description = value.Description; //自己紹介
                string scrName = value.ScreenName; //@User_ID
                textBoxStatus.AppendText("@" + scrName.ToString() + System.Environment.NewLine + description + System.Environment.NewLine);
            }
        }

自分のTweetの取得

        private void MyTimeLine()
        {            
            var tokens = Tokens.Create(API_Key, API_Secret, A_Token, A_TokenSecret);
                var home = tokens.Statuses.UserTimeline(count => 10);
                foreach (Status status in home) 
                {
                    textBoxStatus.AppendText(status.User.ScreenName +" / " + status.Text+ System.Environment.NewLine);
                }                     
        }

スマホでプログラミング

普段のプログラミングはWindows PCで行いますが、通勤中などスマホでちょっと構文を試してみたいときがあります。

スマホで簡単なプログラミング(主にはコンソールアプリ)ができるものを探しました。
私が、使ってみてそこそこ使えると思ったものを紹介します。
Androidの前提です。

C言語
C4droid
play.google.com
有料ですが、使い勝手は申し分ない。

C Compiler IDE
play.google.com
無料にこだわるならこちら。
こちらはC++も出ている様子。私は使ってませんが。

これらは、それぞれで作成した「.c」ファイルをもう一方で読み込むことも可能。

C#
今のところAndroidアプリは見つけられていない。
そこで、スマホでも使い勝手のいいOnline Compiler。
f:id:s51517765:20170819122356j:plain
https://dotnetfiddle.net/
https://dotnetfiddle.net/Mobile

スマホにこだわらなければ、こちら。
Web-based online coding environment | paiza.IO

人工無能による3目並べ

3目並べとはこのようなものですが、
f:id:s51517765:20170813170441p:plain
三目並べ - Wikipedia

人工知能ならぬ「人工無能」でC#で作成しました。
無能な所以は、Computerは乱数で指すだけだから。

このゲームは今、AI界隈で流行りの「将棋」や「囲碁」と比べて、すこぶる単純で、勝敗判定も総当たりで実現できます。

f:id:s51517765:20170813171000j:plain

ぐぐると、プログラミングしている例はあると思いますが、今回はこんなですが完全自力です。
素人なので、効率的なアルゴリズムではないかもしれませんし、一つどうしても修正できない部分もあります。
//ここだけ強引
と書いてあるところ。
いずれ考えなおして修正します。

using System;
using System.Windows.Forms;

namespace _3x3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        bool teban = true;
        int shouhai = 0;
        int count = 0;
        int[,] Array = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };

        private void Form1_Load(object sender, EventArgs e)
        {                      
        }
        
        private void hantei()
        {
            if (Array[0, 0] == 1)
            {
                button00.Text = "〇";
            }
            else if(Array[0,0]==-1)
            {
                button00.Text = "●";
            }
            if (Array[0, 1] == 1)
            {
                button01.Text = "〇";
            }
            else if (Array[0, 1] == -1)
            {
                button01.Text = "●";
            }
            if (Array[0, 2] == 1)
            {
                button02.Text = "〇";
            }
            else if (Array[0, 2] == -1)
            {
                button02.Text = "●";
            }
            if (Array[1, 0] == 1)
            {
                button10.Text = "〇";
            }
            else if (Array[1, 0] == -1)
            {
                button10.Text = "●";
            }
            if (Array[1, 1] == 1)
            {
                button11.Text = "〇";
            }
            else if (Array[1, 1] == -1)
            {
                button11.Text = "●";
            }
            if (Array[1, 2] == 1)
            {
                button12.Text = "〇";
            }
            else if (Array[1, 2] == -1)
            {
                button12.Text = "●";
            }
            if (Array[2, 0] == 1)
            {
                button20.Text = "〇";
            }
            else if (Array[2, 0] == -1)
            {
                button20.Text = "●";
            }
            if (Array[2, 1] == 1)
            {
                button21.Text = "〇";
            }
            else if (Array[2, 1] == -1)
            {
                button21.Text = "●";
            }
            if (Array[2, 2] == 1)
            {
                button22.Text = "〇";
            }
            else if (Array[2, 2] == -1)
            {
                button22.Text = "●";
            }

            int sum = 0;
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    sum += Array[i, j];

                }
                if (sum == 3)
                {
                   shouhai = 1;
                }
                else if(sum ==-3)
                {
                       shouhai = -1;
                }
                sum = 0;
            }
            for (int j = 0; j < 3; j++)
            {
                for (int i = 0; i < 3; i++)
                {
                    sum += Array[i, j];

                }
                if (sum == 3)
                {
                    shouhai = 1;
                }
                else if (sum == -3)
                {
                    shouhai = -1;
                }
                sum = 0;
            }
            if (Array[0, 0] + Array[1, 1] + Array[2, 2] == 3) //斜め
            {
                shouhai = 1;
            }
            else if (Array[0, 0] + Array[1, 1] + Array[2, 2] == -3)
            {
                shouhai = -1;
            }
            if (Array[2, 0] + Array[1, 1] + Array[0, 2] == 3)  //斜め
            {
                shouhai = 1;
            }
            else if (Array[2, 0] + Array[1, 1] + Array[0, 2] == -3)
            {
                 shouhai = -1;
            }



            if (teban == true)
            {
                count++;
            }
            else if (shouhai == 0)
            {

                DateTime now = DateTime.Now;
                int set;
                set = now.Second + 2;
                if (set > 59)
                {
                    set = set - 60;
                }
                while (DateTime.Now.Second - set != 0) { }

                Random r = new Random();
                int randX = r.Next(0, 3);
                int randY = r.Next(0, 3);
                while (Array[randX, randY] != 0 && shouhai == 0)
                {
                    randX = r.Next(0, 3);
                    randY = r.Next(0, 3);
                }
                Array[randX, randY] = -1;
                teban = !teban;
                hantei();
                count++;              
            }

            if (shouhai == 1)
            {
                MessageBox.Show("You Win!");
            }
            else if (shouhai == -1)
            {
                MessageBox.Show("You Lose!");
                shouhai = 2;
                count = 10;   //ここだけ強引
            }
            else if (count == 9)
            {
                MessageBox.Show("Draw!");
                shouhai = 2;
            }
        }

        private void button00_Click(object sender, EventArgs e)
        {
            if (teban == true)
            {              
                Array[0, 0] = 1;
            }
            else
            {               
                Array[0, 0] = -1;
            }
            teban = !teban;
            hantei();
         }

        private void button01_Click(object sender, EventArgs e)
        {
            if (teban == true)
            {
                Array[0, 1] = 1;
            }
            else
            {               
                Array[0, 1] = -1;
            }
            teban = !teban;
            hantei();
        }

        private void button02_Click(object sender, EventArgs e)
        {
            if (teban == true)
            {               
                Array[0, 2] = 1;
            }
            else
            {
                Array[0, 2] = -1;
            }
            teban = !teban;
            hantei();
        }

        private void button10_Click(object sender, EventArgs e)
        {
            if (teban == true)
            {
                Array[1, 0] = 1;
            }
            else
            {
                Array[1, 0] = -1;
            }
            teban = !teban;
            hantei();
        }

        private void button11_Click(object sender, EventArgs e)
        {
            if (teban == true)
            {
                Array[1, 1] = 1;
            }
            else
            {
                Array[1, 1] = -1;
            }
            teban = !teban;
            hantei();
        }

        private void button12_Click(object sender, EventArgs e)
        {
            if (teban == true)
            {
                Array[1, 2] = 1;
            }
            else
            {
                Array[1, 2] = -1;
            }
            teban = !teban;
            hantei();
        }

        private void button20_Click(object sender, EventArgs e)
        {
            if (teban == true)
            {
                Array[2, 0] = 1;
            }
            else
            {
                Array[2, 0] = -1;
            }
            teban = !teban;
            hantei();
        }

        private void button21_Click(object sender, EventArgs e)
        {
            if (teban == true)
            {
                Array[2, 1] = 1;
            }
            else
            {
                Array[2, 1] = -1;
            }
            teban = !teban;
            hantei();
        }

        private void button22_Click(object sender, EventArgs e)
        {
            if (teban == true)
            {
                Array[2, 2] = 1;
            }
            else
            {
                Array[2, 2] = -1;
            }
            teban = !teban;
            hantei();
        }

        private void buttonRestart_Click(object sender, EventArgs e)
        {
            shouhai = 0;
            count = 0;
            teban = true;
            button00.Text = "";
            button01.Text = "";
            button02.Text = "";
            button10.Text = "";
            button11.Text = "";
            button12.Text = "";
            button20.Text = "";
            button21.Text = "";
            button22.Text = "";

            for (int j = 0; j < 3; j++)
            {
                for (int i = 0; i < 3; i++)
                {
                    Array[j, i] = 0;
                }
            }
        }
    }

    }