4*4*4 LED CUBEを作った話

今回は4*4*4のLEDキューブを作りました。

・回路
LEDCUBE_回路図
 今回使用した回路はこのようなものです。

 LEDCUBE LO
 論理回路にするとこんな感じです。

 軽く調べたところシフトレジスタを使って作っているものが多かったのですが、シフトレジスタが家になかったのと、プログラムを直感的に描くために今回は使いませんでした。(みんながやってることをやってもつまらないしね)
 ANDが家になかったのでNORで代用しています。
 見ての通り、X,Y,Z座標を決めてあげるとそこのLEDが光るという単純なもので、直感的にプログラムを書くことができるようにしました。

・必要なもの
NORかAND*4
LED*64
トランジスタ*4
Arduino UNO
ジャンパ線たくさん
導線たくさん
ピンソケットかピンヘッダそこそこ
ユニバーサル基板の切れ端

・作り方
 適当に作ります。写真を適当にとったらピンボケがひどかったです。
①まず大量の銅線を切り、両端をペンチで挟みねじりながら引き伸ばします。
 今回は、100mm*32(Z座標決定用の格子用),160mm*20(XY座標用16+Z座標の格子への導線の集積用)を使いました。
UTFZ4192

②格子を作る
 今回は、方眼紙の上に並べて、それをはんだ付けしました。
RQNK3542

③LEDをつける
 気合で付けます。練り消しとか粘土とかでLEDを固定するとやりやすい気がします。
WJLE7718


④LEDをつけた格子同士をつなげる
 今回は、洗濯ばさみで立たせてやりました。
SBFK4744

⑤基板でコネクタを作れば完成
MBUU0145



・動作
 実際に光るとこんな感じです。そこそこきれいにできたと思います。プログラムをいじればもっといろいろな光り方ができると思いますが、満足しちゃったのでここまでで。(こんな単純なパターンでも全部で2000行近くなってしまったし...)


・総括
 はんだ付けの練習としてはかなり良かったです。また、行き当たりばったりで作っていたので無茶なところにはんだごてをねじ込むことになりましたが、完成したのでオッケーです。
 今度は電子楽器? を作ろうと思ってますが、全然仕組みが決まってません。年末で秋月が閉まる前までには部品を買っておきたいです。それではまた今度。

Arduinoで静電容量式のセンサーを作った話。

 Arduino日本語リファレンスを見てたら面白いものがあったので使ってみました。

 CapSenseというもので、適当な抵抗一本とアルミホイルなどで作ることができます。

 このファイルをダウンロードし、IEDのスケッチ→ライブラリのインクルード→.zip形式のライブラリをインストールと進みライブラリを使えるようにします。

 あとは、リファレンスに書いてあるサンプルプログラムを入れ実行すると、センサーの値が返ってきます。

静電
 これは、読み取りを一つにしたものです。
 使う抵抗によってセンサーの値が全然違うものになってくるのですが、こんかいは1MΩ抵抗を使っています。
 何も上にない時が一桁台、5cm離れたところあたりに手をかざしたときに30程になり、マスキングテープを挟んで触れているときは700台後半と変化したので、実用に足る精度ではないでしょうか?

 今回静電容量センサーを作りましたが使う予定はありません。
 最近LEDCubeを作っているので、近々ブログにかけると思います。それではまた今度。

Pygameでゲームを作ってみた話

 今回は、Pygameでパックマン風のゲームを作りました。サークルでEne-1の計器を作っているときにPygameを使っていて、それの続きとして作ってみました。

素材
 使いたい人がもし仮にいたら勝手に使ってください。
・chip2
chip2
・coin
coin
・enemy-2
enemy-2
・message
message
・bon
bom
・step
step

・sozai-1
これだけは、自分では描けなかったので、(●MACK●http://homepage3.nifty.com/looseleaf/)様の素材を使っています。
sozai-1


プログラム
 今回はきれいなプログラムを書く気が起きなかったのと、書いてるうちにどこがどう動いているのかよくわからなくなってきたので、プログラムが雑です。
import pygame,sys
import random


pygame.init()
window_size = (640, 640)
bg_color = (0, 0, 255)
clock = pygame.time.Clock()
screen = pygame.display.set_mode(window_size)
pygame.display.set_caption("GAME")

img_bg = pygame.image.load('chip2.png')
message = pygame.image.load('message.png')
charae = pygame.image.load('enemy-2.png')
chara = pygame.image.load('sozai-1.png')
bom = pygame.image.load('bom.png')
coin = pygame.image.load('coin.png')
step = pygame.image.load('step.png')
num_chips_per_line = int(img_bg.get_width() / 32)

map_data = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
]
i=0
chara_ex = [9,10,11,12]
chara_ey = [9,10,11,12]
chara_exa = [9,10,11,12]
chara_eya = [9,10,11,12]
coin_x = [1,1,1,1]
coin_y = [1,1,1,1]
coin_s = [0,0,0,0]
chara_x = 1
chara_y = 1
chara_xa = 1
chara_ya = 1
chara_xb = 1
chara_yb = 1
way_ex = [1,1,1,1]
way_ey = [1,1,1,1]
flame = 0
dir = "S"
dir_e = [3,3,3,3]
flag = 0
flag_1 = 0
flag_2 = 0
flag_3 = 0
walk = 0
deth = 0
c = 0
do = 0
bom_x = 0
bpm_y = 0
j = 0

#coin
for i in range(0,4):
while True:
coin_x[i] = random.randint(0, 19)
coin_y[i] = random.randint(0, 19)
if (map_data[coin_y[i] * 20 + coin_x[i]] == 0):
break

#step
while True:
step_x = random.randint(0, 19)
step_y = random.randint(0, 19)
if (map_data[step_y * 20 + step_x] == 0):
break

end_game = False
while not end_game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
end_game = True
#map
for y in range(0, 20):
for x in range(0, 20):
i = y * 20 + x
pos_x = x * 32
pos_y = y * 32
c = map_data[i]
dx = c % num_chips_per_line
dy = int(c / num_chips_per_line)
screen.blit(img_bg, (pos_x, pos_y), (32 * dx, 32* dy, 32,32))

#end event
for i in range(0,4):
if(chara_ex[i] == chara_x and chara_ey[i] == chara_y):
flag = 1

if(flag == 0 or flag == 2):

#my character
if (flame % 30 == 0):
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]:
chara_y = max(chara_y - 1, 0)
if pressed[pygame.K_LEFT]:
chara_x = max(chara_x - 1, 0)
if pressed[pygame.K_DOWN]:
chara_y = min(chara_y + 1, 20 - 1)
if pressed[pygame.K_RIGHT]:
chara_x = min(chara_x + 1, 20 - 1)
walk = 1
if (chara_y == chara_yb and chara_x == chara_xb):
walk = 0

chara_xa = chara_x
chara_ya = chara_y

if (map_data[chara_y * 20 + chara_xb] == 1):
flag_1 = 1
if (map_data[chara_yb * 20 + chara_x] == 1):
flag_2 = 1
if (map_data[chara_y * 20 + chara_x] == 1):
flag_3 = 1

if (flag_3 == 1):
chara_x = chara_xb
chara_y = chara_yb
if (flag_1 == 0 and flag_2 == 1):
chara_y = chara_ya
elif (flag_1 == 1 and flag_2 == 0):
chara_x = chara_xa

if (chara_x > chara_xb):
dir = "E"
if (chara_x < chara_xb):
dir = "W"
if (chara_y > chara_yb):
dir = "S"
if (chara_y < chara_yb):
dir = "N"

#enemy
for i in range(0,4):

if (chara_exa[i] == chara_ex[i] and chara_eya[i] == chara_ey[i]):
while True:
chara_exa[i] = random.randint(0, 19)
chara_eya[i] = random.randint(0, 19)
if (map_data[chara_eya[i] * 20 + chara_exa[i]] == 0):
if (chara_ey[i] > chara_eya[i]):
way_ey[i] = 1
if (chara_ey[i] < chara_eya[i]):
way_ey[i] = 0
if (chara_ex[i] > chara_exa[i]):
way_ex[i] = 1
if (chara_ex[i] < chara_exa[i]):
way_ex[i] = 0
break
#event
if (dir_e[i] == 1):
if (chara_y - chara_ey[i] < 6 and chara_y > chara_ey[i]):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (chara_x - chara_ex[i] < 6 and chara_x > chara_ex[i]):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (chara_ex[i] - chara_x < 6 and chara_ex[i] > chara_x):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (dir_e[i] == 2):
if (chara_x - chara_ex[i] < 6 and chara_x > chara_ex[i]):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (chara_ey[i] - chara_y < 6 and chara_ey[i] > chara_y):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (chara_y - chara_ey[i] < 6 and chara_y > chara_ey[i]):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (dir_e[i] == 3):
if (chara_ey[i] - chara_y < 6 and chara_ey[i] > chara_y):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (chara_x - chara_ex[i] < 6 and chara_x > chara_ex[i]):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (chara_ex[i] - chara_x < 6 and chara_ex[i] > chara_x):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (dir_e[i] == 4):
if (chara_ex[i] - chara_x < 6 and chara_ex[i] > chara_x):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (chara_ey[i] - chara_y < 6 and chara_ey[i] > chara_y):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1
if (chara_y - chara_ey[i] < 6 and chara_y > chara_ey[i]):
chara_exa[i] = chara_x
chara_eya[i] = chara_y
do = 1

if (do == 1):
if (chara_ey[i] > chara_eya[i]):
way_ey[i] = 1
if (chara_ey[i] < chara_eya[i]):
way_ey[i] = 0
if (chara_ex[i] > chara_exa[i]):
way_ex[i] = 1
if (chara_ex[i] < chara_exa[i]):
way_ex[i] = 0

if (flame % 30 == 0):
if (dir_e[i] % 2 == 1):
if (map_data[chara_ey[i] * 20 + chara_ex[i] + 1] == 0 and way_ex[i] == 0):
dir_e[i] = 2
if (chara_ey[i] >= chara_eya[i]):
way_ey[i] = 1
if (chara_ey[i] < chara_eya[i]):
way_ey[i] = 0
if (map_data[chara_ey[i] * 20 + chara_ex[i] - 1] == 0 and way_ex[i] == 1):
dir_e[i] = 4
if (chara_ey[i] >= chara_eya[i]):
way_ey[i] = 1
if (chara_ey[i] < chara_eya[i]):
way_ey[i] = 0
elif (dir_e[i] % 2 == 0):
if (map_data[chara_ey[i] * 20 + chara_ex[i] + 20] == 0 and way_ey[i] == 0):
dir_e[i] = 3
if (chara_ex[i] >= chara_exa[i]):
way_ex[i] = 1
if (chara_ex[i] < chara_exa[i]):
way_ex[i] = 0
if (map_data[chara_ey[i] * 20 + chara_ex[i] - 20] == 0 and way_ey[i] == 1):
dir_e[i] = 1
if (chara_ex[i] >= chara_exa[i]):
way_ex[i] = 1
if (chara_ex[i] < chara_exa[i]):
way_ex[i] = 0

if (flame % 30 == 0):
if (dir_e[i] == 1):
chara_ey[i] = chara_ey[i] - 1
elif (dir_e[i] == 2):
chara_ex[i] = chara_ex[i] + 1
elif (dir_e[i] == 3):
chara_ey[i] = chara_ey[i] + 1
elif (dir_e[i] == 4):
chara_ex[i] = chara_ex[i] - 1

flag_1 = 0
flag_2 = 0
flag_3 = 0
do = 0

# coin event
for i in range(0, 4):
if (coin_x[i] == chara_x and coin_y[i] == chara_y):
coin_s[i] = 1

if (coin_s[0] == 1 and coin_s[1] == 1 and coin_s[2] == 1 and coin_s[3] == 1):
flag = 2


#grafic
if(chara_x == step_x and chara_y == step_y and flag == 2):
flag = 4

for i in range(0,4):
if (coin_s[i] == 0):
screen.blit(coin, (coin_x[i] * 32,coin_y[i] * 32), (0, 0, 32, 32))

for i in range(0,4):
if (coin_s[i] == 0):
screen.blit(coin, (i * 32,0), (32, 0, 32, 32))
else:
screen.blit(coin, (i * 32,0), (0,0,32,32))

for i in range(0,4):
if (dir_e[i] == 1):
screen.blit(charae, (chara_ex[i] * 32, chara_ey[i] * 32), (64, 0, 32, 32))
elif (dir_e[i] == 2):
screen.blit(charae, (chara_ex[i] * 32, chara_ey[i] * 32), (32, 0, 32, 32))
elif (dir_e[i] == 3):
screen.blit(charae, (chara_ex[i] * 32, chara_ey[i] * 32), (96, 0, 32, 32))
elif (dir_e[i] == 4):
screen.blit(charae, (chara_ex[i] * 32, chara_ey[i] * 32), (0, 0, 32, 32))

if (flag == 2):
screen.blit(step, (step_x * 32, step_y * 32), (0, 0, 32, 32))

if (dir == "S"):
if (walk == 0):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 0, 32, 64))
elif (flame % 120 > 89):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 0, 32, 64))
elif (flame % 120 > 59):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (0, 0, 32, 64))
elif (flame % 120 > 29):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 0, 32, 64))
elif (flame % 120 < 30):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (64, 0, 32, 64))
elif (dir == "E"):
if (walk == 0):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 128, 32, 64))
elif (flame % 120 > 89):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 128, 32, 64))
elif (flame % 120 > 59):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (0, 128, 32, 64))
elif (flame % 120 > 29):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 128, 32, 64))
elif (flame % 120 < 30):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (64, 128, 32, 64))
elif (dir == "N"):
if (walk == 0):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 192, 32, 64))
elif (flame % 120 > 89):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 192, 32, 64))
elif (flame % 120 > 59):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (0, 192, 32, 64))
elif (flame % 120 > 29):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 192, 32, 64))
elif (flame % 120 < 30):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (64, 192, 32, 64))
elif (dir == "W"):
if (walk == 0):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 64, 32, 64))
elif (flame % 120 > 89):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 64, 32, 64))
elif (flame % 120 > 59):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (0, 64, 32, 64))
elif (flame % 120 > 29):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (32, 64, 32, 64))
elif (flame % 120 < 30):
screen.blit(chara, (chara_x * 32, chara_y * 32 - 32), (64, 64, 32, 64))

elif(flag == 1):
if(j<10):
screen.blit(bom, (chara_x * 32, chara_y * 32), (0, 0, 32, 32))
elif(j<20):
screen.blit(bom, (chara_x * 32, chara_y * 32), (32 * 1, 0, 32, 32))
elif(j<30):
screen.blit(bom, (chara_x * 32, chara_y * 32), (32 * 2, 0, 32, 32))
elif(j<40):
screen.blit(bom, (chara_x * 32, chara_y * 32), (32 * 3, 0, 32, 32))
elif(j<50):
screen.blit(bom, (chara_x * 32, chara_y * 32), (32 * 4, 0, 32, 32))
elif(j<60):
screen.blit(bom, (chara_x * 32, chara_y * 32), (32 * 5, 0, 32, 32))
elif(j>119):
end_game = True
j = j + 1

if(flag == 4):
if(j < 120):
screen.blit(message, (120,240), (0, 0, 400, 64))
else:
end_game = True
j = j + 1

#for i in range(0,4):
# screen.blit(charae, (chara_exa[i] * 32,chara_eya[i] * 32), (128,0,32,32))
pygame.display.flip()
clock.tick(60)
flame = flame + 1
chara_xb = chara_x
chara_yb = chara_y

 かなり適当に作ったので、雑なところが多々ありますが、きちんと動き、それなりに面白かったので満足しています。

 なんかすごくlivedoorの編集ページが重くなってきたのでこれくらいにしておきます。
 それではまた今度。

Ene1-GPに参加した話

 私がReUsというサークルに入ってるという話は何回か出てきたと思いますが、(サークルって言ってるときは大体このサークルです。)そのサークルの主な活動であるEne1-GP MOTEGI KV-BIKEに参加してきました。

 この大会は充電式の単三電池40本で電動バイクを動かして、一周のタイムと60分で走った周回数を競う大会です。

 今回私はエンジニアとして計器のシステムの開発をしました。今回作ったシステムの概要は以下の通りです。
Untitled Diagram
 今回はすべてのセンサーがアナログなので機能のわりに複雑なシステムになりました。

・プログラム
Arduino-slave

#include <Wire.h>
#include <math.h>
int val = 0;
int i = 0;
int stb;
int sta;
int V;
float f;
void setup() {
  Serial.begin(9600);
  Wire.begin(8);
  Wire.onRequest(requestEvent);
  }

void loop() {
  val=analogRead(0);
  Serial.println(val);
  i++;
  if(val > 900){
    sta = 1;
  }else{
    sta = 0;
  }
  if(sta > stb){
      f = 10000 / i;
      V = 55*3.14*f;//なんかいい感じの係数をかける
      Serial.print("V=");
      Serial.println(V);
      i = 0;
  }
  stb = sta;
  delayMicroseconds(100);
}

void requestEvent() {
  Wire.write(V);
}


Arduino-master
#include <SoftwareSerial.h>
#include <math.h>
#include <Wire.h>
 
// rxPin = 2  txPin = 3
SoftwareSerial mySerial(2, 3);
 
// NMEAの緯度経度を「度」(DD)の文字列に変換する
String NMEA2DD(float val) {
  int d = val / 100;
  int m = (((val / 100.0) - d) * 100.0) / 60;
  float s = (((((val / 100.0) - d) * 100.0) - m) * 60) / (60 * 60);
  return String(d + m + s, 6);
}


int val1;//温度
int val2;//電圧
int temp;
float vol;
void setup() {
  Wire.begin();
  mySerial.begin(9600);
  Serial.begin(9600);
  }

void loop() {
  // 1つのセンテンスを読み込む
  String line = mySerial.readStringUntil('\n');
 
  if(line != ""){
    int i, index = 0, len = line.length();
    String str = "";
  
    // StringListの生成(簡易)
    String list[30];
    for (i = 0; i < 30; i++) {
      list[i] = "";
    }
 
    // 「,」を区切り文字として文字列を配列にする
    for (i = 0; i < len; i++) {
      if (line[i] == ',') {
        list[index++] = str;
        str = "";
        continue;
      }
      str += line[i];
    }
    
    // $GPGGAセンテンスのみ読み込む
    if (list[0] == "$GPGGA") {
      
      // ステータス
      if(list[6] != "0"){
        Serial.println("start");
        
        //緯度
        Serial.println(NMEA2DD(list[2].toFloat()));
        
        //経度
        Serial.println(NMEA2DD(list[4].toFloat()));
        
        //温度
        val1=analogRead(0);
        Serial.println(temp);

        //電圧
        val2=analogRead(1);
        vol = val2 * 0.00488281 * 11 ;
        Serial.println(vol);
  
        Wire.requestFrom(8,1);
        while (Wire.available()) {
          long c = Wire.read();
          Serial.println(c);
          }

      }else{
        Serial.println("start");
        
        //緯度
        Serial.println("error");

        //経度
        Serial.println("error");
        
        //温度
        val1=analogRead(0);
        Serial.println(temp);
        
        //電圧
        val2=analogRead(1);
        vol = val2 * 0.00488281 * 11 ;
        Serial.println(vol);
        
        Wire.requestFrom(8,1);
        while (Wire.available()) {
          long c = Wire.read();
          Serial.println(c);
      }
    }
  }
 }
}


Raspberry Pi

from serial import *
from sys import exit
from datetime import datetime
import pygame
import datetime,time
import requests

from pygame.locals import *
import sys

SCREEN_SIZE = (640, 480)
url = 'https://xxx.jp/yyy/update.php'

def addTime(logtext):
return str(datetime.datetime.now()) + ' ,' + logtext

def retime():
if(retime1 >= 50):
if(retime2 >= 50):
return "0" + str(59-retime2) + ":" + "0" + str(59-retime1)
elif(retime2 < 50):
return str(59-retime2) + ":" + "0" + str(59-retime1)
elif(retime1 < 50):
if(retime2 >= 50):
return "0" + str(59-retime2) + ":" + str(59-retime1)
elif(retime2 < 50):
return str(59-retime2) + ":" + str(59-retime1)


pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE)
pygame.display.set_caption("data")

# ArduinoのUSBデバイス名
port = '/dev/ttyACM0'

# フォントの作成
sysfont = pygame.font.SysFont(None, 80)

# シリアルポートを開く
try:
ser = Serial(port, 9600)
print('open port: %s' % port)
except:
print('cannot open port: %s' % port)
exit(1)

f = open("write.txt","w")
f.write(addTime("start\n"))
f.close()


# 読み出しと出力
while True:
line = ser.readline().rstrip().decode("utf-8")
if(line=="start"):

# 1ライン単位で読み出し、末尾の改行コードを削除
line1 = ser.readline().rstrip().decode("utf-8")
line2 = ser.readline().rstrip().decode("utf-8")
line3 = ser.readline().rstrip().decode("utf-8")
line4 = ser.readline().rstrip().decode("utf-8")
line5 = ser.readline().rstrip().decode("utf-8")


payload = {"speed":line5,"temp":line3,"volt":line4}
response = requests.get(url,params=payload)
# テキストを描画したSurfaceを作成
text1 = sysfont.render("North", True, (0,0,0))
text2 = sysfont.render("East", True, (0,0,0))
text3 = sysfont.render("Temp", True, (0,0,0))
text4 = sysfont.render("Volt", True, (0,0,0))
text5 = sysfont.render("Speed", True, (0,0,0))
data1 = sysfont.render(line1, True, (0,0,0))
data2 = sysfont.render(line2, True, (0,0,0))
data3 = sysfont.render(line3, True, (0,0,0))
data4 = sysfont.render(line4, True, (0,0,0))
data5 = sysfont.render(line5, True, (0,0,0))

f = open("write.txt","a")
f.write("North,")
f.write(line1)
f.write(", Eeat,")
f.write(line2)
f.write(", Temp,")
f.write(line3)
f.write(", Volt,")
f.write(line4)
f.write(", Speed,")
f.write(line5)
f.write(",\n")
f.close()

try:
screen.fill((255,255,255))

# テキストを描画する
screen.blit(text1, ( 0, 50))
screen.blit(data1, (200, 50))
screen.blit(text2, ( 0,100))
screen.blit(data2, (200,100))
screen.blit(text3, ( 0,150))
screen.blit(data3, (200,150))
screen.blit(text4, ( 0,200))
screen.blit(data4, (200,200))
screen.blit(text5, ( 0,250))
screen.blit(data5, (200,250))

pygame.display.update()
except Exception as e:
print(e.message)



for event in pygame.event.get():
if event.type == QUIT:
sys.exit()

プログラム自体は今までやってきたものの組み合わせでした。

 本番のこととかはこちら

 まあ、これでひと段落したので、Pygameで作っているパックマンを完成させて、その後にライントレーサーのIoT化とかをやっていきたいと思います。
 あと、インバーターとかも作ります。それではまた今度。

ラズパイをUltraVNCでパソコンから操作した話

 サークルで作っているセンサーのシステムで、バイク本体に乗せているラズパイをほかのデバイスから操作できたほうが便利です。それなので、今回はまずパソコンで操作できるようにしました。


・使ったソフト
 今回は導入が手軽だったので、UltraVNCというものを使いました。


・ラズパイの操作
 ラズパイの操作としては以下の手順をすることになります。
% sudo apt-get install x11vnc
% x11vnc -storepasswd
③% ifconfig
④% x11vnc -usepw

①このコマンドでインストールします。いくつかの質問が来ますが、基本すべてエンターで流しておけば大丈夫です。
②このコマンドで接続するときのパスワードを設定します。
③このコマンドでは、ラズパイのIPアドレスを見ることができます。
④このコマンドで起動することができます。PORT=xxxxと4桁の数字が表示されますが、この数字は後でパソコンで使います。


・パソコンの操作
 パソコンでの操作としてはこのサイトからソフトをダウンロードしてきてインストールします。
 インストールしてきたらUltraVNC Viewerを起動します。起動したらVNC serverに”IPアドレス:ポート番号”となるように入力しConnectをクリックします。そうするとパスワードを聞かれるので先ほど設定したパスワードを入力するとラズパイの画面が表示されます。


・動作
 実際に動かすとこのようにラズパイを操作することができました。
DrI-zwTVAAAS4-v

 今回はパソコンとラズパイを直接つないでしまいましたが、API,WebIOPiなどでもしてみたいです。それではまた今度。

最小構成?のArduinoを作った話

 なんとなく今までやれていなかった自作Arduinoを作りました。

・回路図
Arduino_回路図
 今回はこのような回路を作りました。ICのVCCに給電できてなかったり、AGNDがGNDに短絡してなかったりしますが動いたので問題はないはずです...
 ATMEGA328pにArduinoを書き込むのが面倒だったので、家で余ってるArduinoから抜いてきました。

 ただし、最小構成で作った場合シリアル通信ができないため、プログラムを書き込むことができなかったりシリアルモニタが使えなかったりしますが、まああまり困らないと思います。


 今日は暇で進捗が出たので二本も記事を書いてしまいましたが、まあまた忙しくなるのでこのままのペースではいきません。それではまた今度。

Pygameで遊んだ話

 製作実験という授業でライントレーサーを作るのですが、今までにいろいろなトレーサーを作っているのでただ作るだけでは面白くないと思い、ディスプレイに走行状態を表すアニメーションなんかを移そうと思いました。ちょうど、ラズパイ用のディスプレイも買ったのでPygameを使って作り、ラズパイで写すことにしました。

・準備
 ラズパイとWindowsのPCのセットアップの仕方は忘れました。ラズパイではデフォルトのもの、ノートパソコンではPyCharmを使っています。

・プログラム
import sys, pygame

pygame.mixer.pre_init(44100, -16, 1, 512)
pygame.init()
window_size = (320, 240)
clock = pygame.time.Clock()
screen = pygame.display.set_mode(window_size)
#img_char1 = pygame.image.load('reimu2.png')
img_char2 = pygame.image.load('reimu3.png')
before = 3
after = 3

# SEの読み込み
se = pygame.mixer.Sound('se.wav')
"""
# BGMを読み込んで再生
pygame.mixer.music.load('bgm1.wav')
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
"""

x = 75 # 表示位置X

# キー入力
class KeyState:
def __init__(self):
self.key_new = pygame.key.get_pressed()
self.key_old = self.key_new

def update(self):
self.key_old = self.key_new
self.key_new = pygame.key.get_pressed()

def get_key(self, name):
return self.key_new[name]

ks = KeyState()
end_game = False
while not end_game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
end_game = True

ks.update()

r, g, b = 255, 255, 255
if ks.get_key(pygame.K_w):
loop_anim_index = int(20) % 4
after = 0
elif ks.get_key(pygame.K_a):
loop_anim_index = int(21) % 4
after = 1
elif ks.get_key(pygame.K_d):
loop_anim_index = int(22) % 4
after = 2
elif ks.get_key(pygame.K_s):
loop_anim_index = int(23) % 4
after = 3
else:
loop_anim_index = int(23) % 4
after = 3


if before != after:
se.play() # SEの再生

before = after

screen.fill((r,g,b))
#screen.blit(img_char1, (x, 50), (27 * loop_anim_index, 0, 27, 16))
screen.blit(img_char2, (x, 150), (163 * loop_anim_index, 0, 163, 96))
pygame.display.flip()
clock.tick(60)

sys.exit(0)
 このようなプログラムを書きました。
 いろいろなプログラムを参考にして適当に描いたので、ぐちゃぐちゃですが許してください。
 コメントアウトしている文では、小さいほうのアニメーションを動かせます。

・素材
reimu2
reimu3
 今回はサイズ違いの二つのものを作りました。画力がないので微妙ですが。
 博麗霊夢が旗をパタパタしてるように見えたらいいです。

・動作
 映像のようにWを押すと両手をA,Dを押すとそれぞれ右手と左手を挙げてくれます。


 今回は製作実験のためにPygameを使いました。ソフトの素材はほとんどできていると思うので、ハードの制作とソフトの合成?を進めていきたいです。
 それではまた今度。

ラズパイとArduinoでシリアル通信をした話

 製作実験という授業で作るライントレーサーとサークルのモジュールで使うために、Raspberry PiとArduinoでシリアル通信をしました。


・準備すること
 ラズパイでシリアル通信をするためにはpysirialというライブラリが必要なのですが、それをインストールするためにはpipというものが必要です。それぞれをダウンロードするために↓のコマンドをターミナルで打ちます。
$ sudo apt-get install python-pip
$ pip install pyserial

・Arduinoのプログラム
 ラインとレースをする都合でいろいろシリアル通信と関係ない部分が多いですが、Arduinoから出力する分にはシリアルモニタに出力するときと一緒です。
 ちなみにこのプログラムで読み取っているのはフォトリフレクタからの出力で、出力しているのはTA7291pへの信号です。
int val1,val2,val3,val4,val5;
int thre1=500;
int thre2=500;
int thre3=500;
int thre4=500;
int thre5=500;

int repo;

void setup() {
  Serial.begin(9600);
  pinMode(13,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(10,OUTPUT);
}
 
void loop() {
  
  val1=analogRead(0);
  val2=analogRead(1);
  val3=analogRead(2);
  val4=analogRead(3);
  val5=analogRead(4);
  
  if(val2>thre2){
  repo=2;
  digitalWrite(13,HIGH);
  digitalWrite(12,LOW );
  digitalWrite(11,HIGH);
  digitalWrite(10,HIGH);}
  
  if(val3>thre3){
  repo=1;
  digitalWrite(13,HIGH);
  digitalWrite(12,LOW );
  digitalWrite(11,LOW );
  digitalWrite(10,HIGH);}
  
  if(val4>thre4){
  repo=3;
  digitalWrite(13,HIGH);
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW );
  digitalWrite(10,HIGH);}
  
  if(val1>thre1){
  repo=4;
  digitalWrite(13,LOW );
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW );
  digitalWrite(10,HIGH);}
  
  if(val5>thre5){
  repo=5;
  digitalWrite(13,HIGH);
  digitalWrite(12,LOW );
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW );}
  
  if(val1>thre1 && val5>thre5){
  repo=0;
  digitalWrite(13,HIGH);
  digitalWrite(12,LOW );
  digitalWrite(11,LOW );
  digitalWrite(10,HIGH);}
  
  Serial.println(repo);
  delay(10);
}

・Raspberry Piのプログラム
# coding: UTF-8

from serial import *

from sys import exit

from datetime import datetime

# ArduinoのUSBデバイス名

port = '/dev/ttyACM0'

# シリアルポートを開く

try:

   ser = Serial(port, 9600)

   print('open port: %s' % port)

except:

   print('cannot open port: %s' % port)

   exit(1)

# 読み出しと出力

while True:

   # 1ライン単位で読み出し、末尾の改行コードを削除

   line = ser.readline().rstrip()

   try:

       print(datetime.now(),line)

   except Exception as e:

       print(e.message)


・動作
 これを入れて、Ardinoと普通のパソコンをつなぐのと同じ様にラズパイとArduinoをつなぐと、Serialprintされた値がラズパイに表示されます。この値を使ってラズパイ側で音を鳴らしたり画像を表示したりしたいのですが、いまいちいい方法が見つからず...まあ、いろいろ試行錯誤してやっていこうと思います。それではまた今度。


こんな感じで動かしてました。
JPiAwx-C

ラズパイ用ディスプレイを買った話

 ラズパイを家の外でも動かすために専用ディスプレイを買ったので、今回はそのことを書きました。

 ラズパイ用のディスプレイを選ぶにあたって色々調べていたところ、ラズパイのGPIOピンを使っているものがあり、そのディスプレイを使っているとGPIOピンが使えなくなってしまうということがわかりました。なので今回はGPIOが使えることを第一条件に選びました。

 その結果今回選んだのはこちらのものです。


 先ほど言った通りGPIOが使えるものの中でもいいと思ったのでこれにしました。
 このディスプレイはGPIOを使わないためHDMIでラズパイと接続します。そのために、このように二つ並んだHDMIのポートをつなぐための独特な形の基板が付いてきます。

IMG_1130

↑の二つのHDMIポートをつなぐために↓のような基板が付いてきます。
IMG_1131

 また、ディスプレイにつながれてしまうはずのGPIOピンは横に飛び出たピンヘッダで使えます。IMG_1128


 このディスプレイはタッチディスプレイとしても使えるのですが、使えるようにするには別にセットアップしなければいけません。付属しているDVDにドライバなどが入っているようなのですが、ラズパイに光学ドライブはもちろんついてないし、一回デスクトップに入れてから移し替えるのも面倒くさいです。それなので今回は、githubにも同じものがあるのでそれをインストールしました。
 
 セットアップ手順は、ターミナルで下のコマンドを実行するだけです。
$ git clone https://github.com/goodtft/LCD-show.git
chmod -R 755 LCD-show
cd LCD-show/
sudo ./MPI3508_480_320-show
 これを実行すると画面が暗転し、大量の文字が下から流れてきますがそれが終わればタッチパネルが機能するようになります。


 今回は、ラズパイを外出先でも使えるようにディスプレイの設定を行いました。これで家以外でもラズパイをいじれるようになったので、開発を進めていきたいと思います。それではまた今度。

「みちびき」対応のGPSセンサーを使ってみた話

 サークルのほうで、GPSを使って面白いことができたらいいと思ったので、ちょっと使ってみました。

 秋月でGPSモジュールを検索したら「みちびき」対応のものがあったので、それを買ってきて使うことにしました。

・回路
 今回はアナログシリアルを使ったことや1PPSを使わなかったため、入っている説明書とは少し違う回路になってます。
 説明書ではTXとRXになっている所を今回はDIGITALピンの3,2ピンに接続しています。

・プログラム
 ネットで見つけたプログラムを改良して使っています。ゴリ押しで速度を出しているのでプログラムが汚いですが、そこには目を瞑ってください...
#include <SoftwareSerial.h>
#include <math.h>
 
// rxPin = 2  txPin = 3
SoftwareSerial mySerial(2, 3);
 
// NMEAの緯度経度を「度」(DD)の文字列に変換する
String NMEA2DD(float val) {
  int d = val / 100;
  int m = (((val / 100.0) - d) * 100.0) / 60;
  float s = (((((val / 100.0) - d) * 100.0) - m) * 60) / (60 * 60);
  return String(d + m + s, 6);
}
 
// UTC時刻から日本の標準時刻に変換する(GMT+9:00)
String UTC2GMT900(String str) {
  int hh = (str.substring(0,2).toInt()) + 9;
  if(hh > 24) hh = hh - 24;
 
  return String(hh,DEC) + ":" + str.substring(2,4) + ":" + str.substring(4,6);  
}
 
  float ai,bi,di;//緯度の状態
  float ak,bk,dk;//経度の状態
  float fi=294.2940886111111;//緯度一分当たりの距離
  float fk=295.2841203703704;//経度一分当たりの距離
  float dmi,dmk,def;//移動距離
void setup() {
  mySerial.begin(9600);
  Serial.begin(115200);
}
void loop() {
  // 1つのセンテンスを読み込む
  String line = mySerial.readStringUntil('\n');
 
  if(line != ""){
    int i, index = 0, len = line.length();
    String str = "";
  
    // StringListの生成(簡易)
    String list[30];
    for (i = 0; i < 30; i++) {
      list[i] = "";
    }
 
    // 「,」を区切り文字として文字列を配列にする
    for (i = 0; i < len; i++) {
      if (line[i] == ',') {
        list[index++] = str;
        str = "";
        continue;
      }
      str += line[i];
    }
    
    // $GPGGAセンテンスのみ読み込む
    if (list[0] == "$GPGGA") {
      
      // ステータス
      if(list[6] != "0"){      
        // 現在時刻
        Serial.println(UTC2GMT900(list[1]));
        
        //緯度
        bi =list[2].toFloat();
        di = bi - ai;
        dmi = di * fi;
        Serial.print(" 緯度:");
        Serial.println(NMEA2DD(list[2].toFloat()));

        //経度
        bk =list[4].toFloat();
        dk = bk - ak;
        dmk = dk * fk;
        Serial.print(" 経度:");
        Serial.println(NMEA2DD(list[4].toFloat()));

        //速度
        def=sqrtf(dmi*dmi + dmk*dmk);
        Serial.print("速度:");
        Serial.println(def);
        
      }else{
        Serial.print("測位できませんでした。");
      }
      
      Serial.println("");
      ai =bi;
      ak =bk;
    }
  }
}


・動作
 GPS信号を扱っている関係で、出力に緯度と経度が乗ってしまうので画像は上げられないのですが、速度を出力することは一応できました。しかし、等速に移動しているときでも結構表示される速度に違いが出てしまいました。


 今回は、精度の良いGPS信号を得ることができていたのに、あまりそれを活用することができませんでした。このモジュールは10Hzで信号を出すことができるので、それを利用してもっと複雑な処理をすれば精度が上がると思います。
 すぐ改良したいのですが、大学が始まってしまって忙しくなってしまったので今回はここまで、それではまた今度。
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

読者登録
LINE読者登録QRコード