1. 課題
・自宅で楽しく運動したい
・エアロバイクを買ったものの、動画を見ながら漕ぐのも飽きてきた
・バイクに表示される距離の表示だけでは、どの辺りまで進んだかの実感がない
2. 解決策
・漕いだ分だけGoogle map上でピンを進める
・Google spreadsheet上に進んだ座標を記録する
・イメージはこんな感じ
3. 手順
(a) 準備したもの
・Raspberry Pi 4
・リードスイッチ
・ネオジム磁石
・抵抗
・タクトスイッチ
(b) ハードのセットアップ
・接続する図は省略、基本的には上のイメージ図の感じで結線
・磁石とリードスイッチの位置はこんな感じ
4. プログラム
(a)準備
・とりあえずお決まりのアップデート
sudo apt-get update
sudo apt-get upgrade
・Google mapをchromiumで開き、操作する。そのためにSeleniumモジュールとchromiumのドライバをインストール
pip3 install selenium
sudo apt-get intsall chromium-chromedriver
・Google spreadsheetにデータをアップロードするために必要なモジュールもインストール
(b)コード
・GPIO17で回転を検知して回転数をカウント
・10秒間で漕いだ分だけ緯度経度をすすめてGoogle mapの検索点を更新
・GPIOの20と21でボタンプッシュごとに進行方向を45度程度傾けて進むようにしてみた
import math
import time
import sys
sys.path.append('/home/pi/.local/lib/python3.5/site-packages/')
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import RPi.GPIO as GPIO
import time
import gspread
from oauth2client.service_account import ServiceAccountCredentials
key_name = '***.json'
sheet_name = '***'
scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
credentials = ServiceAccountCredentials.from_json_keyfile_name(key_name, scope)
gc = gspread.authorize(credentials)
count = 0
total_count = 0
rotate = 0
def count_up(gpio_pin):
global count, total_count
count += 1
total_count += 1
print("count = ", count,"\n")
def count_right(gpio_pin):
global rotate
if(rotate<2):
rotate += 1
else:
rotate += 0
print("rotate = ", rotate)
def count_left(gpio_pin):
global rotate
if(rotate>-2):
rotate -= 1
else:
rotate -= 0
print("rotate = ", rotate)
pin_number = 17
pin_left = 20
pin_right = 21
try:
GPIO.remove_event_detect(pin_number)
GPIO.remove_event_detect(pin_right)
GPIO.remove_event_detect(pin_left)
GPIO.cleanup()
except:
a=1
GPIO.setmode(GPIO.BCM)
GPIO.setup(pin_number, GPIO.IN)
GPIO.add_event_detect(pin_number, GPIO.RISING, callback = count_up, bouncetime=200)
GPIO.setup(pin_right, GPIO.IN)
GPIO.add_event_detect(pin_right, GPIO.RISING, callback = count_right, bouncetime=200)
GPIO.setup(pin_left, GPIO.IN)
GPIO.add_event_detect(pin_left, GPIO.RISING, callback = count_left, bouncetime=200)
driver = webdriver.Chrome(executable_path="/usr/lib/chromium-browser/chromedriver")
driver.get("https:www.google.co.jp/maps/")
driver.maximize_window()
search_bar = driver.find_element_by_name("q")
i=0
m_per_rot = 4.5
m_per_sec_l = 30.86
m_per_sec_g = 24.97
sec_per_rot_l = 1.0 / m_per_sec_l / 3600.0 * m_per_rot
sec_per_rot_g = 1.0 / m_per_sec_g / 3600.0 * m_per_rot
lati = 35.680210
grat = 139.769272
search_bar.send_keys(str(lati) + ', ' + str(grat))
search_bar.submit()
search_bar.send_keys(Keys.ENTER)
try:
while True:
time.sleep(10)
search_bar.clear()
if(rotate==0):
lati += count * sec_per_rot_l
elif(rotate==1):
lati += (count * sec_per_rot_l) / math.sqrt(2.0) * math.cos(math.radians(45.0))
grat += (count * sec_per_rot_g) / math.sqrt(2.0) * math.cos(math.radians(45.0))
elif(rotate==2):
grat += count*sec_per_rot_g
elif(rotate==-1):
lati += (count * sec_per_rot_l) / math.sqrt(2.0) * math.cos(math.radians(45.0))
grat -= (count * sec_per_rot_g) / math.sqrt(2.0) * math.cos(math.radians(45.0))
elif(rotate==-2):
grat -= count*sec_per_rot_g
else:
lati+= count * sec_per_rot_l
search_bar.send_keys(str(round(lati, 6)) + ', ' + str(round(grat,6)))
search_bar.submit()
search_bar.send_keys(Keys.ENTER)
cell_position = 'B2'
wks = gc.open(sheet_name).sheet1
wks.update_acell(cell_position, total_count)
count = 0
i+=1
except KeyboardInterrupt:
cell_number = ['B4', 'B5']
input_value = [round(lati, 6), round(grat, 6)]
wks = gc.open(sheet_name).sheet1
for j in range(2):
input_value[j] += random.random()
wks.update_acell(cell_number[j], input_value[j])
print('\nbreak')
GPIO.remove_event_detect(pin_number)
GPIO.cleanup()
5. 運用してみた感想
・かなり適当な進路ですが、観光地周りを起点にして進むとなんとなくイメージが湧いて楽しいです。次は道路上を進むようにさせ、本当にツーリング感を出したいです。
・仲間とスプレッドシート上で回転数とか到着位置を競いたいと思っていましたがまだ一人で遊んでいます。
・エアロバイクでHIIT (High Intensity Interval Training)をしていますが、その時も少しだけ進んでいる感じがあって楽しめています。