LoginSignup
6
5

More than 5 years have passed since last update.

[メモ] Digispark(ATTiny85)をI2CのA/D変換デバイスにして、RaspberryPiから使う。

Posted at

前回、Digispark(ATTiny85) をI2CのSlaveで使用(TinyWireS)して、RaspberryPi(Master)と通信してみる の続きで、

#ラズパイにADCがない! => 手元にあるATTiny85のADCの値をI2Cで受け渡せば... ってのが動機。

を解消。フォトセルを使って、電圧を適当にかえて、A/D変換して、値をとる。

準備

ピン配

  • DigisparkのP4をADCポートとして使用。
  • 接続は
    • 5V - フォトセル - P4 - 1Kオームの抵抗 - GND
    • フォトセル と 1Kオームの抵抗 のあいだにDigispark::P4端子を接続
  • 5Vがリファレンスなので、0V=0, / 5V=1023くらいの値がかえってくるハズ。
  • あとは前回と同じ。P0=I2C-SDA, P2=I2C-CLK

IMG_5049VGA.jpg

Digispark側のコード

  • get_adcVal()という、P4の電圧値を読みとって、i2c_regs[0]と[1]に格納する関数追加。loop内で呼び続ける。
    • ## データが要求される[requestEvent()]ときにget_adcVal()を呼ぶようにしたら、たまに、というかけっこうな頻度で、変な値がでてきた。ADCリードで遅延するから??I2Cのレートをおとせば、いけるかも。
  • あとは、前回とほぼ同じ。

#define I2C_SLAVE_ADDRESS 0x5A // the 7-bit address
#define LED_PIN         1      // DigiSpark LED pin

#include "TinyWireS.h"

#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif

volatile uint8_t i2c_regs[] =
{
    0xDE, 
    0xAD, 
    0xBE, 
    0xEF, 
};

int get_adcVal() {
  analogReference(DEFAULT);  // Reference = 5V
  int adcValue = analogRead(2); // Read P4
  i2c_regs[0] = adcValue & 0xff;
  i2c_regs[1] = (adcValue>>8) & 0xff;
}


volatile byte reg_position;
const byte reg_size = sizeof(i2c_regs);

void requestEvent()
{  
    reg_position %= reg_size;
    TinyWireS.send(i2c_regs[reg_position]);
    reg_position++;
}

void receiveEvent(uint8_t howMany)
{
    // Sanity check
    if ((howMany < 1) || (howMany > TWI_RX_BUFFER_SIZE)) return;
    
    reg_position = TinyWireS.receive();
    howMany--;

    while(howMany--)
    {
        reg_position %= reg_size;
        i2c_regs[reg_position] = TinyWireS.receive();
        reg_position++;
    }
}

void setup(){
    pinMode(4, INPUT);  // P4=ADC Input
    pinMode(LED_PIN,OUTPUT);
    mt08Blink(LED_PIN, 2);               //開始時LED点滅

    TinyWireS.begin(I2C_SLAVE_ADDRESS);
    TinyWireS.onReceive(receiveEvent);
    TinyWireS.onRequest(requestEvent);
}

void loop()
{
    TinyWireS_stop_check();
    get_adcVal();
}

void mt08Blink(byte led, byte times)
{
  times *= 2;
  while(times > 0) {
    digitalWrite(led,(times & 0x01) ? LOW : HIGH);
    delay (200);
    times--;
  }
}

実行例

pi@raspberrypi ~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- 5a -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
pi@raspberrypi ~ $ i2cget -y 1 0x5a 0x00; i2cget -y 1 0x5a 0x01
0xed
0x02
pi@raspberrypi ~ $ i2cget -y 1 0x5a 0x00; i2cget -y 1 0x5a 0x01
0x59
0x00
ADC(16進) ADC(10進) ADC電圧 電圧実測(テスタで計測)
0x02ED 749 5V * 749/1024 = 3.66V 3.64V
0x0059 89 5V * 89/1024 = 0.43V 0.412V

予定は未定

  • 一定間隔で値を読み出して、クらウドとかにデータ送って、グラフなんかつくったりしちゃうとかっこいいよね。
6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5