[참고] Digispark (ATTiny85)를 I2C의 A/D 변환 장치로 사용하여 RaspberryPi에서 사용합니다.

전회, Digispark (ATTiny85)를 I2C의 슬레이브에서 사용 (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



  • 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


    일정은 미정


  • 일정 간격으로 값을 읽고, 쿠라우드라든지에 데이터 보내고, 그래프 따뜻하게 하거나 버리면 멋지네요.
  • 좋은 웹페이지 즐겨찾기