또 한다. 한 것 또 하고 또 하고...
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 |
더욱 좋은 정보를 제공하겠습니다.~ ^^