# ROS-STM32 communication [TOC] ## USB轉串口模塊 常見的有:CH340,CP2102 we use PL2303 USB to TTL(手邊剛好有) ![](https://i.imgur.com/uUvDAJI.png) linux: 一般情況不須另外安裝驅動程式,若需要請查看下面文章: https://www.796t.com/content/1541534290.html 1. 利用下面指令確認是否已有驅動程式支援: ```![](https://i.imgur.com/r0aDEDf.png) $ lsmod |grep pl2303 ``` ![](https://i.imgur.com/ZaFumwT.png) 若有驅動程式,會得到類似的資訊。 2. 檢視系統資訊: ``` $ dmesg | tail -f ``` ![](https://i.imgur.com/0b3J0RD.png) 由上面結果可以看到裝置為ttyUSB0 3. 尋找serial port的資訊 ``` udevadm info -a -n /dev/ttyUSB0 udevadm info -a -n /dev/ttyUSB1 udevadm info -a -n /dev/ttyUSB2 ``` ![](https://i.imgur.com/ySmIrLF.png) ![](https://i.imgur.com/CePUdm3.png) 4. 利用上述資訊創建自定義的rules rules名字自己取 ``` $ sudo vim /etc/udev/rules.d/rplidar_imu_stm32_port.rules ``` In the file: ``` KERNEL=="ttyUSB*", ATTRS{devpath}=="3.3", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="front_left_laser" KERNEL=="ttyUSB*", ATTRS{devpath}=="3.2", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="back_right_laser" KERNEL=="ttyUSB*", ATTRS{devpath}=="3.1", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60",, MODE:="0777", SYMLINK+="imu" ~ ~ ``` # KERNEL=="ttyUSB*": 把所有的ttyUSB都叫出來修改,並符合後面條件的都叫出來修改。 # MODE:="0777": MODE代表賦予串口端口的權限,"0777"是具體的權限 # ATTRS{devpath}:用來使用在當廠商代碼跟商品代碼都一樣時,這個通常是電腦本身的port口的號碼,除此之外,如果像我們有另外接usb集線器就有可能會有"."。 # ATTRS{idVendor}:廠商代碼,有可能rpli imu這類的都會有一樣的名字。 # ATTRS{idProduct}: 商品代碼,有可能rpli imu這類的都會有一樣的名字,因為通訊的東西都一樣。 # SYMLINK+="stm32_port": 別名,"stm32_port" 是自己取的別名 :warning: 通常devpath都是選第一次出現的devpath因為在那裡才有標明確切在集線器的位置。 4. 重新加載udev規則 ``` $ service udev reload $ service udev restart ``` 5. 拔插USB之後,查詢更改結果 ``` ls -l /dev/ | grep ttyUSB ``` ![](https://i.imgur.com/HOiBZgB.png) 結果類似截圖,則表示更改完成! https://leidawt.github.io/post/%E5%9C%A8stm32%E4%B8%8A%E8%BF%90%E8%A1%8Cros%E8%8A%82%E7%82%B9-rosserial-stm32%E5%BC%80%E5%8F%91%E5%8F%8A%E8%B0%83%E8%AF%95%E6%96%B9%E6%B3%95/ ## rosserial (failed) 主要按照第二個連結影片步驟: https://blog.csdn.net/leida_wt/article/details/109690562 https://www.bilibili.com/s/video/BV19B4y1M7f3 安裝rosserial_stm, 修改stm32cubeIDE程式碼, 執行 但最後rosrun時, reqiring topic失敗 ![](https://i.imgur.com/HuJ532N.png) ## 07/28 問學長方法 1. 利用screen /dev/ttyUSB0 115200 (在terminal),先確認STM32是否有正確傳送訊息 2. 之後在ros寫node:建議用pyserial https://pyserial.readthedocs.io/en/latest/shortintro.html :::info $ screen /dev/ttyUSB0 9600 (usb port and baud) * Close screen: ctrl+a -> K -> y ::: 目前問題: * linux terminal screen ttyUSB0 沒有訊息 * 改成 screen ttyACM0 才出現訊息 * STM32 Debug Console 新增ttyACM0也可以查看 * ttyACM0 是 STM32 micro usb 傳輸線 * ttyUSB0 是 uart 傳輸線訊息 解決: * 把 uart2 換成 uart3 pin 則可以成功傳送 ## Linux terminal command <-> STM32 ### STM32 Send Message In STM32CubeIDE: 1. Connectivity: USART3 2. Mode: Asynchronous 3. Baud rate: 115200 4. Code in while loop: ``` HAL_UART_Transmit(&huart3, (uint8_t*)"Hello World!\n\r", sizeof("Hello World!\n\r")-1, 1000); HAL_Delay(200); ``` 5. Run In Linux terminal: 1. find Uart port ``` $ ls -l /dev/ttyUSB* ``` 2. screen the message STM32 sending ``` $ screen /dev/ttyUSB4 115200 ``` ![](https://i.imgur.com/GAx5P6k.png) 3. close screen ctrl+a -> K -> y ### STM32 Receive message In STM32CubeIDE: 1. Connectivity: USART3 2. Mode: Asynchronous 3. Baud rate: 115200 4. Code in Private user code: ``` uint8_t Rx_data[10]; ``` 6. Code in while loop: ``` HAL_UART_Receive(&huart3, Rx_data, 10, 100); ``` 5. Debug 6. Llive Expression 7. Add New Expression: Rx_data 8. Resume In Linux terminal: 1. Set baud rate ``` $ stty -F /dev/ttyUSB0 115200 ``` 2. Write message to the uart ``` $ echo "Helloworld" > /dev/ttyUSB0 ``` ![](https://i.imgur.com/owWQInk.png) ## Pyserial ### install ``` $ sudo apt-get install python3 $ sudo apt install python3-pip $ sudo pip3 install pyserial $ python3 -m pip show pyserial ``` ![](https://i.imgur.com/qBGQ7Hk.png) ``` $ mkdir pyserial_ws $ cd pyserial_ws $ touch receive.py $ vim receive.py ``` In the file: ``` import serial ser = serial.Serial() ser.port = '/dev/ttyUSB0' ser.baudrate = 115200 ser.open() while(True): line = ser.readline() print(line) ``` ``` $ python receive.py ``` ![](https://i.imgur.com/mfyYDje.png) ## keyboard control stm32 motors ### Method 1: teleop_twist_keyboard + base_controller teleop_twist_keyboard: https://github.com/ros-teleop/teleop_twist_keyboard base_controller: subscribe data type: geometry_msgs.msg / Twist ![](https://i.imgur.com/QXjdgD7.png) ### Method 2: (目前執行方案) import keyboard + keyboard_control keyboard_control: subscribe data type: std_msgs.msg / String ![](https://i.imgur.com/xbNzxYZ.png) **Github file:** Ros: https://github.com/PeiChi-Hu/unmanned_car_KeyboardUartToSTM32 keyboard_control pkg & base_controller pkg STM32: https://github.com/PeiChi-Hu/unmanned_car_stm/tree/main/keyboard0805 terminal 1: ``` $ roscore ``` terminal 2: ``` $ source /opt/ros/noetic/setup.bash $ source ~/stm32_ws/devel/setup.bash $ rosrun base_controller keyboard_control.py ``` terminal 3: ``` $ sudo su (enter root) $ source devel/setup.bash (in workspace directory) $ rosrun keyboard_control keyboard_control.py $ exit // exit root ``` Use command sudo su to enter root, because python keyboard import function requires root. :small_red_triangle:try to find some other ways to avoid root reqiurement. ### Method 3: import getkey + keyboard_control getkey function: :small_red_triangle: Issue: getkey(blocking=False) results in missed keyboard inputs https://github.com/kcsaff/getkey/issues/17 getkey(blocking=True): The keyboard status will remain until the next input. -> need to modify the STM32 code. :small_red_triangle:STM32 code: in the dc motor function, we put stop function at the end. However, the car didn't move. ### Method 4: import pynput + keyboard_control :small_red_triangle:Problem: pynput do not detect the keyboard inputs ### Method 5: import tkinker + keyboard_control tkinker: GUI module in python