[아두이노] [강좌] 34. SPI 통신 (3) - 기압 센서(MPL115A1) 실습하기
오늘 실습에 사용할 기압 센서는, 바로바로
스파크펀 사의 “MPL115A1” 센서이다.
SPI 통신을 사용하는 센서이고, 다른 기압 센서들은 어떤지 모르겠지만 얘는 계산 식이 엄청 복잡하다. 데이터 시트를 봐도 무슨 말인지 모르겠어;;;
그럼에도 불구하고 이 아이를 선택한 이유는, 예제 소스가 제공되기 때무느흐흐흐흐.
아두이노에 사용되는 센서들의 대부분은 자신들의 라이브러리를 제공하는 경우가 많기 때문에 구매 사이트의 정보 페이지를 잘 살펴보면 유용한 정보를 얻을 수 있는 경우가 많다. 데이터 시트 등도 마찬가지고, 회로도랑 PCB 레이아웃 파일까지 있음.
일단 연결부터. SPI 통신을 사용하니까 50~53번 핀을 사용하는 데, 우노(Uno) 보드를 사용하는 사람도 있을 테니 ICSP 포트를 이용해서 연결해보도록 하자.
선이 많네..
‘CSN’이라고 표시된 핀이 SS 핀, ‘SDO’는 ‘MISO’, ‘SDI’는 ‘MOSI’, ‘SCK’는 ‘SCK’에 연결하면 되고, VCC와 GDN도 각각 연결한다. ‘SDN’ 핀은 ‘Shut Down’ 기능의 핀으로 GND에 연결하면 칩을 Sleep 모드로 전환하여 동작하지 않도록 하는 기능을 가지는데, 사용하지 않으므로 연결하지 않아도 좋다. 만일 사용한다면 3.3V의 전압이 나오는 핀에 연결해야 하므로 유의.
혹시 VCC 핀을 보드의 POWER 부분에 직접 연결하는 사람은 5V가 아니라 3.3V에 연결해야 한다.
SS 핀은 일부러 다른 핀에 연결했다. 53번이나 10번에 연결해도 좋고, 원하는 핀 어디에 연결해도 좋다. 난 일단 가까운 7번에 연결함.
ICSP 포트의 핀 기능은 이전 강좌에 상세히 표시해 뒀으므로 참고.
그리고 소스를 짜면 되는데, 데이터 시트를 보니 계산 식과 이걸 구하려면 몇 번째 비트를 써야 되고, 뭐 이런 내용들이 있다.
그래숴! 우린 제조사에서 제공하는 예제 소스를 활용할 예정이다. 구매 사이트의 링크를 이용해서 “Example Code”를 다운로드 한다. 그리고 열어보자.
아두이노 소스가 아닌 건 쪼금 서운.. 하지만 참고하기에 충분한 소스이다.
“main.c” 파일을 열어보면 뭔가 많이 있지만, 우리가 참고할 내용은 calculatePressure() 함수 하나 뿐. 다음은 main.c 파일의 내용을 아두이노 소스로 변경한 것이다.
변환 식 계산 덕분에 조금 긴 소스가 됐..
너무 길어서 일단 접어두기.
훠우. 엄청 기네. 추가로 고도 구하는 공식도 넣었엉. (칭찬해줘)
일단 업로드 한 후 시리얼 모니터를 실행해보면, 현재 위치의 기압과 고도 값이 나오는 것을 알 수 있다.
아쉬운 점은 아두이노 보드를 들고 높은 곳으로 가본 적이 없어 차이를 느낄 수가 없다는..
소스는 엄청 길지만 유의해서 봐야할 부분은 writeData() 함수와 readData() 함수.
MPL115A1 칩은 SPI 통신을 사용하지만, 읽기와 쓰기의 동작 구분을 I2C 통신과 비슷하게 최상위 비트 하나로 하고 있다. 아, I2C 통신은 최하위 비트였구만. 아무튼 최상위 비트가 1이냐, 0이냐에 따라 해당 레지스터(저장 주소)에 쓸 것이냐, 읽어 올 것이냐를 구분한다.
writeData() 함수 먼저 보자.
void writeData(byte addr, char data) { addr &= 0x7F;
digitalWrite(PRESS_SS, LOW); delay(1); SPI.transfer(addr); SPI.transfer(data); delay(1); digitalWrite(PRESS_SS, HIGH); } |
레지스터 주소와 쓸 데이터를 매개 변수로 받고 있으며, addr 값에 0x7F 값을 &(AND) 연산하여 최상위 비트를 0으로 만든다. 음.. & 연산이 처음 나왔지만 소스 때문에 길이가 너무 길어져서 “*참고”로 넣을까 말까 고민 중.
그리고는 PRESS_SS 키워드로 지정한 SS 핀을 LOW로 변경하여 PRESS_SS 핀에 연결된 슬레이브를 선택한다. 약간의 딜레이를 주고SPI.transfer() 함수를 이용하여 주소를 먼저 전송, 쓰기 모드이므로 다시 데이터를 전송한다. 또 약간의 딜레이를 준 후 SS 신호를 HIGH로 변경하면 쓰기 끝.
이번엔 readData() 함수.
char readData(byte addr) { char data; addr |= 0x80;
digitalWrite(PRESS_SS, LOW); delay(1); SPI.transfer(addr); data = SPI.transfer((byte)0); delay(1); digitalWrite(PRESS_SS, HIGH);
return data; } |
레지스터 주소 값을 매개 변수로 받아서 최상위 비트를 1로 만든다. |(OR) 연산을 이용해서.
그리고는 역시 SS 핀을 LOW 신호로 만든 후 레지스터 값(+읽기 비트)을 전송, 데이터를 읽기 위해 다시 한 번 0(사실 무슨 값을 쓰든 상관 없다)을 전송하여 반환되는 값을 data 변수에 저장한다. SPI 통신은 읽기와 쓰기가 동시에 이뤄지기 때문에 데이터를 읽기 위해서는 데이터를 써야 한다는 점 꼭 명심.
그리고 SS 핀을 다시 HIGH로 만든 후 data 값을 반환한다.
어렵지 않다. 유의해야 할 점은 통신 할 때 SS 신호가 LOW여야 한다는 점.
그럼 기압 센서의 기압 값 변환 소스 설명은 나도 잘 모르니까 넘어가면서(읭?) 오늘 강좌는 여기서 끝! 다음 강좌부터는 모터 다루기 실습을 진행할 예정이니까 관심 있으신 분들은 또 들러주세용~
안녕.