본문 바로가기
RaspberryPi

[Raspberry Pi] Raspberry Pi 4B GPIO 제어

by TYB 2024. 2. 1.
반응형

라즈베리파이 쉘 스크립트로 LED 키고 끄기

 

gpio 18번에 led 하나만 연결해서 아래 명령을 치면서 잘 동작하는지 확인한다.

pi@pi08:~ $ echo "18" > /sys/class/gpio/export
#18번 핀을 gpio로 제어하겠다. 라는 듯 일반적인 쉘명령어는 gui에 출력되는 느낌인디 이건 gpio에다 쓰겠다.
pi@pi08:~ $ ls /sys/class/gpio/
export  gpio18  gpiochip0  gpiochip504  unexport
pi@pi08:~ $ echo "out" > /sys/class/gpio/gpio18/direction
pi@pi08:~ $ cat /sys/class/gpio/gpio18/direction
out
pi@pi08:~ $ echo "1" > /sys/class/gpio/gpio18/value
#불켜지고
pi@pi08:~ $ echo "0" > /sys/class/gpio/gpio18/value
#불꺼지고
pi@pi08:~ $ echo "18" > /sys/class/gpio/unexport

 

export는 재부팅 시 없어지므로 다시 쳐주면 됨. 그러나 부팅되어 있는 동안은 잘 돌아감.

                                       

 

https://www.newtc.co.kr/en/dpshop/shop/item.php?it_id=1306915131

 

뉴티씨

Introduction to AM-TL8 (LED output module) - 8EA LED outputmodule - Can checkoutput of the port by LED. LED will be ON when corresponding port output is 1 and OFF when port output is 0. - When using MCU such as AVR,corresponding port should be set to outpu

www.newtc.co.kr

 

 

사진 기준 왼쪽 상단핀이 0 우측하단핀이 9번 핀임. 그래서 0~7번핀까지가 LED1~LED8까지 매핑되고 8번핀이 VCC 9번핀이 GND HW연결은 라즈베리파이 GPIO 6~13까지 LED를 연결해주고 GND만 GND에 꽂아준다. GPIO를 통해 LED를 켜줄것이기 때문에 VCC는 꼽지않는다.

 

HW 다 꽂고 아래의 쉘 스크립트를 실행시킨다.

쉘 스크립트 이름은 for_led.sh 일 때, 명령어는 sudo ./for_led.sh

#!/bin/bash

for ((i=6 ; i<14 ; i++))
do
	echo "$i" > /sys/class/gpio/export 
	echo "out" > /sys/class/gpio/gpio${i}/direction 
	echo "1" > /sys/class/gpio/gpio${i}/value 
	echo -n "gpio$i : "
	cat /sys/class/gpio/gpio${i}/value 
	sleep 1
	echo -n "gpio$i : "
	echo "0" > /sys/class/gpio/gpio${i}/value 
	cat /sys/class/gpio/gpio${i}/value
	sleep 1
	echo "$i" > /sys/class/gpio/unexport 
done

 

1부터 8까지 잘 LED가 켜졌다 꺼지는걸 확인이 됬으면

 

아래의 버튼을 연결하겠음.

좌측 하단이 D0 좌측 상단이 D1 순으로 오른쪽까지 쭉~있음.

D0~D7까지를 라즈베리파이 GPIO 16~23까지 연결해주고 VCC에 3.3V , GND에 GND 연결

 

원래대로라면 풀업 혹은 풀다운 저항을 추가해줘야함. 하지만 모듈 뒤에 보면 SMB형식의 조그만한 저항이 다 풀다운 형식으로 연결되어 있음. 따라서 연결 안해도 됨~b

 

Active High로 작동함.

아래의 스크립트 파일 이름은 forledkey.sh이고 윗 for문은 led 확인용 아랫 for문은 key확인용

실행을 위해서 sudo ./forledkey.sh 를 쳐주면 됨.

pi@pi08:~/gpio.d $ cat for_ledkey.sh
#!/bin/bash

for ((i=6 ; i<14 ; i++))
do
        echo "$i" > /sys/class/gpio/export
        echo "out" > /sys/class/gpio/gpio${i}/direction
        echo "1" > /sys/class/gpio/gpio${i}/value
        echo -n "gpio$i : "
        cat /sys/class/gpio/gpio${i}/value
        sleep 1
        echo -n "gpio$i : "
        echo "0" > /sys/class/gpio/gpio${i}/value
        cat /sys/class/gpio/gpio${i}/value
        sleep 1
        echo "$i" > /sys/class/gpio/unexport
done
for ((i=16 ; i<24 ; i++))
do
        echo "$i" > /sys/class/gpio/export
        echo "in" > /sys/class/gpio/gpio${i}/direction
        echo -n "gpio$i : "
        cat /sys/class/gpio/gpio${i}/value
        sleep 1
        echo -n "gpio$i : "
        cat /sys/class/gpio/gpio${i}/value
        sleep 1
        echo "$i" > /sys/class/gpio/unexport
done

 

버튼을 누르고 있으면 해당 핀 출력이 1로 나올 것이고 안누르고 있으면 0으로 나올 것임.

 

아래의 c코드를 작성해주고

pi@pi08:~/gpio.d $ cat gpioled.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>


int ledControl(int gpio)
{
        int fd;
        char buf[BUFSIZ];//BUFSIZ=8192Byte

        fd = open("/sys/class/gpio/export",O_WRONLY);//이런게 저수준 입출력 함수
        sprintf(buf, "%d" , gpio);
        write(fd, buf, strlen(buf));
        close(fd);

        sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio);
        fd = open(buf, O_WRONLY);
        write(fd, "out", 4);
        close(fd);

        sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);
        fd = open(buf, O_WRONLY);
        write(fd, "1", 2);
        close(fd);
        sleep(1);

        sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);
        fd = open(buf, O_WRONLY);
        write(fd, "0", 2);
        close(fd);
        getchar();


        fd = open("/sys/class/gpio/unexport", O_WRONLY);
        fd = open(buf, O_WRONLY);
        write(fd, "1", 2);
        close(fd);

        return 0;
}

int main(int argc, char **argv)
{
        int gno;
        if(argc < 2){
                printf("usage: %s GPIO_NO\n" , argv[0]);
                return -1;
        }
        gno = atoi(argv[1]);
        ledControl(gno);

        return 0;
}

 

int main(int argc, char **argv) 

main문에 argument를 전달하는 형식인데

int argc = 

char* argv[] = 

이렇게 주는 이유는 cp gpioled.c led.c 이렇게 명령어 argument를 넘기는건데 enter,space,tap 등 문자열 구분자를 통해 argument의 갯수를 구분함. 위와 같은 명령이 넘어갈 때

argc = 3 이 되고 argv는 cp, gpioled.c , led.c 각각의 첫 시작 주소가 저장되어 있는 곳을 가리키고 있는 포인터임.

 

sudo ./gpio 6 이 들어갈 때 sudo는 argc로 안침, 고로 argv[1]은 핀번호 6을 가리킴.

 

gcc gpioled.c -o gpio

명령어를 쳐서 컴파일 해주고

 

제대로 된 양식으로 명령어를 주지 않을 경우 -1로 return 하는데 컴퓨터엔 -값이 없으므로 255로 리턴됨.

pi@pi08:~/gpio.d $ ./gpio
usage: ./gpio GPIO_NO
pi@pi08:~/gpio.d $ echo $?
255

 

가독성이 떨어지므로 main 내부의 return 값은 양수로 주는게 좋음..!

 

pi@pi08:~/gpio.d $ cat gpiokey.c
#include <stdio.h>
#include <stdlib.h>     /* atoi( ) 함수 */
#include <string.h>
#include <fcntl.h>
#include <unistd.h>     /* close( ) 함수 */

int keyControl(int gpio)
{
    int fd;
    char value;
    char buf[BUFSIZ];

    fd = open("/sys/class/gpio/export", O_WRONLY);              /* 해당 GPIO 디바이스 사용 준비 */
    sprintf(buf, "%d", gpio);
    write(fd, buf, strlen(buf));
    close(fd);

    sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio);     /* 해당 GPIO 디바이스의 방향 설정 */
    fd = open(buf, O_WRONLY);
    /* LED를 위해 디바이스를 출력으로 설정 : 입력의 경우 write(fd, “in”, 3); 사용 */
    write(fd, "in", 2);
    close(fd);

    getchar( ); /* KEY 확인을 위한 대기 */

    sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);         /* 디바이스에 값 출력 */
    fd = open(buf, O_RDONLY);
    read(fd, &value, 1);
    if(value == '0') {
        printf("gpio%d key Off\n",gpio);
    } else {
        printf("gpio%d key On\n",gpio);
    }
    close(fd);


    fd = open("/sys/class/gpio/unexport", O_WRONLY);            /* 사용한 GPIO 디바이스 해제하기 */
    sprintf(buf, "%d", gpio);
    write(fd, buf, strlen(buf));
    close(fd);

    return 0;
}

int main(int argc, char **argv)
{
    int gno;

    if(argc < 2) {
        printf("Usage : %s GPIO_NO\n", argv[0]);
        return -1;
    }

    gno = atoi(argv[1]);
    keyControl(gno);

    return 0;
}

이건 컴파일 하고

pi@pi08:~/gpio.d $ gcc gpiokey.c -o gpiokey

실행 후 버튼 누른 상태로 enter키 누르면 button의 상태를 display해줌.

pi@pi08:~/gpio.d $ sudo ./gpiokey 20

gpio20 key On
pi@pi08:~/gpio.d $ sudo ./gpiokey 21

gpio21 key On

 

반응형