티스토리 뷰

반응형

다른 강의자료는 www.codingnow.co.kr/ 여기를 참고해주세요.!!

 

코딩나우

프로그래밍 교육및 개발의뢰 받습니다.

www.codingnow.co.kr

https://youtu.be/ZrIzk8TAkVQ

 

 

 

 

지난 실무 강의는 아두이노 LED를 파이썬으로 제어하기 였습니다.

이번에는 조이스틱을 사용하여 간단한 마우스를 만들어 보겠습니다.

 

자세한 사항은 첨부된 동영상을 참고해주세요.

 

1.  C언어 - 아두이노

1) 회로구성

조이스틱 - A0, A1

버튼 - 2,3,4,5

 

조이스틱 모듈 구입처는 소스 코드내 주석으로 넣어 두었습니다.

 

마우스만들기 전체 소스코드.zip
0.01MB

2) 소스파일

소스 구조

-. Mouse.ino (아두이노 스케치 파일)

#include "src/global.h"

void setup() 
{
  setupMain();
}

void loop() 
{
  loopMain();
}

-.main.cpp

조이스틱 모듈의 키값을 read하여 분석 후 시리얼 통신으로 PC에 데이타를 전송합니다.

#include "global.h"

#define KEY_MAX 6
unsigned char keyMap[KEY_MAX] = {
A0, A1, /*6,*/ 3, 5, 2, 4
};

typedef struct{
  unsigned char key;
  unsigned char keyPre;
  unsigned char keyResult[KEY_MAX + 2];
}KeyValtype;
KeyValtype val;

void getKey()
{
    // int adc1, adc2, key1,key2, key3, key4;
    // adc1 = analogRead(keyMap[0]);
    // adc2 = analogRead(keyMap[1]);
    // Serial.print(adc1);
    // Serial.print(",");
    // Serial.print(adc2);

    // key1 = digitalRead(keyMap[2]);
    // key2 = digitalRead(keyMap[3]);
    // key3 = digitalRead(keyMap[4]);
    // key4 = digitalRead(keyMap[5]);
    // Serial.print(key1);
    // Serial.print(",");
    // Serial.print(key2);
    // Serial.print(",");
    // Serial.print(key3);
    // Serial.print(",");
    // Serial.println(key4);

    unsigned char i, count = 0;
    unsigned int adc;
    memset(val.keyResult, 0x00, sizeof(val.keyResult));
    for (i = 0; i < KEY_MAX; i++)
    {
        if (keyMap[i] >= A0)//아날로그  pin read
        {
            adc = analogRead(keyMap[i]);
            if (adc > 530)
            {
                val.keyResult[count] = 1; //left, up
            }else if(adc < 500)
            {
                val.keyResult[count + 1] = 1; //right, down
            }
            count++;
        }else{//digital pin read
            val.keyResult[count] = (~digitalRead(keyMap[i])) & 0x01;
        }
        count++;
    }
}

void keyProcess(void)
{
    unsigned char i,key = 0x00;
    for (i = 0; i < sizeof(val.keyResult); i++)
    {
        key |= (val.keyResult[i] << i);
    }
    val.key = key;
}

void sendMsg()
{
    char buf[64];
    // unsigned char i,cnt=0;
    // for(i=0; i<sizeof(val.keyResult);i++)
    // {
    //     sprintf(&buf[cnt], "%02X,", val.keyResult[i]);
    //     cnt += 3;
    // }
    // sprintf(buf, "%02X,%02X,%02X,%02X,%02X,%02X,%02X"
    //             , val.keyResult[0], val.keyResult[1]
    //             , val.keyResult[2], val.keyResult[3]
    //             , val.keyResult[4], val.keyResult[5], 
    //             val.keyResult[6]);

    if (val.key == val.keyPre)
        return;
    val.keyPre = val.key;
    sprintf(buf, "key=%02X", val.key);
    Serial.println(buf);
}

void setupMain() 
{
    unsigned char i;
    Serial.begin(9600);//시리얼 초기화
    memset(&val, 0x00, sizeof(val));//변수 초기화
    for (i = 0; i < KEY_MAX; i++) //포트 초기화
    {
        if(keyMap[i] >= A0)
        {
            pinMode(keyMap[i], INPUT);//Analog
        }else{
            pinMode(keyMap[i], INPUT_PULLUP);
        }
    }
}

void loopMain() 
{
    getKey();//key값을 read 한다.
    keyProcess();//key값을 원하는 형태로 변환한다.
    sendMsg();//시리얼 데이타를 전송한다.
}

2. 파이썬

1) 소스코드

.-  main.py

쓰레드 2개를 생성하고 

쓰레드1에서 시리얼 데이타를 받아 keybuffer에 저장

쓰레드2에서 keybuffer의 데이타에 따라 pyautogui를 사용하여 마우스를 제어 합니다.

import serial
import time
import threading
import pyautogui
import tkinter as tk
# pip install serial
# pip install pyserial
# pip uninstall serial
#https://www.devicemart.co.kr/goods/view?no=1279487

seri = serial.Serial(port='COM9',
                    baudrate=9600,
                    parity=serial.PARITY_NONE,
                    stopbits=serial.STOPBITS_ONE,
                    bytesize=serial.EIGHTBITS) 
###########################################
keybuffer = 0
def readSerial():
    global isT1Run
    global keybuffer
    while isT1Run:
        pass
        try:
            if seri.readable():
                res = seri.readline()
                res = res.decode()[:len(res)-1]
                print(res)
                if res.find('key') != -1:
                    res = res.replace("key=","")
                    key = int(res,16)
                    keybuffer = key
        except:
            pass
    print('stop thread1')

def mouseProcess():
    global isT2Run
    global keybuffer
    keybufferPre = 0
    key = 0
    moveOffset = 1
    while isT2Run:
        pass
        try:
            if keybuffer != keybufferPre:
                key = keybuffer
                keybufferPre = keybuffer
                print(key)
    #move
            x, y = 0, 0
            if key & 0x01:
                x -= moveOffset
            if key & 0x02:
                x += moveOffset
            if key & 0x04:
                y -= moveOffset
            if key & 0x08:
                y += moveOffset
            pyautogui.move(x,y)

            if x or y:
                if moveOffset < 100:
                    moveOffset *= 2
            else:
                moveOffset = 1
    #click   
            if key&0x10:
                pyautogui.leftClick()
            if key&0x20:
                pyautogui.rightClick()
            if key&0x40:
                pyautogui.scroll(200)
            if key&0x80:
                pyautogui.scroll(-200)
            key &= (~0x30);#0xCF#bnt은 한번만 동작하도록 삭제
        except:
            pass
        time.sleep(0.01)
    print('stop thread2')

###########################################
isT1Run = True
t1 = threading.Thread(target=readSerial)
t1.start()

isT2Run = True
t2 = threading.Thread(target=mouseProcess)
t2.start()
###########################################
win = tk.Tk()
win.title('[파이선] 아두이노 제어')
win.mainloop()
###########################################
#GUI 종료 후
seri.close()
isT1Run = False
isT2Run = False
time.sleep(0.5)
print('Finish')
반응형