2) 스위치 입력 모듈 제작 (c 언어- gcc)
이번 페이지에는 c 언어와 wiringpi를 이용하여 스위치의 입력을 받는 module에 대하여 쓰고자 한다. 이전 글에서 밝힌 바와 같이 약간의 트릭이 필요한데 이 글의 끝 즈음에 나올 것이다.
(기본적으로 wiringPi를 이용한 개발은 다른 블로거의 페이지 등에 많이 나와 있고 또한 가능하다면 원 제작자의 페이지(여기)를 통하여 정보를 얻는 것이 더욱 확실할 것이라 생각 한다.)
이번 페이지에는 c 언어와 wiringpi를 이용하여 스위치의 입력을 받는 module에 대하여 쓰고자 한다. 이전 글에서 밝힌 바와 같이 약간의 트릭이 필요한데 이 글의 끝 즈음에 나올 것이다.
(기본적으로 wiringPi를 이용한 개발은 다른 블로거의 페이지 등에 많이 나와 있고 또한 가능하다면 원 제작자의 페이지(여기)를 통하여 정보를 얻는 것이 더욱 확실할 것이라 생각 한다.)
제일 먼저 해야 할 일은 버튼(혹은 스위치-버튼으로 통일 하겠다. 동작이 그러하니)과 Raspberry Pi의 GPIO간의 Bin bind가 계획 되어야 할 것 같다 하여 나는 다음과 같이 Bind 하였다.
|
|
다소 복잡해 보이는데 GPIO를 지원하는 H/W와 Library가 서로 Pin define이 틀려서 이런 작업을 해 놓지 않으면 오히려 내가 해깔려 버리는 상황이 오기때문에 이렇게
미리 정해 놔야 혼란이 없다.
자그럼 본격적으로 Code를 살펴보자.
#include #include #include #include // Button's WiringPi ID #define BTN1 8 #define BTN2 9 #define BTN3 7 #define BTN4 0 #define BTN5 2 #define BTN6 3 #define BTN7 12 #define BTN8 13 // constants #define SwitchCount 8 #define PREVENT_REACT_TICK 250 // global variables int Buttons[ButtonCount] = {BTN1,BTN2,BTN3,BTN4,BTN5,BTN6,BTN7,BTN8}; int ButtonStatus[ButtonCount] = {1,}; // pull-up 저항을 사용 하므로 1인 상태가 버튼이 눌러지지 않은상태 임. // Function front declear void init(void); void initDevice(void); unsigned long GetTickCount(void);
///////////////////////////////////////////////////////////////////////////
// main 함수
///////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[]){ int nLoop = 0; if(init()) return 1;
while(1){
unsigned long curTick = GetTickCount();
for(nLoop = 0; nLoop < ButtonCount; nLoop++){
int CurButtonStauts = digitalRead(Buttons[nLoop]);
// Button click 검출
if(0 == ButtonStatus[nLoop] && 1 == CurButtonStauts && (0 == ulTick || (curTick-ulTick>PREVENT_REACT_TICK))){
printf("%d Button clicked\n", nLoop);
}// if
ButtonStatus[nLoop] = CurButtonStauts;
}// for
sleep(50); // Process가 CPU를 너무 만힝 잡아 먹지 않도록 적당히 동작해라.
}// while
return 0;
}
///////////////////////////////////////////////////////////////////////////
// wiringPi를 setup
///////////////////////////////////////////////////////////////////////////
{ if(wiringPiSetup() == -1){ printf("unable to setupwiringPi:%s\n", strerror(errno)); return 1; } initDevice(); return 0; }
///////////////////////////////////////////////////////////////////////////
// 버튼에 할당된 GPIO들을 INPUT을 설정
///////////////////////////////////////////////////////////////////////////
void initDevice(void)
{
int nLoop =0;
for(nLoop = 0; nLoop < ButtonCount; nLoop++)
pinMode(Buttons[nLoop], INPUT);
}
///////////////////////////////////////////////////////////////////////////
// Linux에서 Win32의 getTickCount와 유사한 동작을 하도록 함.
// ※ 서핑을 통해 찾은 코드 조각
///////////////////////////////////////////////////////////////////////////
unsigned long GetTickCount(void)
{
struct timeval gettick;
unsigned long tick;
int ret;
gettimeofday(&gettick, NULL);
tick = gettick.tv_sec*1000 + gettick.tv_usec/1000;
return tick;
}
|
시그널은 down edge /up edge 모두 들어오고 우리가 필요한 데이터는 버튼을 눌렀다 띄었을때의 데이터 이므로 down edge와 up edge의 모든 데이터가 필요하다.
사람의 손이라는 것이 매우 투박하고 느리지만 PC(Raspberry Pi)의 신호 접수 속도는 사람 손의 속도에 비하면 번개와 같다. 또한 물리적인 운동이 회로상에서 발생되는 신호와 1:1로 매칭 되지 않는다. (실제 동작을 해보면 생각보다 많은 신호를 확인 할 수 있다.)
※ 정말로 더 명확하게 동작 하는 push button을 확인하고 싶으면 다음과 같은 로직이 적용되어야 할 것으로 보인다.
- 아주 짧은 interval로 값을 확인 해당 값의 변화 추이에 따른 상태값의 변화
ex) down 상태가 일정 시간 이상 되어야하거나 up 상태가 일정 시간 이상일 때문 입력으로 인식 하도록
본인이 사용한 방법은 단지 입력값이 무엇이 었든 회로로부터 한번에 한가지 신호만 들어 온다고 가정 하였기 때문에(회로도 그렇게 구성 했겠다.) 입력 변화의 인터벌 자체를 제한 하는 방법을 사용 한 것이다.
3) 5V 8ch Relay 연동 및 control (c언어 -gcc)
본인이 사용한 relay이다.
생긴건 투박해도 동작 하는 모습을 보면 왠지 모르게 귀엽게 느껴지기도 한다.
Pin assign은 사진에서 보는 중앙 부분을 볼때 왼쪽부터 GND/1/2/3/4/5/6/7/8/VCC으로 되어 있다.
인가 전압을 5V로 control은 Raspberry Pi에서 직접 넣었다. 라즈베리가 3.3V 동작인것을 감안하면 잘 안될것 같았는데 잘 되더라. 그리고 서핑한 결과 해외에서 사용해본 유저들의 리뷰를 보아서는 9개월 이상 이상없이 사용 중이다라는 리뷰가 있는 것을 보아서 크게 문제될 것은 없어 보인다. (상전 220v를 컨트롤 하는데 문제가 상기면 어쩌지 하는 걱정은 사실 지금도 있다.)
자 그럼 이놈을 어떻게 해볼까.
우선 계획은 순차적으로 켜지고 순차적으로 켜지고 다 키고 다 끄고 이정도의 동작이면 충분 할 것으로 생각 했다.
그럼 코드 조각을 살펴보자.
코드가 다소 난잡해 보인다.
하지만 끌때 0 켤때 1을 해당 GPIO에 write 해주기만 하면 된다.
결국 핵심은
이번 글은 여기까지 하도록 하겠습니다.
사람의 손이라는 것이 매우 투박하고 느리지만 PC(Raspberry Pi)의 신호 접수 속도는 사람 손의 속도에 비하면 번개와 같다. 또한 물리적인 운동이 회로상에서 발생되는 신호와 1:1로 매칭 되지 않는다. (실제 동작을 해보면 생각보다 많은 신호를 확인 할 수 있다.)
※ 정말로 더 명확하게 동작 하는 push button을 확인하고 싶으면 다음과 같은 로직이 적용되어야 할 것으로 보인다.
- 아주 짧은 interval로 값을 확인 해당 값의 변화 추이에 따른 상태값의 변화
ex) down 상태가 일정 시간 이상 되어야하거나 up 상태가 일정 시간 이상일 때문 입력으로 인식 하도록
본인이 사용한 방법은 단지 입력값이 무엇이 었든 회로로부터 한번에 한가지 신호만 들어 온다고 가정 하였기 때문에(회로도 그렇게 구성 했겠다.) 입력 변화의 인터벌 자체를 제한 하는 방법을 사용 한 것이다.
if(0 == ButtonStatus[nLoop] && 1 == CurButtonStauts && (0 == ulTick || (curTick-ulTick>PREVENT_REACT_TICK))){
이전 버튼의 상태가 0(pull-up 저항을 사용 했으므로 누른 상태)이고 현재 상태가 1(손을 땐 상태)이며 입력 변화가 0.25초이상의 간격이 존재할 경우 클릭으로 인식하라는 코드입니다.
3) 5V 8ch Relay 연동 및 control (c언어 -gcc)
본인이 사용한 relay이다.
생긴건 투박해도 동작 하는 모습을 보면 왠지 모르게 귀엽게 느껴지기도 한다.
Pin assign은 사진에서 보는 중앙 부분을 볼때 왼쪽부터 GND/1/2/3/4/5/6/7/8/VCC으로 되어 있다.
인가 전압을 5V로 control은 Raspberry Pi에서 직접 넣었다. 라즈베리가 3.3V 동작인것을 감안하면 잘 안될것 같았는데 잘 되더라. 그리고 서핑한 결과 해외에서 사용해본 유저들의 리뷰를 보아서는 9개월 이상 이상없이 사용 중이다라는 리뷰가 있는 것을 보아서 크게 문제될 것은 없어 보인다. (상전 220v를 컨트롤 하는데 문제가 상기면 어쩌지 하는 걱정은 사실 지금도 있다.)
자 그럼 이놈을 어떻게 해볼까.
우선 계획은 순차적으로 켜지고 순차적으로 켜지고 다 키고 다 끄고 이정도의 동작이면 충분 할 것으로 생각 했다.
그럼 코드 조각을 살펴보자.
#include #include #include #include
// reley's wiringPI ID
#define SW1 15
#define SW2 16
#define SW3 1
#define SW4 4
#define SW5 5
#define SW6 6
#define SW7 10
#define SW8 11
// constants
#define SwitchCount 8
// global variables
int Switchs[SwitchCount] = {SW1,SW2,SW3,SW4,SW5,SW6,SW7, SW8};
int SwitchStatus[SwitchCount]={0,};
// front function declare
void initDevice(void);
void SwitchON(int nIDX);
void SwitchOFF(int nIDX);
void SwitchToggle(int nIDX);
void TurnOffAllSwitch(void);
void TurnOnAllSwitch(void);
///////////////////////////////////////////////////// // main function /////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
int nLoop =0;
if(init())
return 1;
// 순서대로 켜기
for( nLoop = 0; nLoop
SwitchON(nLoop);
sleep(1000);
}
// 순서대로 끄기
for( nLoop = 0; nLoop
SwitchOFF(nLoop);
sleep(1000);
}
// 모두 켜기
TurnOnAllSwitch();
sleep(1000);
// 모두 끄기
TurnOffAllSwitch();
sleep(1000);
// 니 맘대로 한번 해봐라.(20번)
for( nLoop = 0; nLoop < SwitchCount; nLoop++){
int nIdx = (int)(rand()%SwitchCount);
SwitchToggle(inIdx);
sleep(1000):
}
return 0;
}
///////////////////////////////////////////////////// // wiringPI setup ///////////////////////////////////////////////////// int init(void) { printf("Start Init Device\n"); if(wiringPiSetup() == -1){ printf("unable to setupwiringPi:%s\n", strerror(errno)); return 1; } initDevice(); printf("End Init Device\n"); return 0; } ///////////////////////////////////////////////////// // Relay를 control 할 GPIO를 OUTPUT으로 설정 ///////////////////////////////////////////////////// void initDevice(void) { for(nLoop = 0; nLoop < SwitchCount; nLoop++){ pinMode(Switchs[nLoop], OUTPUT); // 일단 모두 꺼라(만약 켜 있던놈이 있을지도 모르니 SwitchOFF(nLoop); } } ///////////////////////////////////////////////////// // 켜기 ///////////////////////////////////////////////////// void SwitchON(int nIDX) { digitalWrite(Switchs[nIDX], 0); // ON SwitchStatus[nIDX]=1; printf("Turn On Switch %d\n", nIDX); } ///////////////////////////////////////////////////// // 끄기 ///////////////////////////////////////////////////// void SwitchOFF(int nIDX) { digitalWrite(Switchs[nIDX], 1); // OFF SwitchStatus[nIDX]=0; printf("Turn OFF Switch %d\n", nIDX); } ///////////////////////////////////////////////////// // 토글링 ///////////////////////////////////////////////////// void SwitchToggle(int nIDX) { if(SwitchStatus[nIDX]==0) SwitchON(nIDX); else SwitchOFF(nIDX); printf("Toggle Switch %d\n", nIDX); } ///////////////////////////////////////////////////// // 모두 끄기 ///////////////////////////////////////////////////// void TurnOffAllSwitch(void) { int nLoop=0; log_message(szLogPath,"Turn Off All Switch\n"); for(nLoop = 0; nLoop < SwitchCount; nLoop++){ SwitchOFF(nLoop); } } ///////////////////////////////////////////////////// // 모두 켜기 ///////////////////////////////////////////////////// void TurnOnAllSwitch(void) { int nLoop=0; log_message(szLogPath,"Turn Off All Switch\n"); for(nLoop = 0; nLoop < SwitchCount; nLoop++){ SwitchON(nLoop); } } |
코드가 다소 난잡해 보인다.
하지만 끌때 0 켤때 1을 해당 GPIO에 write 해주기만 하면 된다.
결국 핵심은
/////////////////////////////////////////////////////
// 켜기
/////////////////////////////////////////////////////
void SwitchON(int nIDX)
{
digitalWrite(Switchs[nIDX], 0); // ON
SwitchStatus[nIDX]=1;
printf("Turn On Switch %d\n", nIDX);
}
/////////////////////////////////////////////////////
// 끄기
/////////////////////////////////////////////////////
void SwitchOFF(int nIDX)
{
digitalWrite(Switchs[nIDX], 1); // OFF
SwitchStatus[nIDX]=0;
printf("Turn OFF Switch %d\n", nIDX);
}
해당 GPIO에 끌때는 0 킬때는 1을 써준다.이번 글은 여기까지 하도록 하겠습니다.
댓글 없음:
댓글 쓰기