또 한다. 한 것 또 하고 또 하고...
WiringPi GPIO 라이브러리는 라즈베리파이5에서도 잘 작동한다. 위대한 작품은 아주 꿋꿋하게 살아남는다.
1. 가장 유명한 GPIO 제어 라이브러리인 WiringPi 를 설치한다. Debian Package 로 설치한다. 가장 쉽다.
# fetch the source
$sudo apt install git
$git clone https://github.com/WiringPi/WiringPi.git
$cd WiringPi
# build the package
$./build debian
$mv debian-template/wiringpi_3.6_arm64.deb .
# install it
$sudo apt install ./wiringpi_3.6_arm64.deb
위 과정을 따라하면 아래와 같은 화면으로 된다. 참고삼아 본다.
pi@raspberrypi:~ $ sudo apt install git
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
git is already the newest version (1:2.39.2-1.1).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
pi@raspberrypi:~ $ git clone https://github.com/WiringPi/WiringPi.git
Cloning into 'WiringPi'...
remote: Enumerating objects: 2374, done.
remote: Counting objects: 100% (1251/1251), done.
remote: Compressing objects: 100% (367/367), done.
remote: Total 2374 (delta 952), reused 1082 (delta 856), pack-reused 1123
Receiving objects: 100% (2374/2374), 1010.53 KiB | 10.31 MiB/s, done.
Resolving deltas: 100% (1583/1583), done.
pi@raspberrypi:~ $ cd WiringPi
pi@raspberrypi:~/WiringPi $ ./build debian
version:3.6 architecture:arm64
[Compile] wiringPi.c
[Compile] wiringSerial.c
[Compile] wiringShift.c
[Compile] piHiPri.c
[Compile] piThread.c
[Compile] wiringPiSPI.c
[Compile] wiringPiI2C.c
[Compile] softPwm.c
[Compile] softTone.c
[Compile] mcp23008.c
[Compile] mcp23016.c
[Compile] mcp23017.c
[Compile] mcp23s08.c
[Compile] mcp23s17.c
[Compile] sr595.c
[Compile] pcf8574.c
[Compile] pcf8591.c
[Compile] mcp3002.c
[Compile] mcp3004.c
[Compile] mcp4802.c
[Compile] mcp3422.c
[Compile] max31855.c
[Compile] max5322.c
[Compile] ads1115.c
[Compile] sn3218.c
[Compile] bmp180.c
[Compile] htu21d.c
[Compile] ds18b20.c
[Compile] rht03.c
[Compile] drcSerial.c
[Compile] drcNet.c
[Compile] pseudoPins.c
[Compile] wpiExtensions.c
[Compile] wiringPiLegacy.c
[Link (Dynamic)]
[Install Headers: deb]
[Install Dynamic Lib: deb]
install -m 0755 -d /home/pi /WiringPi/debian-template/wiringPi/usr/lib
install -m 0755 libwiringPi.so.3.6 /home/pi/WiringP i/debian-template/wiringPi/usr/lib/libwiringPi.so.3.6
ln -sf /home/pi/WiringPi/debian-template/wiringPi/usr/lib/libwiringPi.so.3.6 / home/pi/WiringPi/debian-template/wiringPi/usr/lib/libwiringPi.so
[Compile] ds1302.c
[Compile] maxdetect.c
[Compile] piNes.c
[Compile] gertboard.c
[Compile] piFace.c
[Compile] lcd128x64.c
[Compile] lcd.c
[Compile] scrollPhat.c
[Compile] piGlow.c
[Link (Dynamic)]
[Install Headers: deb]
[Install Dynamic Lib: deb]
install -m 0755 -d /home/pi /WiringPi/debian-template/wiringPi/usr/lib
install -m 0755 libwiringPiDev.so.3.6 /home/pi/WiringP i/debian-template/wiringPi/usr/lib/libwiringPiDev.so.3.6
ln -sf /home/pi/WiringPi/debian-template/wiringPi/usr/lib/libwiringPiDev.so.3.6/ home/pi/WiringPi/debian-template/wiringPi/usr/lib/libwiringPiDev.so
[Compile] gpio.c
[Compile] readall.c
[Link]
[Install: deb]
dpkg-deb: building package 'wiringpi' in 'wiringPi.deb'.
dpkg-name: info: moved 'wiringPi.deb' to './wiringpi_3.6_arm64.deb'
pi@raspberrypi:~/WiringPi $ mv debian-template/wiringpi-3.0-1.deb .
pi@raspberrypi:~/WiringPi $ mv debian-template/wiringpi_3.6_arm64.deb .
pi@raspberrypi:~/WiringPi $ sudo apt install ./wiringpi_3.6_arm64.deb
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Note, selecting 'wiringpi' instead of './wiringpi_3.6_arm64.deb'
The following NEW packages will be installed:
wiringpi
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/65.2 kB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 /home/pi/WiringPi/wiringpi_3.6_arm64.deb wiringpi arm64 3.6 [65.2 kB]
Selecting previously unselected package wiringpi.
(Reading database ... 228617 files and directories currently installed.)
Preparing to unpack .../wiringpi_3.6_arm64.deb ...
Unpacking wiringpi (3.6) ...
Setting up wiringpi (3.6) ...
Processing triggers for man-db (2.11.2-2) ...
N: Download is performed unsandboxed as root as file '/home/pi/WiringPi/wiringpi _3.6_arm64.deb' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Perm ission denied)
pi@raspberrypi:~/WiringPi $
다 설치하였다면 아래 명령어로 확인한다.
$gpio readall
아주 아름다운 화면을 볼 수 있다.
pi@raspberrypi:~/WiringPi $ gpio readall
+-----+-----+---------+------+---+---Pi 5---+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| | | 3.3v | | | 1 || 2 | | | 5v | | |
| 2 | 8 | SDA.1 | ALT3 | 1 | 3 || 4 | | | 5v | | |
| 3 | 9 | SCL.1 | ALT3 | 1 | 5 || 6 | | | 0v | | |
| 4 | 7 | GPIO. 7 | - | 0 | 7 || 8 | 0 | - | TxD | 15 | 14 |
| | | 0v | | | 9 || 10 | 0 | - | RxD | 16 | 15 |
| 17 | 0 | GPIO. 0 | - | 0 | 11 || 12 | 0 | - | GPIO. 1 | 1 | 18 |
| 27 | 2 | GPIO. 2 | - | 0 | 13 || 14 | | | 0v | | |
| 22 | 3 | GPIO. 3 | - | 0 | 15 || 16 | 0 | - | GPIO. 4 | 4 | 23 |
| | | 3.3v | | | 17 || 18 | 0 | - | GPIO. 5 | 5 | 24 |
| 10 | 12 | MOSI | ALT0 | 0 | 19 || 20 | | | 0v | | |
| 9 | 13 | MISO | ALT0 | 0 | 21 || 22 | 0 | - | GPIO. 6 | 6 | 25 |
| 11 | 14 | SCLK | ALT0 | 0 | 23 || 24 | 1 | OUT | CE0 | 10 | 8 |
| | | 0v | | | 25 || 26 | 1 | OUT | CE1 | 11 | 7 |
| 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 |
| 5 | 21 | GPIO.21 | - | 0 | 29 || 30 | | | 0v | | |
| 6 | 22 | GPIO.22 | - | 0 | 31 || 32 | 0 | - | GPIO.26 | 26 | 12 |
| 13 | 23 | GPIO.23 | - | 0 | 33 || 34 | | | 0v | | |
| 19 | 24 | GPIO.24 | - | 0 | 35 || 36 | 0 | - | GPIO.27 | 27 | 16 |
| 26 | 25 | GPIO.25 | - | 0 | 37 || 38 | 0 | - | GPIO.28 | 28 | 20 |
| | | 0v | | | 39 || 40 | 0 | - | GPIO.29 | 29 | 21 |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+---Pi 5---+---+------+---------+-----+-----+
pi@raspberrypi:~/WiringPi $ gpio -V
2
온 습도 센서 연결은 아래와 같다.

코드는 아래와 같다.
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MAXTIMINGS 83
#define DHTPIN 7
int dht11_dat[5] = {0, } ;
void read_dht11_dat()
{
uint8_t laststate = HIGH ;
uint8_t counter = 0 ;
uint8_t j = 0, i ;
uint8_t flag = HIGH ;
uint8_t state = 0 ;
float f ;
dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0 ;
pinMode(DHTPIN, OUTPUT) ;
digitalWrite(DHTPIN, LOW) ;
delay(18) ;
digitalWrite(DHTPIN, HIGH) ;
delayMicroseconds(30) ;
pinMode(DHTPIN, INPUT) ;
for (i = 0; i < MAXTIMINGS; i++) {
counter = 0 ;
while ( digitalRead(DHTPIN) == laststate) {
counter++ ;
delayMicroseconds(1) ;
if (counter == 200) break ;
}
laststate = digitalRead(DHTPIN) ;
if (counter == 200) break ; // if while breaked by timer, break for
if ((i >= 4) && (i % 2 == 0)) {
dht11_dat[j / 8] <<= 1 ;
if (counter > 20) dht11_dat[j / 8] |= 1 ;
j++ ;
}
}
if ((j >= 40) && (dht11_dat[4] == ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xff))) {
printf("humidity = %d.%d %% Temperature = %d.%d *C \n", dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3]) ;
}
else printf("Data get failed\n") ;
}
int main(void)
{
printf("dht11 Raspberry pi\n") ;
if (wiringPiSetup() == -1) exit(1) ;
while (1) {
read_dht11_dat() ;
delay(1000) ;
}
return 0 ;
}
코드를 입력했다면
컴파일은 $gcc -o 출력 실행파일이름 소스이름 -lwiringPi 하면 된다. dash 마이너스 영어 o 다. 대문자 P에 주의
$gcc -o dht11_cprog dht11_cprog.c -lwiringPi
실행은 점 슬래시 실행파일 이름이다.
$./dht11_cprog
맨 아래 실행 화면이다. data get failed는 무시한다.
코드 상세한 설명을 아래에 적는다.
코드 설명
uint8_t laststate = HIGH ;
uint8_t counter = 0 ;
uint8_t j = 0, i ;
uint8_t flag = HIGH ;
uint8_t state = 0 ;
이번에는 조금 특이하게 변수가 uint8_t 라고 지정되었습니다.
평소에 쓰던 char, int등과는 차이점이 있습니다.
uint8_t는 unsigned 8 bit type 변수를 의미합니다.
char, int가 word의 크기에 따라 달라지는데 이를 방지하기 위하여 쓰는 형식입니다.
user-defined type이라고 부르며 stdint.h에 정의되어 있습니다.
pinMode(DHTPIN, OUTPUT) ;
digitalWrite(DHTPIN, LOW) ;
delay(18) ;
digitalWrite(DHTPIN, HIGH) ;
delayMicroseconds(30) ;
DHT11은 여타 센서와 다르게 신호의 길이로 데이터를 내보냅니다.
처음에 신호선으로 LOW를 18ms동안, 그리고 20 ~ 40us동안 HIGH신호를 주면 start 신호입니다.
여기서는 중간값인 30us를 사용하였습니다.
자 이제 DHT11에서 신호를 출력하기 시작할 것입니다.
pinMode(DHTPIN, INPUT) ;
라즈베리는 받아야 하는 입장이므로 pinMode를 이용하여 INPUT으로 변경해줍니다.
for (i = 0; i < MAXTIMINGS; i++) {
counter = 0 ;
while ( digitalRead(DHTPIN) == laststate) {
counter++ ;
delayMicroseconds(1) ;
if (counter == 200) break ;
}
laststate = digitalRead(DHTPIN) ;
if (counter == 200) break ;
if ((i >= 4) && (i % 2 == 0)) {
dht11_dat[j / 8] <<= 1 ;
if (counter > 20) dht11_dat[j / 8] |= 1 ;
j++ ;
}
}
이번 소스코드의 핵심입니다.
먼저 MAXTIMINGS만큼 for문을 반복하며 값을 읽어들입니다.
이때 MAXTIMINGS는 83의 값을 가지는데 이는
40개의 데이터 비트 * 2(LOW, HIGH가 반복되어야 데이터 1개를 읽을 수 있으므로)
+ 3개의 처음 비트 - Response signal, pullup ready signal, 처음 start to transmit bit 해서 3개입니다.
while ( digitalRead(DHTPIN) == laststate) {
이 부분에서 laststate와 반대가 되었을 경우(비트가 HIGH에서 LOW로 혹은 LOW에서 HIGH로 바뀌었을 경우를 인식합니다.
1us단위로 count를 증가시켜 반전되는데 시간이 얼마나 걸렸는지 짐작합니다.
다만 최대 시간을 100us로 지정하여 이 시간동안 바뀌지 않을 경우
에러로 인식하고 break와 뒤에 나오는 if문을 이용하여 에러를 검출합니다.
(i >= 4) && (i % 2 == 0)
위 코드는 처음 3비트를 버린상태로, 그리고 짝수번째 비트인지를 확인합니다.
홀수번째는 LOW상태의 start to transmit bit이므로 필요가 없기 때문입니다.
조건이 부합할 때 i 를 8로 나눈곳에 데이터를 씁니다.
앞에서 비트가 반전될 때 까지 count를 측정하였는데 이게 20이상이면 1이라고 값을 씁니다.
0은 이미 초기화가 되어있으므로 무시합니다.
그러면 왜 20이냐구요?
데이터시트에 보면 26 ~ 28us정도를 data 0으로 지정하고 있습니다.
다만 count연산과 if문연산 속도가 있기에 26정도를 바로 써주게되면 지연이 일어나서 이미 늦어버리게 됩니다.
그렇기에 20이라는 값을 기준으로 비교해주는 것입니다.
if ((j >= 40) && (dht11_dat[4] == ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xff))) {
printf("humidity = %d.%d %% Temperature = %d.%d *C \n", dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3]) ;
}
else printf("Data get failed\n") ;
값이 다 쓰였으면 0, 1, 2, 3번값을 더한 값과 마지막 4번값을 비교합니다.
마지막 4번째 8비트는 패리티 비트라고 부릅니다.
값이 잘 전송되었는지를 확인하기 위한 비트입니다.
이와 비교하여 잘 나왔다면 값 출력을, 아니라면 Data get failed라는 문장을 출력합니다.
main에서 1번씩 함수를 호출하여 실행하는 형태입니다.
코딩이 끝났으면 실행해 보도록 하겠습니다.
dht.c 라고 저장한 후 gcc를 이용하여 컴파일하고 실행합니다.
$gcc dht.c -o dht -lwiringPi
$sudo ./dht
동작 결과는 아래와 같다.
pi@raspberrypi:~/all_sensortest $ ./dht11_cprog
dht11 Raspberry pi
humidity = 60.0 % Temperature = 26.6 *C
Data get failed
humidity = 61.0 % Temperature = 26.2 *C
Data get failed
humidity = 62.0 % Temperature = 26.2 *C
Data get failed
humidity = 62.0 % Temperature = 26.2 *C
Data get failed
humidity = 62.0 % Temperature = 26.3 *C
Data get failed
^C
pi@raspberrypi:~/all_sensortest $
참고 문서
'라즈베리파이 5' 카테고리의 다른 글
| 라즈베리파이 Python 1 - python 실행 (1) | 2024.08.20 |
|---|---|
| 1970년대 크레이-1 슈퍼컴퓨터 대 2012 라즈베리 파이 (1) | 2024.08.12 |
| Raspberry Pi Pico2 빠르게 시작하기 (1) | 2024.08.11 |
| 라즈베리파이 피코2 Raspberry Pi Pico 2 (1) | 2024.08.09 |
| 파이썬 라즈베리파이 5 GPIO를 제어하는 방법 (1) | 2024.07.31 |
| 라즈베리파이 5와 함께 M.2 HAT+ 사용 (0) | 2024.07.31 |
| 라즈베리파이 오디오 시스템 제작 (1) | 2024.07.29 |
| 라즈베리파이 5-레이어 아크릴 케이스 홀더 박스 (1) | 2024.07.23 |
취업, 창업의 막막함, 외주 관리, 제품 부재!
당신의 고민은 무엇입니까? 현실과 동떨어진 교육, 실패만 반복하는 외주 계약,
아이디어는 있지만 구현할 기술이 없는 막막함.
우리는 알고 있습니다. 문제의 원인은 '명확한 학습, 실전 경험과 신뢰할 수 있는 기술력의 부재'에서 시작됩니다.
이제 고민을 멈추고, 캐어랩을 만나세요!
코딩(펌웨어), 전자부품과 디지털 회로설계, PCB 설계 제작, 고객(시장/수출) 발굴과 마케팅 전략으로 당신을 지원합니다.
제품 설계의 고수는 성공이 만든 게 아니라 실패가 만듭니다. 아이디어를 양산 가능한 제품으로!
귀사의 제품을 만드세요. 교육과 개발 실적으로 신뢰할 수 있는 파트너를 확보하세요.
캐어랩