Control with VESC driver

We describe the VESC control method in ROS using the VESC driver developed by Michael T. Boulet at MIT.

1. Use Custom App

VESC๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Custom App์ด๋ผ๋Š” ๋ถ€๋ถ„์„ ๋งŒ๋“ค์–ด ์ด ๋ถ€๋ถ„์ด ์‚ฌ์šฉ์ž๊ฐ€ ์ถ”๊ฐ€์ ์œผ๋กœ ๊ฐœ๋ฐœํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ์‰ฝ๊ฒŒ ํƒ‘์ œํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฐฐ๋ คํ•˜์˜€๋‹ค. OpenRobot์—์„œ ๊ฐœ๋ฐœํ•œ Custom App์€ VESC ๊ธฐ๋ณธ ํŽŒ์›จ์–ด์˜ application ํด๋”์— openrobot ํด๋”์— ์ €์žฅํ•ด๋†“์•˜๋‹ค.

๊ธฐ๋ณธ Firmware์— app_custm.c ๋ผ๋Š” ํŒŒ์ผ์ด custom app์˜ ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ๊ณณ์— ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ ์˜ˆ์ œ๋งŒ์„ ๋ณด๊ณ ๋กœ์ฒ˜์Œ๋ถ€ ์ง์ ‘ custom app์„ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ์€ ์‰ฌ์šด ์ผ์ด ์•„๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ VESC ํŽŒ์›จ์–ด์˜ ๋™์ž‘์›๋ฆฌ์— ๋Œ€ํ•ด ๋จผ์ € ์ดํ•ดํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

VESC์—๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ†ต์‹  ์ฑ„๋„๋“ค์ด ์žˆ๊ณ  ๋Œ€ํ‘œ์ ์œผ๋กœ UART, USB ํ†ต์‹ ์ด VESC์— ๋ช…๋ น์„ ๋‚ด๋ฆด ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” VESC์˜ ํ†ต์‹  Protocol์— ๋Œ€ํ•ด ๋จผ์ € ์„ค๋ช…ํ•˜๊ฒ ๋‹ค.

๋ณธ ๋‚ด์šฉ์€ ์•„๋ž˜ ํ™ˆํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ ํ•˜์˜€๋‹ค.

โ€‹http://vedder.se/2015/08/vesc-writing-custom-applications/โ€‹

โ€‹http://vedder.se/2015/10/communicating-with-the-vesc-using-uart/โ€‹

1. VESC ํ†ต์‹  Protocol

VESC์˜ ํ†ต์‹  ํ”„๋กœํ† ์ฝœ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ํ•˜๊ณ  ์žˆ๋‹ค. ๋ฐ์ดํ„ฐ๋Š” Packet ๋‹จ์œ„๋กœ ์ „์†ก๋˜๋ฉฐ Packet์€ ์ „์†กํ•˜๊ณ ์ž ํ•˜๋Š” Data ์˜ ์‚ฌ์ด์ฆˆ์— ๋”ฐ๋ผ Short Packet ๊ณผ Long Packet์˜ ๋‘ ๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋‹ค.

  • Short Packet

1st Byte

2nd Byte

3rd ~ (n-3)th Byte

(n-2)th Byte

(n-1)th Byte

(n)th Byte

2

packet length

data

CRC High

CRC Low

3

Short Packet ์€ ์ฒซ๋ฒˆ์งธ Byte ์ˆซ์ž 2๋กœ ์‹œ์ž‘ํ•œ๋‹ค. ์ดํ›„ 2๋ฒˆ์งธ Byte์— packet์˜ ๊ธธ์ด ๊ฐ’์„ ๋„ฃ๋Š”๋‹ค. 3๋ฒˆ์งธ Byte๋ถ€ํ„ฐ๊ฐ€ ์‹ค์ œ ๋ฐ์ดํ„ฐ์ด๋ฉฐ ์ „์†กํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ์— ๋”ฐ๋ผ ์ด ๋ถ€๋ถ„์ด ์ฐจ์ง€ํ•˜๋Š” ํฌ๊ธฐ๋Š” ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค. ์ดํ›„ ๋งˆ์ง€๋ง‰์—์„œ 3๋ฒˆ์งธ์™€ 2๋ฒˆ์งธ์— CRC Check sum์„ ์œ„ํ•œ 2๊ฐœ์˜ Byte๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ  ๋งˆ์ง€๋ง‰ Byte๋Š” Stop Byte๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ ์ˆซ์ž 3์„ ์‚ฌ์šฉํ•œ๋‹ค.

Short Packet ์€ Packet์˜ ํฌ๊ธฐ๋ฅผ ํ‘œํ˜„ํ•˜๋Š”๋ฐ 1Byte๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ 1Byte๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ์ˆซ์ž์˜ ํฌ๊ธฐ๋Š” 0~255๊นŒ์ง€์ด๋ฏ€๋กœ Short Packet์— ์‹ค๋ ค์„œ ์ „์†ก๋  ์ˆ˜ ์žˆ๋Š” ์‹ค์ œ data์˜ ํฌ๊ธฐ๋Š” 255 Byte๊ฐ€ ์ตœ๋Œ€๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค. ์ด๋ ‡๊ฒŒ Short Packet์— ์ตœ๋Œ€๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์–ด์„œ ์ „์†กํ•˜๊ฒŒ ๋˜๋ฉด ์ „์ฒด packet์˜ ์‚ฌ์ด์ฆˆ๋Š” 1(์‹œ์ž‘) + 1(length) + 255(data) + 2(crc) + 1(stop) = 260 Byte๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๋งˆ์ดํฌ๋กœํ”„๋กœ์„ธ์„œ์—์„œ int32, float๋“ฑ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ 4byte ๋ฐ์ดํ„ฐํ˜•์ด๋ฏ€๋กœ ๋‹จ์ˆœ ๊ณ„์‚ฐ์œผ๋กœ ์ƒ๊ฐํ•ด๋ณด๋ฉด 255 Byte๋Š” 63๊ฐœ์˜ float ๋ณ€์ˆ˜๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ์‚ฌ์ด์ฆˆ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  • Long Packet

1st Byte

2nd Byte

3rd Byte

4th ~ (n-3)th Byte

(n-2)th Byte

(n-1)th Byte

(n)th Byte

3

packet

length High

packet

length Low

data

CRC High

CRC Low

3

Long Packet ์€ ์ฒซ๋ฒˆ์งธ Byte๊ฐ€ ์ˆซ์ž 3์œผ๋กœ ์‹œ์ž‘ํ•˜๊ณ  ์ด์–ด์„œ 2~3๋ฒˆ์งธ Byte๊ฐ€ packet length์— ํ•ด๋‹นํ•œ๋‹ค. Packet length์— 2Byte๋ฅผ ํ• ๋‹นํ•˜๋ฏ€๋กœ ์ตœ๋Œ€๋กœ ์ „์†ก๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ์˜ ์–‘์€ 65535 Byte๊ฐ€ ๋œ๋‹ค. ์ด๋Š” Short Packet์— ๋น„ํ•ด 257๋ฐฐ ๋” ํฐ ๋ฐ์ดํ„ฐ๋Ÿ‰์— ํ•ด๋‹นํ•œ๋‹ค. ์ดํ›„ Byte์—๋Š” Short Packet๊ณผ ๋™์ผํ•˜๊ฒŒ CRC์— 2Byte์™€ Stop Byte๋กœ ์ˆซ์ž 3์ด ์“ฐ์ธ๋‹ค.

2. VESC ํ†ต์‹  Interface

VESC์˜ ํ†ต์‹  ํ”„๋กœํ† ์ฝœ์— ๋Œ€ํ•ด์„œ๋Š” ์•ž์—์„œ ์ด์•ผ๊ธฐ ํ•˜์˜€์œผ๋ฉฐ ์ด ๋ถ€๋ถ„์—์„œ๋Š” VESC ํ†ต์‹ ์˜ Interface์— ๋Œ€ํ•ด ๋‹ค๋ฃฌ๋‹ค. VESC๋Š” ๋‹ค์–‘ํ•œ ํ†ต์‹ ๋ฐฉ์‹์„ ์ง€์›ํ•œ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ UART์™€ USB ๊ทธ๋ฆฌ๊ณ  CANํ†ต์‹ ์ด ์žˆ๋‹ค.

USB๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ VESC-Tool์„ ์ด์šฉํ•  ๋•Œ ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ์ด๋Š” ํ†ต์‹ ๋ฐฉ์‹์ด๋ฉฐ ROS(Robot Operating System)์„ ์ด์šฉํ•˜์—ฌ VESC๋ฅผ ์‹ค์‹œ๊ฐ„ ์ œ์–ดํ•  ๋•Œ๋„ ์ฃผ๋กœ USB๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค.

UART๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ USB-Serial Adapter๋ฅผ ์ด์šฉํ•˜๋ฉด USB๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•˜๊ฒŒ VESC-Tool์ด๋‚˜ ROS๋“ฑ์— ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ, UART๋Š” ๋ธ”๋ฃจํˆฌ์Šค ๋™๊ธ€(nRF51822)์„ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฌด์„ ์œผ๋กœ ์•ˆ๋“œ๋กœ์ด๋“œ์šฉ VESC-Tool์—์„œ VESC๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

CAN ํ†ต์‹ ์€ ๋‹ค์ˆ˜์˜ VESC๋ฅผ ์„œ๋กœ ์—ฐ๊ฒฐํ•˜์—ฌ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ฉฐ ํ†ต์‹ ๋ฐ์ดํ„ฐ๋ฅผ Forwardingํ•˜์—ฌ ํ•˜๋‚˜์˜ VESC๋กœ ์ „๋‹ฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฅธ VESC๋กœ ์ „๋‹ฌํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

์ด๋ฐ–์—๋„ I2C ํ†ต์‹ ์„ ์ด์šฉํ•˜์—ฌ ๋ฌด์„  ์ œ์–ด๊ธฐ์ธ Nunchuk(๊ณผ๊ฑฐ ๋‹Œํ…๋„ Wii ๊ฒŒ์ž„ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์‚ฌ์šฉ๋จ)์„ ์ด์šฉํ•ด VESC๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค. I2C ํ†ต์‹ ์€ IMU์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด๋“ค์ด๊ธฐ ์œ„ํ•ด์„œ๋„ ์‚ฌ์šฉ๋˜๋ฉฐ ํ˜„์žฌ VESCular์—๋Š” Bosch ์‚ฌ์˜ BMI160 IMU๊ฐ€ On-board์— ํƒ‘์žฌ๋˜์–ด Custom App์„ ์‚ฌ์šฉ์‹œ ๊ธฐ๋ณธ์ ์œผ๋กœ IMU ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฐ–์—๋„ SPI ํ†ต์‹ ์€ Magnetic Encoder์ธ AS5047p์™€ ์—ฐ๊ฒฐ์‹œ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ํŠน์ดํ•œ ์ ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” Hardware SPI๊ฐ€ ์•„๋‹Œ Software SPI๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ(Firmware์—์„œ Hardware SPI๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฐ”๊ฟ€์ˆ˜๋Š” ์žˆ๋‹ค)์ด๊ณ  DRV8301(Mosfet Gate Driver)๊ณผ์˜ ํ†ต์‹ ๋„ Software SPI ํ†ต์‹ ์„ ์ด์šฉํ•œ๋‹ค.

Hardware SPI๋Š” PA4~PA7์— ํ• ๋‹น๋œ SPI1 ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด ํ•€๋“ค์€ UART ๋ฐ I2C ํ†ต์‹ ์œผ๋กœ๋„ Alternate ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— PA4~PA7์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋Š” ํ†ต์‹  ๊ธฐ๋Šฅ์€ UART, I2C, SPI ์„ธ๊ฐ€์ง€ ํ†ต์‹ ์ค‘ ๋™์‹œ์— ํ•˜๋‚˜๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

OpenRobot App์—์„œ๋Š” Hardware SPI ํ†ต์‹ ์„ ์ด์šฉํ•˜์—ฌ Arduino์™€ ๊ณ ์† ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜์—ฌ VESC์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์‚ฌํ•ญ์„ ๋ชฐ๋ผ๋„ Arduino์—์„œ SPI ํ†ต์‹ ์„ ํ†ตํ•ด ์ œ์–ด๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ”„๋กœ๊ทธ๋žจํ•˜์˜€๋‹ค. Hardware SPI ํ†ต์‹  ๊ธฐ๋Šฅ์€ OpenRobot App์˜ ๋…์ž์ ์ธ ๊ธฐ๋Šฅ์ด๋‹ค.

์•„๋ž˜ ํ‘œ์— VESC์˜ ํ†ต์‹  Interface๋ฅผ ๋ชจ๋‘ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

ํ†ต์‹ ์ฑ„๋„

์‚ฌ์šฉ

ํ†ต์‹ ์†

USB

VESC-Tool, ROS

๊ธฐ๋ณธ 115200bps, ์ตœ๋Œ€ 3000000bps

UART

VESC-Tool, ROS, Bluetooth

๊ธฐ๋ณธ 115200bps, ์ตœ๋Œ€ 921600bps

CAN

VESC to VESC

๊ธฐ๋ณธ 500Kbps, ์ตœ๋Œ€ 1Mbps

I2C (Software)

Nunchuk, IMU

๊ธฐ๋ณธ 1Mbit/sec, ์ตœ๋Œ€ 2Mbit/sec

SPI (Software)

DRV8301, AS5047p

Bit-banging (didn't measure yet)

SPI (Hardware)

Arduino (OpenRobot App Only)

๊ธฐ๋ณธ 4Mhz, ์ตœ๋Œ€ 8Mhz(Clock Speed)

VESC ๊ธฐ๋ณธ ํŽŒ์›จ์–ด์—์„œ๋Š” I2C ๋ฐ SPI ํ†ต์‹ ์„ Software ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜์˜€๋Š”๋ฐ, ์ด๋Š” STM32F4x์—์„œ ์ œ๊ณตํ•˜๋Š” ํŠน์ • ํ•€๋งˆ๋‹ค ํ• ๋‹น๋œ ํ•˜๋“œ์›จ์–ด์ ์ธ ํ†ต์‹  Pin์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹์ด ์•„๋‹Œ, ์ผ๋ฐ˜์ ์ธ digital IO๋ฅผ ์ด์šฉํ•˜์—ฌ ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•œ ๊ฒƒ์œผ๋กœ ์•„๋‘์ด๋…ธ ์šฐ์˜ software serial ๊ณผ ์œ ์‚ฌํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ณด๋ฉด ๋œ๋‹ค.

์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•œ ๋ฐ๋Š” ์•„๋ฌด๋ž˜๋„ ๋ชจํ„ฐ ์ œ์–ด์— ์ข€๋” ํ•˜๋“œ์›จ์–ด ๋ฆฌ์†Œ์Šค๋ฅผ ๋” ํˆฌ์ž…ํ•˜๊ณ ์ž ํ•˜๋Š” ์˜๋„๊ฐ€ ๋ณด์ธ๋‹ค. Hardware ํ†ต์‹  ์ฑ„๋„์„ ์ด์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์•„๋ฌด๋ž˜๋„ ํ†ต์‹ ์‹œ Hardware ์ธํ„ฐ๋ŸฝํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ณ  ์ด ์ƒํ™ฉ์—์„œ ๋ชจํ„ฐ์ œ์–ด๋ฅผ ์œ„ํ•œ Interrupt ๋“ฑ๊ณผ ์ซ‘๋‚ ์ˆ˜ ์žˆ์–ด์„œ ํŽŒ์›จ์–ด๊ฐ€ ๋ฉˆ์ถฐ๋ฒ„๋ฆฌ๊ฑฐ๋‚˜ ๋ฆฌ์…‹๋˜๋Š” ๋ฌธ์ œ๋“ฑ์ด ๋ฐœ์ƒํ•  ์œ„ํ—˜์†Œ์ง€๊ฐ€ ์žˆ๋‹ค. ๋ฌผ๋ก  ํ”„๋กœ๊ทธ๋žจ์„ ์ž˜ ๋งŒ๋“ค๋ฉด ์ด๋Ÿฐ ์ƒํ™ฉ์„ ํ”ผํ•  ์ˆ˜๋Š” ์žˆ๊ฒ ์ง€๋งŒ, software ์ ์œผ๋กœ๋„ ์ถฉ๋ถ„ํžˆ ์›ํ™œํ•œ ํ†ต์‹  ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ๊ตณ์ด Hardware ๋ฐฉ์‹์„ ๊ฐˆ ํ•„์š”๋Š” ์—†๋‹ค.

๊ตณ์ด Hardware ํ†ต์‹  ๋ฐฉ์‹์„ ์จ์•ผํ•  ๋•Œ๋Š” ๊ณ ์†์˜ ํ†ต์‹ ์ด ์š”๊ตฌ๋  ๋•Œ์ด๋ฉฐ, VESCuino์˜ ๊ฒฝ์šฐ์—๋Š” Hardware SPIํ†ต์‹ ์„ ์ด์šฉํ•ด ์•„๋‘์ด๋…ธ Due์™€ ์ตœ๋Œ€ 8Mhz SPI Clock ์Šคํ”ผ๋“œ๋กœ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜์—ฌ ๊ณ ์†์˜ ์‹ค์‹œ๊ฐ„ ์ œ์–ด(Low Latency)์— ์œ ๋ฆฌํ•˜๋‹ค.

3. VESC์˜ ํ†ต์‹  Software Architecture

์•ž์—์„œ ์–ธ๊ธ‰ํ•œ ๋‹ค์–‘ํ•œ ํ†ต์‹ ์ฑ„๋„์— ๋น„ํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” software ๋ฃจํ‹ด์€ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค. ์ด๋Š” ๋ชจ๋“  ํ†ต์‹  ์ฑ„๋„์—์„œ ๋“ค์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•˜์—ฌ ์‹ค์ œ data๋งŒ ์ถ”์ถœํ•œ ํ›„ ์ด๋ฅผ ํ•ด์„ํ•˜๋Š” ๊ตฌ๋ฌธ์ด ํ•œ ๊ณณ์—์„œ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋„๋ก ์„ค๊ณ„ํ•ด๋†“์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

VESC ํŽŒ์›จ์–ด์—์„œ๋Š” C์–ธ์–ด๋กœ ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ํ†ต์‹  ์ฑ„๋„๋งˆ๋‹ค ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ์„ ์œ„ํ•œ ํ•จ์ˆ˜๋ฅผ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋ฐ”๊ฟ”์ค„ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ผ๋Š” ๊ฒƒ์ด ์กฐ๊ธˆ ์ƒ์†Œํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ธ๋ฐ ์ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • UART ํ†ต์‹ 

VESC-Tool์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด ํฌ๊ฒŒ ๋‘๊ฐœ์˜ ํŒŒํŠธ๋กœ ๋‚˜๋‰˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ์•Œ์ˆ˜ ์žˆ๋Š”๋ฐ ๋ฐ”๋กœ Motor setting ๋ถ€๋ถ„๊ณผ App setting ๋ถ€๋ถ„ ๊ทธ๋ฆฌ๊ณ  Data Analysis ์ด๋‹ค. Motor setting์€ ๋ชจํ„ฐ์˜ Identification ๋ฐ ์ œ์–ดGain๋“ฑ์˜ ์„ธํŒ…๊ณผ ๊ด€๋ จ๋œ ๋ถ€๋ถ„์ด๊ณ  App setting์€ ์–ด๋– ํ•œ App์„ ์‹คํ–‰์‹œํ‚ฌ๊ฑด์ง€ ๊ทธ๋ฆฌ๊ณ  ํŠน์ • App ์ด ์‹คํ–‰์ค‘์ผ๋•Œ ์ด์— ๊ด€ํ•œ ์„ธํŒ…์— ๋Œ€ํ•œ ๋ถ€๋ถ„์ด๋‹ค. ์„ธํŒ…๊ณผ ๊ด€๋ จ๋œ ๋‘ ๋ถ€๋ถ„์€ ๊ฐ๊ธฐ ๋ถ„๋ฆฌ๋œ ์ €์žฅ์˜์—ญ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋…๋ฆฝ์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ์ €์žฅ์‹œํ‚ค๋„๋ก ๋˜์–ด์žˆ๋‹ค. ํ˜„์žฌ VESC-Tool์—์„œ ์„ ํƒ๊ฐ€๋Šฅํ•œ App์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค(VESC FW ver5.02 ๊ธฐ์ค€).

No App
PPM
ADC
UART
PPM and UART
ADC and UART
Nunchuk (I2C, Nyko Kama)
NRF
Custom User App
Balance
PAS
ADC and PAS

์•ž์—์„œ ์–ธ๊ธ‰ํ•œ ๋ฐ”์™€ ๊ฐ™์ด VESC์—์„œ ํ†ต์‹ ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ์ปค๋„ฅํ„ฐ๋Š” ์—ฌ๋Ÿฌ ํ†ต์‹ ์ด ํ†ตํ•ฉ๋˜์–ด ์žˆ์–ด ํ•œ๋ฒˆ์— ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜๋Š” ์—†๋‹ค. ๊ทธ๋ž˜์„œ ์œ„์™€ ๊ฐ™์ด App์„ ์„ ํƒํ•˜์—ฌ ํ†ต์‹ ํ•€์ด ์ „์›์ธ๊ฐ€ํ›„ ์ดˆ๊ธฐํ™”๋  ๋•Œ ์›ํ•˜๋Š” ํ†ต์‹ ํ•€์˜ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ธํŒ…๋œ๋‹ค.

UARTํ†ต์‹ ์„ ์œ„ํ•ด์„œ๋Š” Tx, Rx (Tx๋Š” ์†ก์‹ , Rx๋Š” ์ˆ˜์‹ )๋ฅผ ์œ„ํ•œ Pin์ด ์š”๊ตฌ๋˜๋ฉฐ ์ด๋ฅผ ๋ฐ˜๋Œ€ํŽธ ํ†ต์‹ ์ธก๊ณผ ์•„๋ž˜์™€ ๊ฐ™์ด ์—ฐ๊ฒฐํ•˜๋ฉด UARTํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. UART ํ†ต์‹ ์€ ๋ฐ˜๋“œ์‹œ GND๋ฅผ ๋™์ผํ•˜๊ฒŒ ํ•ด์ค˜์•ผํ•˜๋ฏ€๋กœ ์‹ค์งˆ์ ์œผ๋กœ๋Š” 3๊ฐœ์˜ ์„ ์ด ์„œ๋กœ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•œ๋‹ค.

VESC ์ชฝ TX - ๋ฐ˜๋Œ€์ชฝ RX
VESC ์ชฝ RX - ๋ฐ˜๋Œ€์ชฝ TX
VESC ์ชฝ GND - ๋ฐ˜๋Œ€์ชฝ GND

UART ํ†ต์— ๊ด€ํ•ด์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์•„๋ž˜์˜ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ดํŽด๋ณด์•„์•ผ ํ•œ๋‹ค.

app_uartcomm.c
packet.c
commands.c

์œ„ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ตฌ์กฐ๋ฅผ ์ž˜ ์ดํ•ดํ•˜๋ฉด ์ „์ฒด์ ์ธ VESC์˜ ํ†ต์‹  ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ๋˜๋Š”๋ฐ, ์šฐ์„  app_uartcomm.c์—์„œ๋Š” app_uartcomm_start()ํ•จ์ˆ˜์—์„œ UART ํ†ต์‹ ์„ ์œ„ํ•œ Pin ์„ค์ •๊ณผ UART ํ†ต์‹ ์„ ์ฒ˜๋ฆฌํ•˜๋Š” Thread๋ฅผ ์‹คํ–‰์‹œํ‚จ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ด์ „์— packet_init ํ•จ์ˆ˜์—์„œ UART ํ†ต์‹ ์˜ ๋ฐ์ดํ„ฐ Packet์„ ์ฒ˜๋ฆฌํ•  ํ•จ์ˆ˜๋“ค์„ ์„ ํƒํ•ด์ฃผ ํ•จ์ˆ˜ํฌ์ธํ„ฐ๋ฅผ ์ง€์ •ํ•œ๋‹ค.

void app_uartcomm_start(void) {
// UART ํ†ต์‹  Packet์„ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ง€์ •ํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜ํฌ์ธํ„ฐ
packet_init(send_packet, process_packet, PACKET_HANDLER);
โ€‹
// UART ํ†ต์‹ ์ฒ˜๋ฆฌ Thread
if (!thread_is_running) {
chThdCreateStatic(packet_process_thread_wa, sizeof(packet_process_thread_wa),
NORMALPRIO, packet_process_thread, NULL);
thread_is_running = true;
}
// UART Pin ์„ค์ •๋ถ€
sdStart(&HW_UART_DEV, &uart_cfg);
palSetPadMode(HW_UART_TX_PORT, HW_UART_TX_PIN, PAL_MODE_ALTERNATE(HW_UART_GPIO_AF) |
PAL_STM32_OSPEED_HIGHEST |
PAL_STM32_PUDR_PULLUP);
palSetPadMode(HW_UART_RX_PORT, HW_UART_RX_PIN, PAL_MODE_ALTERNATE(HW_UART_GPIO_AF) |
PAL_STM32_OSPEED_HIGHEST |
PAL_STM32_PUDR_PULLUP);
โ€‹
uart_is_running = true;
}

๋ฐ”๋กœ ์ด packet_init ํ•จ์ˆ˜๊ฐ€ ๋งค์šฐ ์ค‘์š”ํ•œ๋‹ค. packet_init ํ•จ์ˆ˜์˜ ์›ํ˜•์„ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. packet.c์— ๊ฐ€๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋˜์–ด์žˆ๋‹ค. packet_init ํ•จ์ˆ˜์˜ ์ฒซ๋ฒˆ์งธ input์—๋Š” send_func(์†ก๋ฅผ ์œ„ํ•œ ํ•จ์ˆ˜)์˜ ํ•จ์ˆ˜ํฌ์ธํ„ฐ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ณ  ๋‘๋ฒˆ์งธ input์—๋Š” process_func(์ˆ˜์‹ ์„ ์œ„ํ•œ ํ•จ์ˆ˜)์˜ ํ•จ์ˆ˜ํฌ์ธํ„ฐ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

void packet_init(void (*s_func)(unsigned char *data, unsigned int len),
void (*p_func)(unsigned char *data, unsigned int len), int handler_num) {
memset(&m_handler_states[handler_num], 0, sizeof(PACKET_STATE_t));
m_handler_states[handler_num].send_func = s_func;
m_handler_states[handler_num].process_func = p_func;

๊ทธ๋Ÿผ ์•ž์—์„œ UART ํ†ต์‹ ์˜ ๊ฒฝ์šฐ๋ฅผ ์‚ดํŽด๋ณด๋ฉด packet_init ํ•จ์ˆ˜์˜ ์ฒซ๋ฒˆ์งธ input์œผ๋กœ ์ง€์ •ํ•œ send_packet ํ•จ์ˆ˜์˜ ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

static void send_packet(unsigned char *data, unsigned int len) {
if (uart_is_running) {
sdWrite(&HW_UART_DEV, data, len);
}
}

send_packet ํ•จ์ˆ˜๋Š” app_uartcomm.c ํŒŒ์ผ์•ˆ์— ์žˆ์œผ๋ฉฐ ๋‹จ์ˆœ์ด data์™€ data์˜ ๊ธธ์ด(len)๋ฅผ ์•Œ๋ฉด ์ด๋ฅผ UART ํ†ต์‹ ์œผ๋กœ ์ „์†กํ•˜๋Š” ์ž„๋ฌด๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

packet_init ํ•จ์ˆ˜์˜ ๋‘๋ฒˆ์งธ input์ธ process_packet ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. process_packet ํ•จ์ˆ˜๋„ app_uartcomm.c ํŒŒ์ผ์•ˆ์— ์žˆ์œผ๋ฉฐ data์™€ data์˜ ๊ธธ์ด(len)์„ commands_process_packet ํ•จ์ˆ˜์— ์ „๋‹ฌํ•˜๋„๋ก ๋˜์–ด์žˆ์œผ๋ฉฐ commands_process_packet ํ•จ์ˆ˜๋Š” commands.c ํŒŒ์ผ์— ์ž‘์„ฑ๋˜์–ด ์žˆ๋‹ค.

static void process_packet(unsigned char *data, unsigned int len) {
commands_process_packet(data, len, app_uartcomm_send_packet);
}

์—ฌ๊ธฐ์„œ commands_process_packet ํ•จ์ˆ˜์˜ ์„ธ๋ฒˆ์งธ input์œผ๋กœ ์ง€์ •๋œ app_uartcomm_send_packet ํ•จ์ˆ˜๋Š” ์ผ๋ช… reply ํ•จ์ˆ˜๋กœ UARTํ†ต์‹ ์„ ํ†ตํ•ด ์—ฐ๊ฒฐ๋œ ์žฅ์น˜์—์„œ ์ „๋‹ฌํ•œ ๋ช…๋ น์— ๋Œ€ํ•œ ๋‹ต๋ณ€์„ ํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. ์•ž์—์„œ send_packet ํ•จ์ˆ˜์™€ ๋‹ค๋ฅธ ์ ์€ send_packet ํ•จ์ˆ˜๋Š” VESC ์ธก์—์„œ ๋จผ์ € ๋ฐ์ดํ„ฐ Packet์„ ์ „์†กํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜์ด๊ณ  app_uartcomm_send_packet ํ•จ์ˆ˜๋Š” UARTํ†ต์‹ ์œผ๋กœ ์—ฐ๊ฒฐ๋œ ๋ฐ˜๋Œ€์ชฝ ์žฅ์น˜์—์„œ ๋จผ์ € ๋ฐ์ดํ„ฐ Packet์ด ์ „์†ก๋˜์–ด ์ด์— ๋Œ€ํ•œ ๋‹ต๋ณ€์„ ์œ„ํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ๋Ÿผ ์‹ค์งˆ์ ์œผ๋กœ Data์˜ ํ๋ฆ„์ด ์–ด๋–ป๊ฒŒ ์ด๋ค„์ง€๋Š”์ง€ ์ข€ ๋” ์ž์„ธํ•˜๊ฒŒ ์•Œ์•„๋ณด์ž

โ€‹