[Netduino] .NET Micro Framework 에서의 I2C 통신 - BH1750FVI 조도 센서 응용
Small Devices/Netduino 2012. 7. 26. 00:331. I2C란?
I2C는 Philips Semiconductors에 의해서 1980년대 초에 개발되었고 1992년에 규격이 나왔다. I2C는 두개의 양방향 Wire를 이용한다. 속도가 다른 Bus 시스템보다 느리긴 하지만 저 비용으로 주변 장치를 붙이는데 이상적이다. 동작중에 주변 장치는 부착 되거나 제거가 가능하기 때문에 Plug-gable Hardware를 만드는데 이상적이다.
첫번쨰 라인은 SDA라는 Serial Data 라인으로 실제 데이터가 Serial하게 전송된다. 두번째 라인은 SCL으로 Serial Clock을 의미하며 bus에 clock을 부과한다.
초기 명세서에서는 bus speed를 100KHz로 규정하였지만 현재의 응용에는 적합하지 않기 때문에 명세는 다시 보완되었다.
각각의 I2C 모듈은 7-bit address로 선택 된다. 여덜번째 비트는 read/write flag로 이 비티는 microcontroller가 read/write를 원하는지 알려준다. 모든 데이터는 MSB First로 전송된다.
Communication은 Master와 Slave사이에 발생하며 MultiMaster Mode도 가능하다. Master는 필요한 주변 장치에게 start condition을 보내며 이때 slave는 버스를 listen하고 있다가 Master가 요청하는 버스의 address와 slave의 address를 비교한다. 해당 address의 slave에서는 master에게 그 address에 맞는 주변 장치가 존재함을 그리고 준비가 되었다고 ACK을 보낸다. 그리고 두 장치간에 데이터를 교환한다. 각각의 Byte 전송시 ACK도 전송된다. Master가 STOP Condition을 보내면 Communication이 완료 된다. Stop condition을 보내면 bus는 다른 communication을 위해서 준비 상태가 된다.
2. .NET Micro Framework에서 제공되는 I2C 클래스
.NET Micro Framework은 다음의 I2CDevice 클래스를 제공한다.
I2CDevice.Configuration 클래스는 I2CDevice 생성시에 필요하다. Configuration 클래스로 Device Address와 Communication Speed를 지정할 수 있다. 이후 CreateReadTransaction 또는 CreateWriteTransaction 메소드를 이용하여 Transaction Object를 생성하며 이때 Read/Write 하고자 하는 Buffer를 전달한다. 그리고 I2CDevice 클래스에 Execute 명령에 Transaction array를 전달하면 Communication이 시작된다. Execute는 read/write transaction 을 같이 섞어서 이용 가능하다. Execute는 모든 Transaction이 완료 되거나 Timeout이 만료되면 리턴한다. 이때 실제적으로 전송된 바이트를 전달한다.(Read+Write) 만약 Timeout이 Timeout.Infinite 또는 -1로 설정되면 Execute 메소드는 모든 transaction이 완료 될 때까지 블락된다.
3. Netduino와 BH1750FVI 조도 센서 연결
BH1750FVI에 대한 설명은 http://alnova2.tistory.com/646 를 참고하면 된다. Netduino의 I2C는 analog pin 4번이 SDA로 동작하며 analog pin 5번이 SCL로 동작한다. (arduino와 동일) 따라서 Netduino의 3.3V는 VCC에, GND는 GND에 Analog Pin 4번은 SDA에 Analog Pin 5번은 SCL에 GND를 ADD에 연결한다.
4. Netduino의 코드
다음은 조도 센서를 Power On 하고 H-Resolution Mode에서 한번 조도 값을 읽는 코드 이다.
1) I2C Device의 Configuration을 설정한다.
- BH1750FVI Datasheet를 보면 센서의 ADD를 GND에 연결할 경우 I2C Address는 이진수로 0100011 (0x23)이 된다. 따라서 I2C Device Configuration은 다음과 같이 설정한다.
I2CDevice.Configuration config = new I2CDevice.Configuration(0x23,100);
2) Device Power On 및 One Time H-Resolution Mode2로 I2C Device Write, 데이터 Read
- http://alnova2.tistory.com/646 에서 보이는 것처럼 BH1750FVI 조도 센서는 전원이 인가된 이후 Power-On 상태로 이전하고 Power-On 상태에서 One Time H-Resolution Mode2 에서 2 byte를 읽은 다음 다시 Powe-Off 모드로 바뀌게 된다. 또한 One Time H-Resolution Mode2 명령을 보내고 난 다음에 최대 180ms 정도 기다려야 한다. 따라서 명령 전송을 위한 write transaction과 read transaction을 같은 Execute 메소드에서 처리가 불가능 하다.
- Power-On 명령은 http://alnova2.tistory.com/646 의 명령어 표에서 처럼 0000_0001(0x01) 이고 One Time H-Resolution Mode2는 0010_0001(0x21) 이다. 다음은 Power On 을 위한 WriteTransaction 설정 코드 이다.
byte[] powerOn = new byte[] { 0x01 };
I2CDevice.I2CWriteTransaction powerOnTransation = I2CDevice.CreateWriteTransaction(powerOn);
다음은 One Time H-Resolution Mode2에 대한 명령을 Write 하기 위한 WriteTransaction 설정 코드이다.
byte[] readHResolution = new byte[] { 0x21 };
I2CDevice.I2CWriteTransaction readHResolutionTrx = I2CDevice.CreateWriteTransaction(readHResolution);
One Time H-Resolution Mode2 명령을 write 한 다음 2 Byte를 읽어 들이면 된다. 다음은 2바이트를 읽기 위한 Read Transaction 설정 코드 이다.
byte[] readData = new byte[2];
I2CDevice.I2CReadTransaction readDataTrx=I2CDevice.CreateReadTransaction(readData);
Read Transaction 을 수행하기 전에 대기 시간이 180ms 정도 있기 때문에 write transaction 과 read transaction을 구별해야 한다. 다음은 write transaction을 모아서 i2c에 보내는 코드이다. (즉 Power On과 H-Resolution Mode 설정을 위한 write가 같이 진행된다.)
I2CDevice.I2CTransaction[] transactions =
new I2CDevice.I2CTransaction[]{powerOnTransation, readHResolutionTrx };
int transferred = device.Execute(transactions, 1000);
이후 180 ms 이상 waiting 한 다음에 Read Transaction을 시도한다.
Thread.Sleep(200);
I2CDevice.I2CTransaction[] transactions2 = new I2CDevice.I2CTransaction[]{readDataTrx};
int transferred2 = device.Execute(transactions2, 1000);
일반 현광등에서 188정도, 바로 위에서 LED 스탠트 조명을 켰을때 약 2270정도 나오는 것을 알수 있다.