Last active
October 7, 2015 03:20
-
-
Save PiTshan/5025d7ba2e5985db494f to your computer and use it in GitHub Desktop.
RaspPiとArduinoをI2C接続して、アナログセンサを最大4つ接続する
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* I2C SensorHub Ver1.0 | |
* created 18 Sep. 2015 | |
* function: | |
* communicate to AD converter(A0,A1,A2,and A3 port) on Aruduino UNO via I2C bus. | |
* based on SUMBus protocol (almost, uncertain) | |
* Editor : PiT | |
* 07 Oct. 2015 V1.1 A0_MSB,A0_LSB,..A3_MSB,A3_LSBをReadOnlyに変更 | |
* 07 Oct. 2015 V1.0.1 コメント:レジスタマップの間違いを修正 | |
* 01 Oct. 2015 V1.0 release | |
* 01 Oct. 2015 V0.5 I2Cのデータロストを防止するため、PWM機能のディセーブル。SDA,SCLの内部プルアップをディセーブル。 | |
* レジスタマップ変更、Vddコントロールの仕様変更、デバイスディスクリプション”SHUB”バージョン、リビジョンレジ 追加 (動作確認用) | |
* 26 Sep. 2015 V0.4 レジスタを16→256に戻す。 余計なアドレス計算でRaspPi側からのアクセスに間に合わない模様 デバッグ用シリアルポートをコメントアウト | |
* 25 Sep. 2015 V0.3 スレーブIDを0x50→0x72に変更。13番PinをAD変換中に点灯させるように変更 | |
* 25 Sep. 2015 V0.2 レジスタを256→16に変更。アドレス上位は不定になります。 コメントを少し変更。 | |
* 18 Sep. 2015 | |
* | |
* pin connection 1 to RaspberryPi | |
* Arduino - Master device (Laspberry Pi) | |
* A4(SDA) - I2C1SDA | |
* A5(SCL) - I2C1SCL | |
* GND - GND | |
* | |
* pin connection 2 (to analog sensor) | |
* センサのアナログ入力です | |
* Arduino - sensor | |
* A0 - A0Vo | |
* A1 - A1Vo | |
* A2 - A2Vo | |
* A3 - A3Vo | |
* | |
* pin connection 3 (to analog sensor Vdd) | |
* アナログセンサの電源をレジスタアクセスでON/OFFできるようにします。 | |
* Arduino - sensor | |
* Digital13 - (A0Vdd) | |
* Digital12 - (A1Vdd) | |
* Digital11 - (A2Vdd) | |
* Digital10 - (A3Vdd) | |
* | |
* Register Map | |
* 0x00 A0_CTRL : 2'b00, vref[1:0], pondly[1:0], powctrl, enable(R/W) | |
* 0x01 A1_CTRL : 2'b00, vref[1:0], pondly[1:0], powctrl, enable(R/W) | |
* 0x02 A2_CTRL : 2'b00, vref[1:0], pondly[1:0], powctrl, enable(R/W) | |
* 0x03 A3_CTRL : 2'b00, vref[1:0], pondly[1:0], powctrl, enable(R/W) | |
* 0x04 - 0x07 reserved : 8'b0000_0000 (R/W) | |
* 0x08 A0_MSB : 4'b0, A0MSB[11:8] (R/W) | |
* 0x09 A0_LSB : A0LSB[ 7:0] (R/W) | |
* 0x0A A1_MSB : 4'b0, A1MSB[11:8] (R/W) | |
* 0x0B A1_LSB : A1LSB[ 7:0] (R/W) | |
* 0x0C A2_MSB : 4'b0, A2MSB[11:8] (R/W) | |
* 0x0D A2_LSB : A2LSB[ 7:0] (R/W) | |
* 0x0E A3_MSB : 4'b0, A3MSB[11:8] (R/W) | |
* 0x0F A3_LSB : A3LSB[ 7:0] (R/W) | |
* 0x10-0x13 DeviceDiscriptionID : "SHUB" | |
* 0x14 Version No. | |
* 0x15 Revision No. | |
* | |
* 0x00-0x03 : A0_CTRL, A1_CTRL, A2_CTRL, A3_CTRL | |
* 2'b00, vref[1:0] pondly[1:0], sleepmode, enable | |
* vref[1:0] : Vrefソースの選択 00:Vdd, 01:internal1V1, 10:Aref-pin, 11:Vdd | |
* pondly : power on delay センサーの電源ONからADC開始までのディレイ(100mSec単位) | |
* 0~300mSecまで センサーが落ち着くのに時間がかかる場合に使う | |
* 100mSec(2'b01)を設定しておくとだいたい安定して測定できるようです。 | |
* powctrl : センサの電源をディジタルピンから供給し、ADC中のみONにする。 | |
* 常時ONにしたい場合は、ディジタルピンを使わずにVddに接続しておいたほうが良いです | |
* センサのドライブ電流に注意 | |
* enable : ADCイネーブル 1のあいだ変換中で、変換終了後0に戻る | |
* | |
* 0x08-0x0F : AD変換された値はここに格納されます。 | |
* 0x10-0x13 DeviceDiscriptionID : I2Cの接続確認などに使います。 | |
* 0x14 Version : I2CSensorHubのバージョンです。インターフェイスの大幅な仕様変更など、RaspPiソフトウェア側の変更が必要な場合増えます。 | |
* 0x15 Revision : I2CSensorHubのリビジョンです。RaspPiのソフトウェアに影響がない場合増えます。 | |
*/ | |
#include <Wire.h> | |
const char DEVICE_ID = 0x72; //slave device address | |
#define VERSION 01 | |
#define REVISION 01 | |
/* REG MAP define */ | |
#define A0_CTRL 0x00 | |
#define A1_CTRL 0x01 | |
#define A2_CTRL 0x02 | |
#define A3_CTRL 0x03 | |
#define A0_RSVD 0x04 | |
#define A1_RSVD 0x05 | |
#define A2_RSVD 0x06 | |
#define A3_RSVD 0x07 | |
#define A0_MSB 0x08 | |
#define A0_LSB 0x09 | |
#define A1_MSB 0x0A | |
#define A1_LSB 0x0B | |
#define A2_MSB 0x0C | |
#define A2_LSB 0x0D | |
#define A3_MSB 0x0E | |
#define A3_LSB 0x0F | |
/* pin connection 3 センサーのパワーピン | |
* アナログセンサの電源をコントロールしたい場合に使用します。 | |
* AD変換中以外はセンサーの電源を落とします。 | |
* この機能が必要ない場合は、センサーの電源はVddなどに接続しておきます。 | |
* Arduino - sensor | |
* 13 - (A0Vdd) | |
* 12 - (A1Vdd) | |
* 11 - (A2Vdd) | |
* 10 - (A3Vdd) | |
*/ | |
#define A0_VDD_PIN 11 | |
#define A1_VDD_PIN 10 | |
#define A2_VDD_PIN 9 | |
#define A3_VDD_PIN 8 | |
#define ADC_ACT_LED 13 | |
unsigned char deviceRegAddr; //SMBusレジスタのアドレス | |
#define MAX_REG_ADDR 256 | |
unsigned char deviceReg[MAX_REG_ADDR]; //SMBus レジスタ | |
void setup() { | |
pinMode(A0_VDD_PIN, OUTPUT); | |
pinMode(A1_VDD_PIN, OUTPUT); | |
pinMode(A2_VDD_PIN, OUTPUT); | |
pinMode(A3_VDD_PIN, OUTPUT); | |
pinMode(ADC_ACT_LED, OUTPUT); | |
digitalWrite(ADC_ACT_LED, LOW); | |
Wire.begin(DEVICE_ID); // slave device address | |
digitalWrite(SDA, 0); // internal PullUp disable | |
digitalWrite(SCL, 0); // internal PullUp disable | |
Wire.onRequest(requestEvent); // tx event | |
Wire.onReceive(receiveEvent); // rx event | |
TIMSK0 = 0; //Timer0 interrupt disable, It means software PWM function also disable. | |
//its necessary for stable I2C communication | |
for (int i = 0; i < MAX_REG_ADDR; i++) deviceReg[i] = 0; //deviceReg initialize | |
deviceReg[0x10] = 'S'; | |
deviceReg[0x11] = 'H'; | |
deviceReg[0x12] = 'U'; | |
deviceReg[0x13] = 'B'; | |
deviceReg[0x14] = VERSION; | |
deviceReg[0x15] = REVISION; | |
} | |
int adcvalue; | |
void loop() { | |
if (deviceReg[A0_CTRL] & 0x01) { // A0_CTRL start flag is enabled | |
digitalWrite(ADC_ACT_LED, HIGH); | |
setARef(A0_CTRL); | |
digitalWrite(A0_VDD_PIN, HIGH); //sensor Vdd enable | |
powerondelay(A0_CTRL); | |
adcvalue = analogRead(A0); | |
deviceReg[A0_MSB] = (char)((adcvalue >> 8) & 0xFF); | |
deviceReg[A0_LSB] = (char)(adcvalue & 0xFF); | |
deviceReg[A0_CTRL] = deviceReg[A0_CTRL] & 0xFE; | |
} | |
if (deviceReg[A0_CTRL] & 0x02) digitalWrite(A0_VDD_PIN, HIGH); //sensor Vdd enable | |
else digitalWrite(A0_VDD_PIN, LOW); //sensor Vdd disable | |
if (deviceReg[A1_CTRL] & 0x01) { // A1_CTRL start flag | |
digitalWrite(ADC_ACT_LED, HIGH); | |
setARef(A1_CTRL); | |
digitalWrite(A1_VDD_PIN, HIGH); //sensor Vdd enable | |
powerondelay(A1_CTRL); | |
adcvalue = analogRead(A1); | |
deviceReg[A1_MSB] = (char)((adcvalue >> 8) & 0xFF); | |
deviceReg[A1_LSB] = (char)(adcvalue & 0xFF); | |
deviceReg[A1_CTRL] = deviceReg[A1_CTRL] & 0xFE; | |
} | |
if (deviceReg[A1_CTRL] & 0x02) digitalWrite(A1_VDD_PIN, HIGH); //sensor Vdd enable | |
else digitalWrite(A1_VDD_PIN, LOW); //sensor Vdd disable | |
if (deviceReg[A2_CTRL] & 0x01) { // A2_CTRL start flag | |
digitalWrite(ADC_ACT_LED, HIGH); | |
setARef(A2_CTRL); | |
digitalWrite(A2_VDD_PIN, HIGH); //sensor Vdd enable | |
powerondelay(A2_CTRL); | |
adcvalue = analogRead(A2); | |
deviceReg[A2_MSB] = (char)((adcvalue >> 8) & 0xFF); | |
deviceReg[A2_LSB] = (char)(adcvalue & 0xFF); | |
deviceReg[A2_CTRL] = deviceReg[A2_CTRL] & 0xFE; | |
} | |
if (deviceReg[A2_CTRL] & 0x02) digitalWrite(A2_VDD_PIN, HIGH); //sensor Vdd enable | |
else digitalWrite(A2_VDD_PIN, LOW); //sensor Vdd disable | |
if (deviceReg[A3_CTRL] & 0x02) digitalWrite(A3_VDD_PIN, HIGH); //sensor Vdd enable | |
if (deviceReg[A3_CTRL] & 0x01) { // A3_CTRL start flag | |
digitalWrite(ADC_ACT_LED, HIGH); | |
setARef(A3_CTRL); | |
digitalWrite(A3_VDD_PIN, HIGH); //sensor Vdd enable | |
powerondelay(A3_CTRL); | |
adcvalue = analogRead(A3); | |
deviceReg[A3_MSB] = (char)((adcvalue >> 8) & 0xFF); | |
deviceReg[A3_LSB] = (char)(adcvalue & 0xFF); | |
deviceReg[A3_CTRL] = deviceReg[A3_CTRL] & 0xFE; | |
} | |
if (deviceReg[A3_CTRL] & 0x02) digitalWrite(A3_VDD_PIN, HIGH); //sensor Vdd enable | |
else digitalWrite(A3_VDD_PIN, LOW); //sensor Vdd disable | |
digitalWrite(ADC_ACT_LED, LOW); //ADC active LED off | |
} | |
void powerondelay(int ControlRegIndex) | |
{ | |
if (deviceReg[ControlRegIndex] & 0x04) delay(100); //power on delay 100ms | |
if (deviceReg[ControlRegIndex] & 0x08) delay(200); //power on delay 200ms | |
} | |
void setARef(int ControlRegIndex) | |
{ | |
//vref[1:0] : Vrefソース 00:Vdd, 01:internal1V1 10:Aref-pin 11:Vdd | |
if ((deviceReg[ControlRegIndex] & 0x30) == 0x10) { | |
analogReference(INTERNAL); //use 1.1v reference | |
} else if ((deviceReg[ControlRegIndex] & 0x30) == 0x20) { | |
analogReference(EXTERNAL); //use ARef pin | |
} else { | |
analogReference(DEFAULT); //use Vdd=5V | |
} | |
analogRead(A0); //dmy 切り替えたあとに1回読む | |
} | |
//I2C interrupt --------- | |
void requestEvent() // I2C TX (i2cget) | |
{ | |
Wire.write(deviceReg[deviceRegAddr]); | |
deviceRegAddr++; //auto increment | |
} | |
void receiveEvent(int howMany) // I2C RX | |
{ | |
deviceRegAddr = Wire.read(); | |
while (0 < Wire.available()) // loop through all but the last | |
{ | |
if (deviceRegAddr >= 0 && deviceRegAddr <= 0x07) //read and write reg | |
deviceReg[deviceRegAddr] = Wire.read(); // receive byte as a character | |
//other : read only | |
deviceRegAddr++; //auto increment | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment