1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WakeUp Pi ATTiny841

Posted at

Raspberry Pi 用電源コントローラ

メカトラックスのSlee-Piみたいな スイッチサイエンスの 電源制御モジュールみたいなボード。https://www.switch-science.com/catalog/3268/
です。ATTiny841を使って再度試作してみました。

 一度 ATTiny85を使って試作しましたがちょと難があって、、

  1. 外部コントロールのためのビットが少ない
  2. i2c通信がソフトウェアでやっているので、時々通信エラーが出る

特に安定してi2c通信はしておきたい処です。もしかするとATTiny85のクロックを上げれば安定するかもしれませんが、消費電力も大きくなってしまうので悩ましいところです。やはりi2cがハードウェアで対応していた方が良いでしょう。

というわけで適当なCPUは無いかと、ATTiny841が丁度良いのではないかと使って見た次第です。ATTiny85の基板を使ってとりあえず試作。結構うまく行きました。

Wakeip841.jpeg

考えている回路図は以下の様なものです。試作なので全部実装はしていませんが、ATTinyからのコントロール線は拡張して使える様にしておきたいです。Raspberry Piとの間はi2cを主に使って通信すれば良いと思っています。

Wakeu841sch.png

スケッチはこんな感じ、、、i2c関連のライブラリはgithubにあります。
https://github.com/orangkucing/WireS
ATTiny側のソフト次第で色々な機能が付加出来ると考えています。アナログ入力で電源電圧を監視するとか、応用出来ると思います。

WakeupPi841.c
# include <WireS.h>
# include <avr/sleep.h>

/*
   Wake Up Pi ATTiny841

   8MHz Internal Clock 

// ATMEL ATTINY84 / ARDUINO  ATTiny Universal lib 
//                           Counter Clock Wise
//
//                           +--U--+
//                     VCC  1|     |14  GND
//             (D  0)  PB0  2|     |13  PA0  (D 10)  AREF
//             (D  1)  PB1  3|     |12  PA1  (D  9) {DOWN LED]
//       RSET  (D 11)  PB3  4|     |11  PA2  (D  8) 
//  PWM  INT0  (D  2)  PB2  5|     |10  PA3  (D  7) 
//  PWM        (D  3)  PA7  6|     |9   PA4  (D  6)  SCL
//  PWM   SDA  (D  4)  PA6  7|     |8   PA5  (D  5)  PWM
//                           +-----+

The SCL of the ATTiny84 (pin 9) 
The SDA of the ATTiny84 (pin 7) 
 
 */



# define I2C_SLAVE_ADDRESS 0x5B // the 7-bit address

# ifndef TWI_RX_BUFFER_SIZE
# define TWI_RX_BUFFER_SIZE ( 16 )
# endif

# define FET  3      // GPIO FET pin  PA7 
# define SW1  7      // PowerON SW PA3 

# define DOWN 9  // Shutdown DIO for Rpi PA1
# define SW2  8  // Option SW or DIO  PA2

# define testled 2 // test LED

struct led {
  int pin;   //  PIN No.
  bool on;   // ON/OFF status
  int cont;  // time count
  int ontime; // ON time (100 msec tic )
  int intval; // interval time (100 msec tic)
};

struct led waitled={DOWN,0,0,1,30};
struct led wakeled={DOWN,0,0,1,10};
struct led stopled={DOWN,0,0,15,16};
struct led waitled2={testled,0,0,1,30};

bool powon=false;
char stopping=0;

/* 
 *  byt0 ...  min
 *  byt1 ...  hour
 *  byt2 ...  day
 *  byt3 ...  WakeupSTART
 *  byt4 ...  ShutDownTimer
 *  byt5 ...  SW Status
 *  byt6 ...  reserve
 *  byt7 ...  reserve
 */

enum {mins,hours,days,wakereg,downreg,swstat};

volatile uint8_t i2c_regs[] =
{
   0,0,0,0,0,0,0,0
};

int    dly=1000;

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

volatile unsigned wordAddr;
volatile boolean repeatedStart;

uint32_t downtimer;
uint32_t waketimer;

//int led = 7;   // for ATT44 pin 6
//int led = 10;   // for ATT44 pin 2

// When Address Received 

boolean addressEvent(uint16_t slaveAddress,uint8_t count)
{  
  if(count>0){
     reg_position= Wire.read();
  }
  return true;
}

// GET Reqesut

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

//  SET Event

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

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

    if(i2c_regs[downreg]){
      downtimer=i2c_regs[downreg];
    } 

    if(i2c_regs[wakereg]){
      waketimer = i2c_regs[mins]*60L+i2c_regs[hours]*60L*60L+i2c_regs[days]*60L*60L*24L;
    } else {waketimer=0;}

}

void stopHandler()
{
  
}


uint32_t  tim;
uint32_t  last;
//uint32_t  mtim;
//uint32_t  mlast;

// the setup function runs once when you press reset or power the board
void setup() {
//    mlast = mtim = millis();
    tim = millis()/1000;
    last =tim;
    pinMode(FET,OUTPUT);
    digitalWrite(FET ,LOW);   // Normal Power OFF
    pinMode(DOWN,OUTPUT);
    pinMode(SW1, INPUT_PULLUP);  // power on sw1
    pinMode(SW2, INPUT_PULLUP);  // power on sw2
    pinMode(testled,OUTPUT);

    Wire.begin(I2C_SLAVE_ADDRESS);
    Wire.onAddrReceive(addressEvent);
    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);
    Wire.onStop(stopHandler);
    delay(500);
}

void mydelay(unsigned long dt);

bool timchk()
{
  tim = millis()/1000;
  if(tim==last)
    return false;
  last=tim;

  return true;  
}

//   Loop 

void loop() {

    if(!powon){
      mydelay(100);
    }else{
      delay(100);
    }
    
    i2c_regs[swstat]= ~(digitalRead(SW1) | digitalRead(SW2) << 1) & 0B00000011;

//  Power ON SW1
      
    if(!stopping && !powon && !digitalRead(SW1)){
      delay(200);
      if(!digitalRead(SW1)){
        poweron();
        }
     }

//  Power ON SW2
      
    if(!stopping && !powon && !digitalRead(SW2)){
      delay(200);
      if(!digitalRead(SW2)){
        poweron();
        }
     }


//--------- Blink LED ---------//

      if(!powon && !i2c_regs[wakereg]){
         blinkled(&waitled);
      }
      if(i2c_regs[wakereg])
        blinkled(&wakeled);
      if(stopping){
        blinkled(&stopled);
       }


    if(!timchk())
        return;

// Power Down Sequence

    if(powon && downtimer){
      downtimer--;
      i2c_regs[downreg] = (unsigned char)downtimer;
      if(downtimer==0){
        stopping=10;
        digitalWrite(DOWN,HIGH);
      }
    }

//   Wakeup Sequence 

    if(!powon && waketimer){
      waketimer=waketimer-1;
      if(waketimer==0){
        i2c_regs[wakereg]=0;
        poweron();
      }
    }
      
//  Stop All Sequence
       
    if(stopping){
      stopping--;
      if(stopping==0){
        digitalWrite(FET, LOW);
        digitalWrite(DOWN, LOW);
        powon=false;
        downtimer=0;
        i2c_regs[downreg] = 0;
        }
    }

// SW1 Power Down Chech

/*
    if(powon && !digitalRead(SW1)&& !stopping ){
      delay(2500);
      if(!digitalRead(SW1)){
        digitalWrite(DOWN, HIGH);
        stopping=15;
        } else {stopping = 0;}    
     }
*/

}

/*
 * Sub funcitons...
 */

void poweron()
{
   digitalWrite(FET, HIGH);
   digitalWrite(DOWN, LOW);  
   powon=true;
   stopping=0;
   downtimer=0;

}

void blinkled(struct led *myled)
{
  int pin=myled->pin;
  if(myled->cont++ == myled->ontime){
    digitalWrite(pin,false);
    myled->on=false;
    } else if(myled->cont >= myled->intval){
      digitalWrite(pin,true);
      myled->cont=0;
      myled->on=true;
    }
//  return myled->on;
}

void mydelay(unsigned long dt) {
  unsigned long _t;
  set_sleep_mode (SLEEP_MODE_IDLE); 
  _t = millis();           
  while( millis() - _t < dt ) {
    sleep_mode();
    }

}

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?