眼鏡っ娘と付き合いたい

海に近い田舎に住む高専生です。プログラミングについて書きます。

超音波センサーで読み取った値をリアルタイムにプロット(Python, Nucleo, mbed)

ざこざこ高専一年生のかんたろうです。
最近部活(ロボット部)で超音波センサーを触るので、勝手に遊びました。

環境は

  • WSL
  • Python3
  • matplotlib

です。

Nucleoから生えてる超音波センサーで読み取った値をシリアル通信でPCに送っています。

import serial
from time import sleep
import matplotlib.pyplot as plt
import numpy as np

se = serial.Serial('/dev/ttyS5', 9600)

fig, ax = plt.subplots()

x = np.arange(0, 10, 0.1)
y = np.zeros(100).tolist()
line, = ax.plot(x, y)

while True:
    distance = int(se.readline().decode().replace('\n', ''))

    y.pop(0)
    y.append(distance)
    line.set_data(x, y)

    ax.set_xlim((x.min(), x.max()))
    ax.set_ylim((0, np.array(y).max()*1.1))
    plt.pause(0.1)

動かしてみた様子

www.youtube.com

以上です。
Nucleo側のプログラムに不備が見つかったので、今度それを直します。
早くロボコニストを名乗れるレベルになりたいものです。

DiscordのBotを無料で24時間稼働にできた

DiscordのBot開発に興味があって色々やってたんですけど、常に動かせる場所がありません。

そこで、最近はじめたRailsチュートリアルで使っているHerokuをどうにか活用できないかと思い、調べてみた所やってる人が既にいました。

こいつぁすげぇやと思い、色々な記事を見ながらやっていたら僕のBotも24時間稼働になりました。

以下、参考にした記事

boostlog.io

qiita.com

やったねたえちゃん

Discordの翻訳Botを作った

はじめに

試験期間中に湧き上がる謎の創作意欲に駆られて作ってしまいました。

言語は現在勉強中のPython、ライブラリは、googletransを使っています。

ほんへ

import discord
import googletrans
import asyncio

#受け取るコマンドの接頭辞
PREFIX = "$"

#Botのトークン
TOKEN = "your token"

translator = googletrans.Translator()
client = discord.Client()


#コマンドが増えたときのためのデコレータ
def deco(f):
    async def wrapper(message):
        temp = message.content.split(" ", 1)
        if temp[0] == PREFIX + f.__name__ and client.user != message.author:
            arg = temp[1] if len(temp) > 1 else None
            await f(message, arg)
#ユーザから受け取った文字列を引数として渡す
    return wrapper

#コマンドごとに関数を作る
@deco
async def trans(message, arg):
    if arg is not None:
        text = translator.translate(arg, src='en', dest='ja').text
        await client.send_message(message.channel, text)

#書いた関数をfuncsに入れる
funcs = [trans]

#ログインした時の処理
@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('-------------')

#メッセージを受け取った時の処理
@client.event
async def on_message(message):
#funcsに入っている関数を全部呼び出す
    for f in funcs:
        await f(message)

client.run(TOKEN)

Discord側からは、

$trans <text>

の形式で呼び出せます

https://gyazo.com/813a2c1f7339d52e5293f36372772b68

今回頑張ったのは、デコレータを使ってメッセージに対する判定をまとめた事です。

今回は1つなので関係ありませんが、コマンドが増えたときにリストに入れるだけで良いので楽になります(多分)。

デコレータ覚えたてで使いたかったというのもあるのですが、他に効率的な書き方があったら是非教えてください。

2018/06/16追記

こちらのサンプルコードを参考にすれば、簡単にif地獄を抜け出せるみたいです。
自前デコレータなんか使わずにこれ参考にしましょう
discord.py/basic_bot.py at master · Rapptz/discord.py · GitHub

おわりに

デコレータと非同期処理の勉強に滅茶苦茶時間使いました。

その割にはあんまり理解できていないので、もっと頑張ります。

お世話になった記事

Python – googletransを試してみました。 | Developers.IO

(第二回)PythonでDiscordのBotを作る

はじめに

今回はGitHubに載っているサンプルコードを見ながら、Botに簡単な機能を実装してみます。

前回

PythonでDiscordのBotを制作してみる - 眼鏡っ娘と付き合いたい

サンプルコードに学ぶ

いきなり書けと言われても難しいので、サンプルコードを読み解いていきます。 一応リンクを貼っておきます。

GitHub - Rapptz/discord.py: An API wrapper for Discord written in Python.

import discord
import asyncio

client = discord.Client()

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

@client.event
async def on_message(message):
    if message.content.startswith('!test'):
        counter = 0
        tmp = await client.send_message(message.channel, 'Calculating messages...')
        async for log in client.logs_from(message.channel, limit=100):
            if log.author == message.author:
                counter += 1

        await client.edit_message(tmp, 'You have {} messages.'.format(counter))
    elif message.content.startswith('!sleep'):
        await asyncio.sleep(5)
        await client.send_message(message.channel, 'Done sleeping')

client.run('token')

何がなんだかわからないよ

取り敢えず動かす

適当なファイル名をつけて実行してみましょう。拡張子は.pyです。

・・・多分エラーが出ます。

お気付きかと思いますが(僕は気付きませんでした)、最後の行のclient.run('token')の引数には、トークンを文字列として渡す必要があります。

ということで、前回使ったDiscordの開発者向けのサイトから、トークンを取得します。 製作中のBotの設定を開き、click to revealをクリックして出てきた文字列をコピーします。

https://gyazo.com/8d79190de44461823e840ea5ea4b4bea

当たり前な話ですが、トークンは絶対に他人に教えないでください。 僕は一度痛い目を見ています・・・

取り敢えずこれで実行してみましょう。

$ python bot.py
Logged in as
kantarowBot
450221997486637066
-------------

ログインメッセージがコンソールに表示されましたね。

次は、サーバー内から使ってみましょう。

!test!sleepが使えます。

https://gyazo.com/eb6e809189ea40c502981201b5bb2267

編集済みとなっているのは、Bot自身が書き換えているからです。

サンプルコードのasync def on_message(message):以降を見てみましょう。

特にこれと言った難しいところはありません。

!testの本体はここです。

async def on_message(message):
    if message.content.startswith('!test'):
        counter = 0
        tmp = await client.send_message(message.channel, 'Calculating messages...')
        async for log in client.logs_from(message.channel, limit=100):
            if log.author == message.author:
                counter += 1
        await client.edit_message(tmp, 'You have {} messages.'.format(counter))

if文で受け取ったメッセージが!testで始まっているかどうかを判定していますね。

また、送信元のチャンネルに、Calculating messages...と送信しています。

その後、for文でログを辿って、messageの送信者によるメッセージの個数を数えています。

計算が終わると、先程自分で送ったメッセージを書き換え、計算結果を表示しています。

自分で書いてみる

サンプルコードを眺めていても面白くないので、少しだけ自分でプログラミングしてみます。

今回は、Botに対して挨拶をすると、返事をしてくれる機能を実装します。

import discord
import asyncio

client = discord.Client()

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

@client.event
async def on_message(message):
    if message.content.startswith('!test'):
        counter = 0
        tmp = await client.send_message(message.channel, 'Calculating messages...')
        async for log in client.logs_from(message.channel, limit=100):
            if log.author == message.author:
                counter += 1

        await client.edit_message(tmp, 'You have {} messages.'.format(counter))
    elif message.content.startswith('!sleep'):
        await asyncio.sleep(5)
        await client.send_message(message.channel, 'Done sleeping')

    #ここから

    elif message.content.startswith('!hello'):
        await client.send_message(message.channel, 'Hello,{}!'.format(message.author.name))

    #ここまで

client.run('token')

書いたのは二行だけですが、ちゃんと動きます。

https://gyazo.com/05c3f341fca968670f79d598c26ae00f

!helloと言うと、Hello,{user_name}!と答えます。

段々楽しくなってきました。

おわりに

今回やったのはとても簡単なことですが、次回以降は何かしら面白い機能を持ったBotを作りたいと思っています。

(第一回)PythonでDiscordのBotを作る

はじめに

Discordとは、ユーザーが自由にサーバーを立てたり管理することが出来るコミュニケーションツールです。 僕は去年辺りから使い始め、人が管理するサーバーにお邪魔したり、自分でもサーバーを立てたりして楽しんでいます。

そんなDiscordには、Botというものが存在します。 現在様々な種類のBotが公開されており、音楽を流してくれるBot、新規で入った人に挨拶をしてくれるBot等、多岐にわたります。 Botの制作に必要なツールは公開されており、誰でも簡単に制作することが出来ます。

今回は、Botを自分のサーバーに導入する方法から、人気プログラミング言語Pythonのインストールまでを解説したいと思います

準備

それでは、Botを制作する準備をしていきます。 それほど難しくはありませんので、安心してください。

Botを作る

いきなり作るの!?と思うかもしれませんが、マウスをカチカチするだけで完成してしまいます。

まず始めに、このサイトにアクセスしてください

discordapp.com

すると、下の画像のようになっていると思います

https://gyazo.com/323618eb98d4b8e4117ad9a7cb915727

「マイアプリ」をクリックした後、「新しいアプリ」をクリックしてください。 下のような画面になります。

https://gyazo.com/58a2886e036635735a4e6a80f2ec4fb6

名前を適当に決めて、アプリを作成をクリックしたら、サーバーに導入する準備をします。

Generate OAuth2 URLをクリックしてください。

https://gyazo.com/d990da9ea50cf0b0d46379f9838660fc

次の画面でたくさんのチェックボックスが出てくると思いますが、Botにだけチェックが入っていることを確認して、下に出てくるURLにアクセスしてください。 そのURLからBotをサーバーに招待できます。

Pythonをインストールする

ここまで上手く行っていれば、Botをサーバーに導入できたと思います。 しかし、よく見てみると、Botがオフラインです。なんてこったい

それもそのはず、今作ったのはただのBotの入れ物です。 Botを思い通りに制御するためには、プログラムを書く必要があります。

今回、プログラミング言語Pythonを使おうと思います。 理由は、Pythonは大変人気な言語で記事も多く、勉強しやすいためです。

・・・実を言うと個人的に勉強したかったということもあります。

インストーラをダウンロードする

Pythonの公式サイトから最新のインストーラをダウンロードします。

www.python.org

PATHを通すかどうかを始めに聞いてくるので、忘れずにチェックしておきましょう。

インストールが終わったら、コマンドラインpython -Vと入力してみましょう

Pythonのバージョンが出てくると思います。

ライブラリをインストールする

次に、pipを使って、Bot制作に必要なパッケージをインストールします。 python -m pip -Vで、pipがインストール済みか確認します。

インストールされていない方は、下記リンクからget-pip.pyをダウンロードして、Pythonで実行してください。 ページを開いてctrl-sで保存できます。

https://bootstrap.pypa.io/get-pip.py

保存先のディレクトリで以下のように実行します。

$ python get-pip.py

これでpipがインストールされます。

次に、パッケージをインストールしていきます。 と言っても、これもまたコマンドを打つだけで終わりです。

$ python -m pip install discord.py

これで準備が全て終わりました。

おわりに

今回はBotの導入からPythonのインストールまで進みました。

次回からは実際にプログラムを書いていこうと思います。