- ๐ฏ ๋ฒ์ฉ RC์นด ํ๋ก์ ํธ ์๊ฐ
- ๐ ์ฃผ์ ๊ธฐ๋ฅ
- ๐์๋ฒ ๋๋ ์ค๊ณ๋
- ๐ ๋ฒ์ฉ RC์นด ํ๋ก์ ํธ ๊ตฌ์ฑ๋
- ๐ ๏ธ ๋์์ฑ ์ ์ด ๊ด๋ จ ์ ํ์กฐ๊ฑด ๊ตฌํ ๋ด์ฉ
- โจ ํ๋ก์ ํธ ํ์ผ ๊ตฌ์ฑ
- ๐ ๊ฐ๋ฐ์ ๋ฌธ์ ์ ๊ณผ ํด๊ฒฐ (ํธ๋ฌ๋ธ ์ํ )
- ๐ ์์คํ ์ปค์คํ ๊ฐ์ด๋
- ๐ฌ ํ์ ์๊ฐ ๋ฐ ์ญํ
RC ์นด์ ์ ์ด์ ๊ธฐ๊ธฐ ์ถ๊ฐ๋ฅผ ์ข ๋ ํ์ฅํ๊ธฐ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์ ์๋์์ต๋๋ค. ์ด ํ๋ก์ ํธ๋ ์๋์ ๊ฐ์ ๋ชฉ์ ์ ๊ฐ์ง๊ณ ์์ต๋๋ค:
- ๋ชจํฐ ๋ฐ ์ ์ด ์ฅ์น ํ์ฅ: DC ๋ชจํฐ, ์๋ณด ๋ชจํฐ ๋ฑ ๋ค์ํ ์๋ฒ ๋๋ ์ ์ด ์ฅ์น๋ฅผ ์ฝ๊ฒ ์ถ๊ฐํ๊ณ , ์ฌ์ฉ์ ๋ง์ถค ์ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํจ.
- ์ ์ด ๋ฐฉ๋ฒ์ ์ปค์คํฐ๋ง์ด์ง: WebSocket API, Bluetooth ๋ฑ์ ํตํด ์ฌ์ฉ์๊ฐ ๋ค์ํ ๋ฐฉ์์ผ๋ก RC ์นด๋ฅผ ์ ์ดํ ์ ์๋๋ก ์ ์ฐ์ฑ์ ์ ๊ณต.
- ํ์ฅ์ฑ๊ณผ ์์ ์ฑ ๊ฐํ: ํ๋ก์ธ์ค ๊ฐ ํต์ ๊ณผ ๋์์ฑ ์ ์ด๋ฅผ ํตํด ์์ ์ ์ด๋ฉฐ ํ์ฅ ๊ฐ๋ฅํ ์์คํ ๊ตฌ์ถ.
-
DC ๋ชจํฐ๋ฅผ ํ์ฉํ ์ ์ง ๋ฐ ํ์ง ๋ฐฉํฅ ์ ์ด
- RC์นด์ ์ ์ง ๋ฐ ํ์ง ๋ฐฉํฅ์ DC ๋ชจํฐ๋ก ์ ๋ฐํ๊ฒ ์ ์ดํฉ๋๋ค.
-
์๋ณด ๋ชจํฐ๋ฅผ ์ด์ฉํ ์คํ์นด ๋ชจ๋
- ์๋ณด ๋ชจํฐ๋ฅผ ํ์ฉํ์ฌ ์ฐจ๋์ ์คํ์นด ๋ชจ๋๋ฅผ ๊ตฌํํฉ๋๋ค.
-
์กฐ๋ ์ผ์ ๋ฐ LED๋ฅผ ํ์ฉํ ์คํ ๋ผ์ดํธ ๊ธฐ๋ฅ
- ์ฃผ๋ณ์ ๋ฐ๊ธฐ๋ฅผ ๊ฐ์งํ์ฌ ์๋์ผ๋ก ๋ผ์ดํธ๋ฅผ ์ผ๊ณ ๋๋ ๊ธฐ๋ฅ์ ๋๋ค.
-
์คํผ์ปค๋ฅผ ํ์ฉํ ๊ฒฝ์ ๊ธฐ๋ฅ
- ์คํผ์ปค๋ฅผ ํตํด RC์นด์ ๊ฒฝ์ ์๋ฆฌ๋ฅผ ์ง์ํฉ๋๋ค.
RC์นด๋ ๋ค์ํ ์ธํฐํ์ด์ค๋ฅผ ์ง์ํ์ฌ ์ ์ฐํ ์ ์ด๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
- WebSocket API : ์น(Web) ํ๊ฒฝ์ ํตํด ์ค์๊ฐ ์ ์ด ๊ฐ๋ฅ
- Bluetooth : ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์ Bluetooth๋ฅผ ํตํด ์ ์ด ๊ฐ๋ฅ
๊ตฌ์ฑ ์ค๋ช
1. ๊ฑด์ ์ง ์คํ
์ ์ ๊ณต๊ธ:
RC ์นด์ ๋ชจํฐ ์ ์ด๋ฐ ์๋ณด ๋ชจํฐ, ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด ๋ณด๋ ์ ์ ๊ณต๊ธ์ ์ฌ์ฉ
๊ฐฏ์ : 2๊ฐ
์ ์: 3.7V
์ฉ๋: 2000mAh
2. UART (๋ธ๋ฃจํฌ์ค ํต์ )
์ญํ :
๋ธ๋ฃจํฌ์ค ๋ชจ๋๊ณผ ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด ๊ฐ ํต์ ์ ํตํด RC ์นด์ ์๊ฒฉ ์ ์ด์ํ
ํ์ฉ: ์ค๋งํธํฐ ๋ฑ ์ธ๋ถ ์ฅ์น์์ ์กฐ์ข ๋ช ๋ น์ ์ ์ก
3. ์๋ณด ๋ชจํฐ (Servo Motor)
์ญํ :
์คํ ์นด ๋ชจ๋ ์ ์ด
RC ์นด์ ๊ฐ๋ ๋ฐ ์กฐํฅ ๋ฐฉํฅ์ ์ธ๋ฐํ๊ฒ ์กฐ์
4. DC ๋ชจํฐ์ ์ด๋ํฐ
์ญํ :
RC ์นด์ ๊ตฌ๋ ๋ฐ ๋ฐฉํฅ ์ ์ด
๋ชจํฐ ๋๋ผ์ด๋ฒ๋ฅผ ํตํด ์๋์ ๋ฐฉํฅ์ ์กฐ์
2๊ฐ์ DC ๋ชจํฐ๋ฅผ ์ฌ์ฉํ์ฌ RC ์นด๋ฅผ ์์ง์
5. LED ํ๊ณผ ์กฐ๋ ์ผ์
์ญํ :
์ฃผ๋ณ ์กฐ๋ ๊ฐ์ง๋ฅผ ํตํด ์คํ ๋ผ์ดํธ ๋ชจ๋ ๊ตฌํ
์กฐ๋ ์ผ์๊ฐ ์ด๋์ด ํ๊ฒฝ์ ๊ฐ์งํ๋ฉด LED๊ฐ ์๋์ผ๋ก ์ผ์ง
6. ์คํผ์ปค
์ญํ :
RC ์นด ๊ฒฝ์ ์ ๋ด๋๋ก ํจ
-
Controller RC ์นด์ ๋์์ ์ ์ดํ๋ฉฐ, ํ์ฌ ๋ฑ๋ก๋ Device ๋ฅผ ์ ์ดํฉ๋๋ค. Thread Pool์ ์ฌ์ฉํด ๋ณ๋ ฌ ์์ ์ ์ํํ๋ฉฐ, ํจ์จ์ ์ธ ๋ฆฌ์์ค ํ์ฉ๊ณผ ๋น ๋ฅธ ์๋ต์ฑ์ ๋ณด์ฅํฉ๋๋ค.
-
Connection Handler ์ธ๋ถ ์ ๋ ฅ(Bluetooth, WebSocket, Remote)์ ์ฒ๋ฆฌํ๋ฉฐ, ๋์ ์ฐ๊ฒฐ ์ ๊ฒฝ์ ์กฐ๊ฑด ๋ฐฉ์ง๋ฅผ ์ํด Mutex Lock์ ์ฌ์ฉํด ์์ ์ฑ์ ๋ณด์ฅํฉ๋๋ค.
-
IPC (Message Queue) ํ๋ก์ธ์ค ๊ฐ ๋ฐ์ดํฐ ๊ตํ์ ์ํ ๋น๋๊ธฐ ๋ฐ์ดํฐ ์ ๋ฌ ์ญํ ์ ์ํํฉ๋๋ค. ๋ฐ์ดํฐ๋ฅผ FIFO ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ๋ฉฐ, Connection Handler์ Controller ๊ฐ์ ์์ฌ์ํต์ ์ค์ฌํฉ๋๋ค.
-
Thread Pool Controller์ Connection Handler ๋ชจ๋์์ ์์ ์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ๋ฉฐ, ๋ฆฌ์์ค ์ต์ ํ ๋ฐ ์ฑ๋ฅ ํฅ์์ ๋๋ชจํฉ๋๋ค.
-
์ธ๋ถ ์ ์ด ์ํํธ์จ์ด WebSocket API์ Bluetooth ๋ชจ๋์ ํตํด ์ฌ์ฉ์๊ฐ ์ค์๊ฐ์ผ๋ก RC ์นด๋ฅผ ์ ์ดํ ์ ์์ต๋๋ค.
-
IPC ๋ฉ์์ง ํ
์ญํ : ํ๋ก์ธ์ค ๊ฐ ๋ฉ์์ง ์ ๋ฌ (Handler โ Controller).
ํน์ง: ๋น๋๊ธฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์์ ์ ํ๋ก์ธ์ค ํต์
// ๋ฉ์์ง ํ ์์ฑ์ ์ด๊ธฐํ
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = BUFSIZ;
attr.mq_curmsgs = 0;
// ๋ฉ์์ง ํ ์คํ
mq = mq_open(MESSAGE_QUEUE_NAME, O_CREAT | O_RDONLY, 0644, &attr);
if (mq == (mqd_t)-1) {
perror("mq_open failed");
return 1;
}
// ๋ฉ์์ง ํ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
n = mq_receive(mq, buf, sizeof(buf), NULL);
if (n == -1) {
perror("mq_receive failed");
continue;
}
// ๋ฉ์์ง ํ๋ก ์ ์ก
if (mq_send(mq, buffer, strlen(buffer), 0) == -1) {
perror("[Handler] Failed to send message");
}-
์ฐ๋ ๋ ํ
๊ตฌ์ฑ: Controller: Device Worker Thread Pool Handler: Connection Worker Thread Pool
์ด์ : ์ค์๊ฐ ์ฒ๋ฆฌ ๊ฐํ ๋ฆฌ์์ค ํจ์จํ (์ค๋ ๋ ์ฌ์ฌ์ฉ) : Device ์ ์ด ์ด๋ฒคํธ ๋ง๋ค ์ฐ๋ ๋๋ฅผ ์์ฑ ๋ฐ ์ข ๋ฃํ๋ฉด ๋ฆฌ์์ค์ ์ฑ๋ฅ์ ๋ถ๋ด์ด ์์ด์ ํ๋ก๊ทธ๋จ ์์์ ์ฐ๋ ๋๋ฅผ ์์ฑํ๊ณ ์ฌ์ฌ์ฉํ๊ฒ๋ ์ค๊ณ ํ์ฅ์ฑ ์ ์ง : ๋๋ฐ์ด์ค์ ์ ์ด ์ฅ์น๊ฐ ์ถ๊ฐ๋๋ฉด ํด๋น ์ฐ๋ ๋๋ฅผ ๋ ์์ฑํ๋ฉด ๋จ
// ๋ชจํฐ ์ ์ด ์ค๋ ๋๋ฅผ ์ด๊ธฐํ
for (int i = 0; i < MAX_MOTOR_TYPES; i++) {
motor_threads[i].motor_id = i;
motor_threads[i].is_active = 0;
pthread_mutex_init(&motor_threads[i].mutex, NULL);
pthread_cond_init(&motor_threads[i].cond, NULL);
pthread_create(&motor_threads[i].thread, NULL, motor_control_thread, &motor_threads[i]);
}-
์ปค๋ฅ์ ๋๊ธฐํ
๋ฌธ์ : ์ปค๋ฅ์ ๋ค์ค ์ง์ ์ํฉ์์ ์ ์ด ๋ช ๋ น์ ๋ํ ๊ฒฝ์ ์กฐ๊ฑด์ด ๋ฐ์ํจ, ์ ์ด ์ํํธ์จ์ด ๊ฐ์ ๋๊ธฐํ ํ์.
ํด๊ฒฐ: Mutex Lock ์ฌ์ฉ โ ์ฐ๊ฒฐ ๋จ์ ๋๊ธฐํ ๋ณด์ฅ
// ๋ชจํฐ ์ ์ด ์ค๋ ๋๋ฅผ ์ด๊ธฐํ
for (int i = 0; i < MAX_MOTOR_TYPES; i++) {
motor_threads[i].motor_id = i;
motor_threads[i].is_active = 0;
pthread_mutex_init(&motor_threads[i].mutex, NULL);
pthread_cond_init(&motor_threads[i].cond, NULL);
pthread_create(&motor_threads[i].thread, NULL, motor_control_thread, &motor_threads[i]);
}1. main.c ํ๋ก๊ทธ๋จ์ ์์์ ์ด์ root process
ํ๋ก๊ทธ๋จ์ด ์์๋๋ฉด child process ๋ก
controller.c ์ handler.c๋ฅผ fork spawn์ ์คํํฉ๋๋ค.
2. handler.c
RC์นด๋ฅผ ์ง์ ์ ์ดํ๊ฑฐ๋ ์น ํต์ ๋ธ๋ฃจํฌ์ค ํต์ ๋ฑ๋ฑ RC์นด ์ ์ด๋ฅผ ์ํ connection ์ ํธ๋ค๋ง ํจ
connection์์ ๋ณด๋ด์ง ๋ฐ์ดํฐ๋ฅผ IPC๋ก ๋ณด๋ด๋ ํ์ดํ๋ผ์ธ ์ญํ ์ ํจ
3. controller.c
๋ฉ์ธ์ง ํ์ ๋ฐ์ดํฐ๋ฅผ polling ํ์ฌ device ์ฅ์น๋ฅผ ์ ์ดํ๋๋ก ์คํํจ
4. device_adaptor.c
connection์์ ๋ณด๋ธ ๋ฐ์ดํฐ๋ฅผ parsing ํ์ฌ ์ ํฉํ device worker thread ์ ๋์ํ๊ฒ ํ๋ค. device_adaptor ์ ์ ๊ณต๋ ๊ท์ ์ device ์คํ ๋ฉ์๋์ ๊ตฌ์กฐ์ฒด , ๋ฌธ์์ด ๊ตฌ์กฐ์ฒด ๋ณํ ๋ฉ์๋๋ฅผ ์ปค์คํ ํ๋ฉด ํด๋น device๋ฅผ ์คํํ ์ ์๋ค.
- ๋ฌธ์ : ์ ํํ๋ ๋ฐ์ดํฐ ํ์ ํ์
- ํด๊ฒฐ ๋ฐฉ์: JSON โ ๊ตฌ์กฐ์ฒด ๋ณํ์ ํตํด ๋ฐ์ดํฐ ํ์คํ ๋ฐ ์ ์ฐ์ฑ ํ๋ณด
- ๋ฌธ์ : FORK ๋น์ฉ ๋ฐ CONTEXT SWITCHING ๋ถ๋ด
- ํด๊ฒฐ ๋ฐฉ์: THREAD ๊ธฐ๋ฐ ์ ์ด ์ฑํ ๋ฐ THREAD POOL ํจํด ์ ์ฉ์ผ๋ก ์ค๋ ๋ ์์ฑ/์ข ๋ฃ ๋น์ฉ ์ต์ํ
- ๋ฌธ์ : ์ฌ๋ฌ ์ปค๋ฅ์ ์ด ๋์์ ์ ๊ทผ ์ ๊ฒฝ์ ์กฐ๊ฑด ๋ฐ์
- ํด๊ฒฐ ๋ฐฉ์: MUTEX LOCK ์ฌ์ฉ, ์ปค๋ฅ์ ๋จ์๋ก ๋๊ธฐํํ์ฌ ๋ฐ์ดํฐ ์ ํฉ์ฑ ๋ฐ ์ฐ๊ฒฐ ์์ ์ฑ ๋ณด์ฅ
- ๋ฌธ์ : HTTP ๋ฐฉ์์ ์ ๋ขฐ์ฑ๊ณผ ์์ ์ฑ์ด ๋์ง๋ง, ๋ฉ์์ง ๋จ์๊ฐ ๋ฌด๊ฒ๊ณ ๋๋ฆฌ๋ค๋ ๋จ์ ์กด์ฌ
- ํด๊ฒฐ ๋ฐฉ์: ์น ์์ผ ํ๋กํ ์ฝ ์ฑํ์ผ๋ก, ์ ๋ขฐ์ฑ ์๋ HTTP ์์ ๋น ๋ฅด๊ณ ์์ ํต์ ๊ฐ๋ฅ
์๋ก์ด ๋ชจํฐ ํ์ ์ ์ถ๊ฐํ๋ ค๋ฉด ๋ค์ ์์ ์ด ํ์ํฉ๋๋ค:
- ๋ช
๋ น ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํฉ๋๋ค.
- ๊ตฌ์กฐ์ฒด์๋ ๋ฐ๋์
idํ๋๋ฅผ ํฌํจํด์ผ ํฉ๋๋ค. - json ๋ฌธ์์ด์ ๊ตฌ์กฐ์ฒด๋ก ๋ณ๊ฒฝํ๋ ํจ์๋ฅผ ๊ตฌํํฉ๋๋ค.
- ๊ตฌ์กฐ์ฒด์๋ ๋ฐ๋์
- ๋ช ๋ น ์ฒ๋ฆฌ ํจ์๋ฅผ ๊ตฌํํฉ๋๋ค.
- ๋ชจํฐ ํธ๋ค๋ฌ๋ฅผ ํ๋ ์์ํฌ์ ๋ฑ๋กํฉ๋๋ค.
- ํ์ฅํ device ๊ด๋ จ ์ปค์คํ ํจ์๋ฅผ ์ ์ํ ํ์ผ์ ์์ฑํฉ๋๋ค (์ด๋ฒ ์์๋ survo.c ์ ์์ฑํ๋ค๊ณ ๊ฐ์ )
๋จผ์ , survo.c ์ ์๋ก์ด ๋ชจํฐ ํ์
์ ๋ช
๋ น ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํฉ๋๋ค.
๊ตฌ์กฐ์ฒด์๋ ๋ฐ๋์ id ํ๋๊ฐ ํฌํจ๋์ด์ผ ํ๋ฉฐ, ๋ชจํฐ์ ๋์์ ํ์ํ ๋ค๋ฅธ ํ๋๋ฅผ ์ถ๊ฐ๋ก ์ ์ํฉ๋๋ค.
typedef struct {
int id; // ๋ชจํฐ ๊ณ ์ ID (ํ์ ํ๋)
int angle; // ์๋ณด ๋ชจํฐ ํ์ ๊ฐ๋
int duration; // ๋์ ์ง์ ์๊ฐ (ms ๋จ์)
} ServoMotorCommand;json ๋ฌธ์์ด์ ๊ตฌ์กฐ์ฒด๋ก ๋ณ๊ฒฝํ๋ ํจ์๋ฅผ ์์ฑํฉ๋๋ค
- survo.c ์ ๋ฌธ์์ด์ ๊ตฌ์กฐ์ฒด๋ก ๋ณ๊ฒฝํ๋ ๋ฉ์๋๋ฅผ ์์ฑํฉ๋๋ค
- dc_motor.c ํ์ผ์ ๊ตฌ์กฐ์ฒด ๋ณ๊ฒฝ ํจ์ ์์๊ฐ ์์ฑ๋์ด ์์ต๋๋ค!
void* parse_servo_motor_message(const char* json_str) {
}- ์๋๋ ์์ ์ ๋๋ค.
- survo.c ์ ๋ช ๋ น ์ฒ๋ฆฌ ๋ฉ์๋๋ฅผ ์์ฑํฉ๋๋ค
void handle_servo_motor_command(void* command) {
ServoMotorCommand* servo_command = (ServoMotorCommand*)command;
printf("์๋ณด ๋ชจํฐ ์ ์ด - ID: %d, ๊ฐ๋: %d, ์ง์ ์๊ฐ: %dms\n",
servo_command->id,
servo_command->angle,
servo_command->duration);
}- device_adaptor.c ํ์ผ์ ํด๋น ํจ์์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์ถ๊ฐํฉ๋๋ค
#include "survo.c" // device_adaptor.c ํ์ผ์ ์ถ๊ฐ
void register_custom_device_handler() { // ๊ตฌํ๋์ด ์๋ ํจ์์ ๋ค์ ์ฝ๋๋ฅผ ์ถ๊ฐ
MotorHandler servo_motor_handler = {
.handle_command = handle_servo_motor_command,
.parse_message = parse_servo_motor_message,
};
register_motor_handler(1, servo_motor_handler); // ๋ชจํฐ ID 1์ ํธ๋ค๋ฌ ๋ฑ๋ก
} gcc -o controller controller.c -lpthread -lwiringPi -ljanssongcc -o controller controller.c -lpthread -lwiringPi -ljansson
gcc -o handler handler.c -lpthread -lwiringPi -ljansson -lwebsockets
sudo ./main| Profile | Role |
|---|---|
|
๊ฐ๋ฏผ๊ธฐ |
์ ์ฒด์ ์ธ ํ๋ก์ ํธ ๊ตฌ์ฑ ์ค๊ณ, ์ ์ด ์ํํธ์จ์ด์ ๋ชจํฐ ์ฌ์ด์ ํ์ดํ๋ผ์ธ ๊ฐ๋ฐ, ๋์์ฑ ์ฒ๋ฆฌ ๊ตฌํ |
|
ํฉ์ฉ์ง |
์น๊ณผ ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด ๊ฐ ์น์์ผ ํต์ ์ ์ํ ์น ํ๋ซํผ ๊ฐ๋ฐ, RC์นด dc๋ชจํฐ ์กฐ๋ฆฝ, RC์นด์ ํธ๋ค๋ฌ๊ฐ ๋ฐ์ดํฐ ํต์ ํ ์คํธ ์งํ |
|
๊ฐ์ธ์ |
๋ผ์ฆ๋ฒ ๋ฆฌํ์ด5์ ์ค๋งํธํฐ ๊ฐ ๋ธ๋ฃจํฌ์ค ํต์ ์ ์ํ ๋ชจ๋ฐ์ผ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ, ๋ถ๊ฐ ๊ธฐ๋ฅ ํ์ฅ |
|
์ ๋ณด๊ฒฝ |
RC์นด ์ ์ฒด ์กฐ๋ฆฝ ๋ฐ device ๋จ์ ์กฐ์ ์ํํธ์จ์ด ๊ฐ๋ฐ, ๋ถ๊ฐ ๊ธฐ๋ฅ ํ์ฅ, RC์นด์ ํธ๋ค๋ฌ๊ฐ ๋ฐ์ดํฐ ํต์ ํ ์คํธ ์งํ |


