RaspberryPi 電源コントローラ | Tamesuke-Goto Maker的Blog

Tamesuke-Goto Maker的Blog

地域ISP管理者だけれど、ここ3年ほどMakerなJobが増えたのでまとめてみたいと思います 旧ハンドル Ringoro

この間PCBGoGoへオーダしたRaspberryPi用電源コントローラの基板を配線します。
SleePiの替わりになる様なボードですが一定時間で起こすので、名前は WakeUpPiにしました。

先ずは表面実装から,,,


{9488F55B-1E60-423A-8AF7-E858074A73F0}

 

その他部品 値は結構バラバラ

デカップリングコンデンサはシルク上は100μFにしてますが、ACアダプタによっては容量が大きすぎるかもしれません。一応手持ちの22μFを取り付けました。

 

 

{6A4E31FA-605F-400B-B7DA-32179ED2A483}

 

 

バッテリーホルダーは裏面です。

 

{45F072DF-F863-4132-B73B-1E278574039F}

 

 

実際に取り付けました。

 

{357EB95C-CBB6-4E24-8EA9-E7237A3565B2}

スケッチは前回の試作からだいぶ変えました。
LEDの点滅には以前書いたオブジェクト指向的LEDブリンクの関数を使っています。点滅タイミングでステータスを表すのにコードがすっきりするのて効果的です。
loop()内での処理は1msec毎で良いのですがloop()の呼ばれるタイミングが意外と速く無駄にタイマアクセスしている様なので一定回数はi2cの処理の他は何もしないというロジックにしました。何回毎にタイマ処理させるかはテキトーに#define INTERVAL  で設定しています。

回路図 、 スケッチがうまく入らない様なので qiitaへも投稿しました。

http://qiita.com/ringorou/items/d6585552471071288579


--------------------------------------------------

/*
 * WakeUp Pi ATtiny85
 * 2017/4/14
 *
 *

                 ATTiny85  
            RST |1---O---8| VCC
   PCINT3/A3/D3 |2       7| D2/A1/INT0/PCINT2
   PCINT4/A2/D4 |3       6| D1/PWM/PCINT1
            GND |4-------5| D0/PWM/A0/PCINT0
 
 */


#include <TinyWireS.h>

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

#include "TinyWireS.h"
// #include <TimeLib.h>

#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif


#define FET  3      // GPIO FET pin
#define SW1  1   // PowerON SW

#define DOWN 4  // Shutdown DIO for Rpi
#define SW2  4  // Option SW or DIO

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

struct led waitled={DOWN,0,0,50,3000};
struct led wakeled={DOWN,0,0,50,1000};
struct led stopled={DOWN,0,0,1500,1600};

bool powon=false;
char stopping=0;

/*
 *  bit0 ...  min
 *  bit1 ...  hour
 *  bit2 ...  day
 *  bit3 ...  WakeupSTART
 *  bit4 ...  ShutDownTimer
 */

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

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


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

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

uint32_t downtimer;
uint32_t waketimer;

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++;
    }

    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 blinkled(int p,int c,int dly);
void blinkled2(struct led);
void poweron(void);

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 sw
    
    TinyWireS.begin(I2C_SLAVE_ADDRESS);
    TinyWireS.onReceive(receiveEvent);
    TinyWireS.onRequest(requestEvent);
}

bool timchk()
{
  tim = millis()/1000;
  if(tim==last)
    return false;
  last=tim;
  return true;  
}
/*   msec check NON Use
 *    
bool mtimchk()
{
  mtim = millis();
  if(mtim==mlast)
    return false;
  mlast=mtim;
  return true;  
}
*/

/*
 * Main Loop
 *
 */

#define INTERVAL  40
void loop()
{
    static int intv=0;
 
    if(powon){
      TinyWireS_stop_check();
    }


    if((intv++ % INTERVAL)){
      return;
    }
      
    if(!stopping && !powon && !digitalRead(SW1)){
      delay(200);
      if(!digitalRead(SW1)){
        poweron();
        }
     }

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

    if(!timchk())
        return;

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

    if(!powon && waketimer){
      waketimer=waketimer-1;

      if(waketimer==0){
        i2c_regs[wakereg]=0;
        poweron();
      }
    }
      
        
    if(stopping){
      stopping--;
      if(stopping==0){
        digitalWrite(FET, LOW);
        digitalWrite(DOWN, LOW);
        powon=false;
        downtimer=0;
        i2c_regs[downreg] = 0;
        }
    }

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

    if(powon){
      TinyWireS_stop_check();
    }
}

/*
 * 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;
}

 

-----------------------------------------------