BH1750FVI센서(이하 조도센서)는 I2C통신을한다.
정식명칭은 I2C이며 윗첨자를 쓰는게 힘들어 I2C로 쓰는듯 하다.
이론부터 설명할것이며 이론은 위키 자료를 사용하며 작동만 되면 되는 사람들은 이론은 넘어가고 밑에 동작부분만 봐도 된다.
동작은 환경은 라즈베리파이4B, 라즈비안OS, python3.7, 조도센서이다.
아래는 참고한 위키 주소이다.
https://en.wikipedia.org/wiki/I%C2%B2C
I2C는 Master와 Slave간의 통신이며 통신을 할때 Slave주소가 7bit 입력이므로 총 127개의 Slave를 연결할 수 있다.
I2C는 클럭으로 싱크를 맞추기 위한 SCL, 실제 데이터를 주고 받는 SDA선이 있다.
위 사진은 위키에서 출처한 타이밍 다이어그램이다.
SDA와 SCL은 풀업저항으로 HIGH가 디폴트이다.
SCL이 HIGH이며 SDA가 LOW로 변환하는 순간 통신의 시작을 알리는 신호이다.
이후 SCL은 HIGH와 LOW를 반복하는 주기를 가져 통신에 싱크를 맞춰준다.
그림상 파란색박스 부분, SCL이 LOW일때는 SDA에서 HIGH 또는 LOW를 결정하며
"자, 이제 데이터 통신한다~ 준비해~?" 라고 생각하면 된다.
그리고 실제로 데이터 통신을 하는 부분이 초록색 박스부분이다.
SDA가 HIGH 또는 LOW냐를 통해 데이터를 쓰거나 읽는다.
데이터 통신이 끝났다면 SCL이 HIGH신호를 주고, SDA도 HIGH신호를 주게 되며 통신을 중지한다.
자, 여기까지가 I2C통신의 방법이었고 이젠 조도센서로 넘어가자.
내가 사용하는 조도센서 BH1750 FVI의 매뉴얼을 첨부한다.
예제를 먼저 보겠다.
매뉴얼 7페이지 ex1) 전문이다.
Continuously H-resolution mode (ADDR=L)의 예제이다.
Continuously H-resolution mode가 뭐고 ADDR이 뭐인지는 나중에보고 예제부터 동작해보겠다.
이전 설명했던 I2C통신을 하여 ①를 설명한다.
1. ST : Start
2. 0100011 : Slave address
3. 0 : write command (Master측에서 Slave로 데이터를 전송한다는 뜻)
4. Ack : 데이터 전송이 끝났다는 응답비트이다. 하얀색 박스는 from Slave to Master, 즉 슬레이브측(조도센서)에서 마스터(라즈베리 or 컨트롤러)데이터를 전송한다는 뜻이다.
5. 00010000 : 명령어부분 여기서는 "Continuously H-resolution mode"이며 이외 명령어는 매뉴얼 5페이지를 참조하자.
6. Ack : 다시 Slave측에서 응답메시지를 보낸다.
7. 통신을 종료한다.
②번은 ①명령어를 보낸뒤 조도센서의 측정을 기다린다는 뜻으로 최대 180ms이다.
③번, 측정이 끝났다면 조도센서의 데이터를 읽어야 한다.
1. ST비트, 2. Slave 주소비트는 ①과 동일하다.
그 이후는 다르다.
3. 1 : 이번에는 Master측에서 Slave에게 Write 하는 것이 아닌 데이터를 읽어오는 Read 명령어를 할 차례이다.
Read command는 1이다.
4. ①과 동일하게 응답비트이다.
5. ①에서는 Master측에서 명령어 command를 보냈다면, 여기서는 Slave측에서 Master측으로 Data를 보낸다.
6. 응답비트이다. 사진을 보면 알겠지만 5~6을 2번 반복한다. 단순히 읽을 데이터가 2byte이기 때문이며
매뉴얼상에서도 1~65535 lx, 즉 2byte를 읽는다.
7. 통신종료
① ~ ③까지가 컨트롤러측에서 조도센서한테 데이터를 읽어오는 방법이다.
이제 추가적인 설명이다.
위 예제에서 바뀌는 거는 ADDR과 write비트에서 Command 이다
먼저 ADDR.
ADDR이 L일 때, 또는 R일때 조건?같은거 인거 같은데... 뭔말인지 난 모르겠다.
라즈베리에서는 L을 인식하기 때문에 0x23 = 01000011(2)를 사용하겠다...
다음은 Command. Opecode가 정식명칭이다.
continuously는 지속적인 측정, One Time은 한번 측정후 Power Down을 한다고 한다.
H는 고성능인데 좀 느리고, L은 저성능이지만 빠르다고 설명한다.
그 외는 못알아보겠다... 각자 매뉴얼로 알아보자.
여기서부터는 실제로 조도센서를 동작시켜본다.
먼저 I2C 통신을 할 수 있는 핀을 찾아야한다. (라즈베리 기준으로 설명한다.)
터미널[Ctrl + Alt + T]을 실행한뒤 아래 명령어를 수행한다.
gpio readall
gpio readall을 실행하면 아래와 같은 핀맵이 뜰 것이다.
라즈베리는 I2C핀이 2개이다.
Physical 기준으로
0번 - SDA 27, SCL 28번핀
1번 - SDA 3, SCL 5번핀이다.
SDA.1과 SCL.1은 기본적으로 개방되어있으나
SDA.0과 SCL.0은 설정을 해줘야 열린다.
0번 포트 개방법은 아래 링크에 있다.
2021.06.29 - [분류 전체보기] - 라즈베리파이 i2c(SCL.0, SDA.0) 사용하기
다음은 I2C에 연결되어있는 Slave들을 알아보기 위해 아래 명령어를 수행한다.
i2cdetect -y 0
나는 0번에 연결했기 때문에 0번을 실행했으나
대부분 1번에 연결했을 것이다.
1번포트에 연결했다면 "i2cdetect -y 0"이 아닌 "i2cdetect -y 1"이다.
그러면 이론파트에서의 ADDR 01000011(2)인 0x23번이 보일 것이다.
보이지 않는다면 조도센서 연결오류일 확률이 높다.
먼저 smbus를 다운받는다.
sudo apt-get install python3-smbus
다음은 파이썬을 실행시켜 아래코드를 작성한 뒤 실행한다.
import smbus
i2c = smbus.SMBus(0)
def getLux():
luxBytes = i2c.read_i2c_block_data(0x23,0x10,2)
lux = int.from_bytes(luxBytes, byteorder='big')
return lux
if __name__ == '__main__':
print(getLux())
SMBus(0)에서 0은 I2C 포트번호이다. 당연히 1번 포트에 연결했으면 1을 입력하자.
i2c.read_i2c_block_data의 인자는 주소, 명령어, 길이이다.
Slave주소인 0x23, Continuously H-resolution mode 명령어인 0x10, 2byte를 읽기위해 길이는 2로 입력한다.
아래는 실행결과이다.
예제를 그대로 구현했기에 poweroff는 안되어있는걸 참고하자.
사실 동작만 하면 땡이었기에 매뉴얼까지 뒤져본적은 거의 없다.
I2C도 이번에 학습한 것이기 때문에 틀렸을 수도 있으니 지적을 해준다면 감사히 수정할 계획이다.
'프로그래밍 > Python' 카테고리의 다른 글
[Python] .csv 파일 데이터 읽어오기 (0) | 2022.03.27 |
---|---|
[Python] 라즈베리파이 LCD I2C 통신 (0) | 2022.01.07 |
[Python] 라즈베리4 Adafruit DHT11/21/22(온습도센서) (9) | 2021.11.08 |
[Python] Tensorflow Function call stack: train_function error 해결 (0) | 2021.09.03 |
[Python] Tensorflow Epoch 1/10 멈춤 에러 해결 (0) | 2021.09.01 |
댓글