Let’s play with AI.
こんにちは。
AI coordinator管理人の清水秀樹です。
人気のコーナー「外でも動く遠隔操作AIロボットを作ろうpart02:Arduino編」に続き、part03:joystick編です。
part01、part02を見ていない方は以下の動画でご確認頂けます。
今回のpart03も動画で紹介しています。
是非参考にしてみてください。
joystickでタイヤを動かしてみよう。
前回はarduino IDEのシリアルモニタからタイヤを動かしました。
今回はjoystickを使ってタイヤを動かしてみたいと思います。
使用したjoystickはこちらです。
では、早速arduinoに書き込むソースコードの紹介です。
test.ino
/* * This example shows how to control MDDS30 in Serial Simplified mode with Arduino. * Set MDDS30 input mode to 0b11001100 * Open Serial Monitor, set baudrate to 9600bps and "No line ending". * Send 0: Left motor stops * 1: Left motor rotates CW with half speed * 2: Left motor rotates CW with full speed * 3: Left motor rotates CCW with half speed * 4: Left motor rotates CCW with full speed * 5: Right motor stops * 6: Right motor rotates CW with half speed * 7: Right motor rotates CW with full speed * 8: Right motor rotates CCW with half speed * 9: Right motor rotates CCW with full speed * * Note: This example also compatible with MDDS10 and MDDS60 * * Hardware Connection: * Arduino Uno MDDS30 * GND ---------- GND * 4 ------------ IN1 * * Related Products: * - SmartDriveDuo-30: http://www.cytron.com.my/P-MDDS60 * - CT UNO: http://www.cytron.com.my/p-ct-uno * - DC Brush Motors: http://www.cytron.com.my/c-84-dc-motor * - LiPo Battery: http://www.cytron.com.my/c-87-power/c-97-lipo-rechargeable-battery-and-charger * - Male to Male Jumper: https://www.cytron.com.my/p-wr-jw-mm65 * * URL: http://www.cytron.com.my */ #include <SoftwareSerial.h> #include <Cytron_SmartDriveDuo.h> #define IN1 4 // Arduino pin 4 is connected to MDDS60 pin IN1. #define BAUDRATE 9600 Cytron_SmartDriveDuo smartDriveDuo30(SERIAL_SIMPLFIED, IN1, BAUDRATE); float motor_L; float motor_R; signed int speedLeft, speedRight; void setup() { Serial.begin(9600); } void loop() { if (Serial.available()) { String motor = Serial.readStringUntil('z'); //Serial.println(motor); int kg = motor.indexOf(","); //Serial.println(kg); int length = motor.length(); //Serial.println(length); float motor_updown = motor.substring(0, kg).toFloat(); float motor_LR = motor.substring(kg + 1 , length).toFloat(); // Serial.println(motor_updown); // Serial.println(motor_LR); if (motor_updown == 0.0 && motor_LR > 0.0) { motor_L = motor_LR; motor_R = -motor_LR; } else if (motor_updown == 0.0 && motor_LR < 0.0) { motor_L = motor_LR; motor_R = -motor_LR; } else if (motor_updown > 0.0 && motor_LR > 0.0) { motor_L = motor_updown; motor_R = 0; } else if (motor_updown < 0.0 && motor_LR > 0.0) { motor_L = 0; motor_R = motor_updown; } else if (motor_updown > 0.0 && motor_LR < 0.0) { motor_L = 0; motor_R = motor_updown; } else if (motor_updown < 0.0 && motor_LR < 0.0) { motor_L = motor_updown; motor_R = 0; } else { motor_L = motor_updown; motor_R = motor_updown; } speedLeft = motor_L * 100; speedRight = motor_R * 100; smartDriveDuo30.control(speedLeft, speedRight); Serial.flush(); } }
続いてPC側のjoystickソースコードです。
こちらはpythonを使用します。
joystick_serial_motor.py
import pygame from pygame.locals import * import time import serial #シリアル通信(PC⇔Arduino) ser = serial.Serial() ser.port = "COM4" #デバイスマネージャでArduinoのポート確認 ser.baudrate = 9600 #Arduinoと合わせる ser.setDTR(False) #DTRを常にLOWにしReset阻止 ser.open() #COMポートを開く joy_list = [[0]*3]*3 pygame.joystick.init() try: j = pygame.joystick.Joystick(0) # create a joystick instance j.init() # init instance print ('Joystickの名称: ' + j.get_name()) print ('ボタン数 : ' + str(j.get_numbuttons())) #キーが押されたフレーム時間を記録するリストを生成 key_list =[0]*j.get_numbuttons() except pygame.error: print ('Joystickが見つかりませんでした。') def main(): pygame.init() frametime = 0 x,y =0,0 while 1: for e in pygame.event.get(): # イベントチェック if e.type == QUIT: # 終了が押された? return if (e.type == KEYDOWN and e.key == K_ESCAPE): # ESCが押された? return # Joystick関連のイベントチェック #Joystick if e.type == pygame.locals.JOYAXISMOTION: joy_list[x][y] = pygame.time.get_ticks() - joy_list[x][y] print('joystick') L_stick_LR = '{:.1f}'.format(j.get_axis(0)) L_stick_updown = '{:.1f}'.format(j.get_axis(1)) #符号変換 L_stick_updown = float(L_stick_updown) * -1 L_stick_updown = str(L_stick_updown) R_stick_LR = '{:.1f}'.format(j.get_axis(4)) R_stick_updown = '{:.1f}'.format(j.get_axis(3)) back_button = '{:.1f}'.format(j.get_axis(2)) print('左スティック:', L_stick_updown, L_stick_LR) print('右スティック:', R_stick_updown, R_stick_LR) print('バックスティック:', back_button) L_stick = L_stick_updown + ',' + L_stick_LR + 'z' print(L_stick.encode()) ser.write(L_stick.encode()) #十字キー elif e.type == pygame.locals.JOYHATMOTION: #print ('hat motion') x,y = j.get_hat(0) joy_list[x][y] = pygame.time.get_ticks() cross_key = str(float(y)) + ',' + str(float(x)) + 'z' print(cross_key.encode()) ser.write(cross_key.encode()) #各種ボタン押下 elif e.type == pygame.locals.JOYBUTTONDOWN: print (str(e.button)+'番目のボタンを押した') key_list[e.button] = pygame.time.get_ticks() #各種ボタン離脱 elif e.type == pygame.locals.JOYBUTTONUP: print('ボタン'+str(e.button)+'を離した') key_list[e.button] = pygame.time.get_ticks() - key_list[e.button] #print("frame : " + str(key_list[e.button]/1000*60 )) if __name__ == '__main__': main() ser.close() #COMポートを閉じる
上記2つのソースコードはgithubでも公開しています。
joystickの十字キーと左スティックを動かしたときにタイヤが回れば成功です。
次回はmqttを使ったpubとsubについて説明します。
それではまた!
この記事へのコメントはありません。