ProcessingでArduinoから複数の値を受けて可視化する
方位センサ(取得値三つ)とフォトリフレクタ4つのときの挙動比較。
import processing.serial.*; Serial myPort; int[][] data; final int N = 4; //ここを受信する数値の数にする void setup(){ size(1000, 1000); myPort = new Serial(this, "COM4", 19600); data = new int[width][N]; for(int i = 0; i < width; i++){ for(int j = 0; j < N; j++){ data[i][j] = 0; } } } void draw(){ background(255); for(int i = 0; i < width - 1; i++){ for(int j = 0; j <N; j++){ strokeWeight(2); colorMode(HSB); stroke(j * 40, 255, 255); line(i, convToGraphPoint(data[i][j], j), i + 1, convToGraphPoint(data[i + 1][j], j)); colorMode(RGB); stroke(150, 100, 100); strokeWeight(4); line(i, convToGraphPoint(0, j), i + 1, convToGraphPoint(0, j)); } } } void serialEvent(Serial p){ try{ if(N + 1 == myPort.available()){ if(myPort.read() == 'a'){ for(int i = 0; i < width - 1; i++){ for(int j = 0; j < N; j++){ data[i][j] = data[i + 1][j]; } } for(int i = 0; i < N; i++){ data[width - 1][i] = myPort.read(); } } } } catch(RuntimeException e) { } } float convToGraphPoint(int value, int j){ return value + j*height/N + height/(N*2); //ここで適当にmapするときれいになるかな。 }
雑にFlask×chart.js
簡単と標ぼうされるものをかけ合わせて簡単に簡単に動かしたいときにコードを書いた
基本的には
Flask and great looking charts using Chart.js – Python Tutorial
を参照したんだけど、当然のようにそのままだと動かないので、編集した。
graph.html
{% extends "layout.html" %} {% block content %} <!-- Form ================================================== --> <div class="form"> <div class="container"> <div class="row"> <div class="col-md-12"> <canvas id="chart" width="600" height="400"></canvas> </div> </div> </div> </div> <script> var barData = { labels : [{% for item in labels %} "{{item}}", {% endfor %}], datasets : [{ label: 'Sample', backgroundColor: 'rgba(255, 99, 132, 0.2)', borderColor: 'rgba(255,99,132,1)', borderWidth:10, data : [{% for item in values %} {{item}}, {% endfor %}] }] } var mychart = document.getElementById("chart"); var chart = new Chart(mychart, { type:'bar', data:barData }); </script> {% endblock %}
メインのpythonコード、昔別のところで使っていたコードなんだけど、変える必要もないのでそのまま使った。(かなり雑である)
app.py
import os from flask_sqlalchemy import SQLAlchemy from datetime import datetime import time from flask import Flask, render_template, request, redirect, url_for import numpy as np app = Flask(__name__) def picked_up(): messages = [ "こんにちは、あなたの名前を入力してください", "やあ!お名前は何ですか?", "あなたの名前を教えてね" ] return np.random.choice(messages)[f:id:hungrykirby:20170521164836g:plain][f:id:hungrykirby:20170521164836g:plain] @app.route('/') def index(): title = "ようこそ" message = picked_up() return render_template('index.html', message=message, title=title) @app.route('/post', methods=['GET', 'POST']) def post(): title = "こんにちは" if request.method == 'POST': name = request.form['name'] return render_template('post.html', name=name, title=title) else: return redirect(url_for('index')) @app.route('/display', methods=['GET', 'POST']) def diplay(): titile = "You can see your graph" if request.method == 'POST': labels = ["January","February","March","April","May","June","July","August"] values = [10,9,8,7,6,4,7,8] return render_template('graph.html', values=values, labels=labels) else: return "Error" if __name__ == '__main__': app.run()
で
layout.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> {% if title %} <title>{{ title }}</title> {% else %} <title>Bootstrap 101 Template</title> {% endif %} <!-- Bootstrap --> <link href="/static/css/bootstrap.min.css" rel="stylesheet"> <script src="/static/js/Chart.min.js"></script> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> {% block content %}{% endblock %} <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="/static/js/jquery.min.js"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="/static/js/bootstrap.min.js"></script> </body> </html>
jQuery、bootstrapは適時使ってください。これもどこかのコピペ。
これで動く。あとで成形したいけど、備忘録なので次描くときでいいか。
フォトリフレクタ+Arduinoで可変抵抗をつないで分解能を上げる話
フォトリフレクタ(RPR220)を使ったときに、分解能を上げるための施策にこまった。
deviceplus.jp
基本的にはこのサイトを参照した。困ったのは512Ωの部分の最適な抵抗値。なるべく大きいrangeで取りたい。
で普通に可変抵抗(max10kΩ)を使ってみると、どうやら20kΩくらいがちょうど良さそうなことがわかった。
ふむふむ
マイコン・カーを製作してみよう(9) - ARM(Cortex-M3,M0)
ちなみに今(手元に在庫がなくて二種類使っているのだけど)LBR-127HLDも同時に使っている。
ちなみに最終的にどういう回路になったかと言うと
適当に組んだので真逆の動きをする。いいんだけどね。変化が取れれば。
herokuコマンドを入力するとエラーが出る問題に対処する
heroku login
をするが、なぜか動かない
heroku-cli: Installing CLI... 18.53MB/18.53MB ! Heroku client internal error. ! Search for help at: https://help.heroku.com ! Or report a bug at: https://github.com/heroku/heroku/issues/new Permission denied @ rb_sysopen .../heroku/cli/lib/node.exe
みたいなのが出る。
github.com
ここを見るとよくわからんが「消せ」と書いてあるので
/heroku
以下を消す
消せない
node.exeが起動中らしい。
コントロールパネルを見ると、node.jsが勝手に起動しているので止める。
デプロイできた!!!
pythonでherokuの/tmpファイルに一時ファイルを保管する
これに需要がなさそうなのですが、herokuは一時的にファイルを置けるんですよね。どう使い道があるのかわからないのですが…。
from flask import Flask, render_template, request, redirect, url_for import numpy as np import os import glob from werkzeug import secure_filename import requests ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif']) app = Flask(__name__) def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS @app.route('/') def index(): title = "ようこそ" message = "welcome" return render_template('index.html', message=message, title=title) @app.route('/post', methods=['GET', 'POST']) def post(): title = "こんにちは" if request.method == 'POST': name = request.form['name'] return render_template('index.html', name=name, title=title) else: return redirect(url_for('index')) @app.route('/image-upload', methods=['GET', 'POST']) def image_post(): if request.method == 'POST': f = request.files['file'] if f and allowed_file(f.filename): filename = secure_filename(f.filename) path_2_tmp = os.path.join(os.path.dirname(os.path.abspath(__file__)), "tmp") print(os.path.join(path_2_tmp, filename)) if not os.path.exists(path_2_tmp): os.mkdir(path_2_tmp) f.save(os.path.join(path_2_tmp, filename)) return filename return "file req error" return "post error" @app.route('/fetch-image', methods=['GET', 'POST']) def fetch_image(): if request.method == 'GET': for fn in glob.glob(os.path.join(os.getcwd(),"tmp","*")): print(fn) return "fetch image" if __name__ == '__main__': app.run()
どっかで見たようなコードですがだいたいどっかのパクリです。
これを適当にhtmlファイルと画像uploadボタンを作ってください。
そのあとURLに/image-uploadや/fetch-imageすれば完了です。まじで誰が使うんだこれ…。
Arduinoからシリアル通信で送られてきた値をリアルタイムにグラフでプロットしていく
Processingでやれよ!!!!
三軸方位センサの値をプロットしています。
冷静に考えて、webとしてFlask+p5.jsとかでやったほうがきれいだったんじゃないか…。
ちなみに何回かやってわかったのですが、これやらないほうがいいです。Ctrl-cでも止まらなくなったりdelayが出たり、そもそも重くなったりするので。
#app.py import serial import re import arrange def main(): arra = arrange.Arrange() with serial.Serial('COM3',9600,timeout=1) as ser: while True: c = ser.readline() de = c.decode('utf-8') m = re.match("\-*[\w]+", str(de)) if(m != None): arra.fetch_three_numbers(m.group()) else: pass ser.close() if __name__ == "__main__": main()
#arrage.py import numpy as np from scipy import signal from pylab import * class Arrange: bwn_a = False ax = None plots_numbers = [] def __init__(self): plot(500, 1) #ここいらない気がする。 plot(500, 3) plot(500, 5) def plots(self, x, y, z): clf() axis([-500, 500, -0.5, 5.5]) subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.2, hspace=0.5) plot(x, 1, 'o') plot(y, 3, '*') plot(z, 5, 'd') pause(0.01) def fetch_three_numbers(self, matched_group): if matched_group == "a": self.bwn_a = True self.plots_numbers = [] elif self.bwn_a: self.plots_numbers.append(matched_group) if len(self.plots_numbers) == 3: pl = self.plots_numbers self.plots(pl[0], pl[1], pl[2]) self.bwn_a = False print(pl)
ちなみにArduinoのコード
#include <Wire.h> #include "skHMC5883L.h" #define SENSOR_ADRS 0x1E skHMC5883L Compass(SENSOR_ADRS); void setup() { int ans; Serial.begin(9600); Wire.begin(); ans = Compass.Begin() ; } void loop() { // put your main code here, to run repeatedly: int ans; float deg; ans = Compass.SingleRead(°,6.6); if(ans == 0){ Serial.println("a"); Serial.println(RowX); Serial.println(RowY); Serial.println(RowZ); }else Serial.println("NG"); delay(1000); }
mySQLで新たに作ったユーザでデータベースが作れなかった。
mysql -u root -p
でrootに入る。この状態で作成したユーザに権限を付与しないとエラーになる(なった)
grant all on *.* to 'user'@'localhost';
これするといい!