USB電源遅延装置
USBケーブルの中間に挿入しUSBデバイスへの電源投入を遅延させる装置。
USBキーボードをRaspberry Piに接続してから電源を入れるとキーボードが認識しなかった。Raspberry Piを起動してから接続すると認識する。そこでUSBのコネクタ内に電源を遅延する回路を組み込むことにする。
Hardware
手元にあるAtmelのAVRデバイスAT90S2323を使用する。5VラインにPchのMOSFETを挿入し所定の時間が経過した後にオンするようプログラミングする。
Schematic
回路はホビーなので各種保護など考えず簡単なものに。発振器はセラロック4MHz。
Imprement
B面にはMOSFETを実装。
A面にはMPUと発振器を実装。
Software
開発環境はAtmel Studio 7.0で行なった。
Source Code
遅延時間はRaspberry Piが起動してPrompt待ちとなる、5sとした。
/*
proj.name: Power Switch
cir.diagram: Rev 1
MCU: AT90S2323, 4MHz
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#define TRUE (1)
#define FALSE (0)
#define TIMEOUT (5000) /* [ms] */
#define SW_PORT (PORTB)
#define SW_BIT (2)
#define RELOAD_CNT (256 - 63 + 1) /* 63*64/4MHz=1.008ms */
#define enable_timerint() (TIMSK = 0x02)
#define disable_timerint() (TIMSK = 0x00)
#define turn_off_sw() (SW_PORT |= _BV(SW_BIT)) /* Hi */
#define turn_on_sw() (SW_PORT &= ~_BV(SW_BIT)) /* Lo */
typedef unsigned char uint8;
typedef unsigned int uint16;
int main(void);
void exec_cmd(void);
uint16 get_count1ms(void);
void init_MCU(void);
volatile uint16 Count1ms;
volatile uint8 Flag1ms;
int main(void)
{
init_MCU();
Count1ms = 0;
Flag1ms = FALSE;
exec_cmd(); /* Init */
enable_timerint();
sei();
while(TRUE) {
if(Flag1ms) {
Flag1ms = FALSE;
exec_cmd();
}
}
return(1);
}
void exec_cmd(void)
{
enum state_list { CMD_INIT, CMD_WAIT, CMD_ON, CMD_OFF };
static enum state_list state = CMD_INIT;
static uint16 timer;
switch(state) {
case CMD_INIT:
timer = get_count1ms();
state = CMD_WAIT;
break;
case CMD_WAIT:
if((uint16)(get_count1ms() - timer) > TIMEOUT) {
turn_on_sw();
state = CMD_ON;
}
break;
case CMD_ON:
break;
default:
break;
}
}
uint16 get_count1ms(void)
{
uint16 count;
cli();
count = Count1ms;
sei();
return(count);
}
void init_MCU(void)
{
/* MCU controll */
MCUCR = 0x00; /* 00000000 */
/* port */
PORTB = 0x04; /* 00000100 B2=~FETgate */
DDRB = 0x07; /* 00000111 B2=~FETgate */
/* 8bit timer 0 */
TIMSK = 0x02; /* enable TOIE0 */
TIFR = 0x00; /* clear TOV0 */
TCNT0 = RELOAD_CNT;
TCCR0 = 0x03; /* 00000011 f=CK/64 */
}
SIGNAL(SIG_OVERFLOW0) /* 1ms interval */
{
TCNT0 = RELOAD_CNT;
Flag1ms = TRUE;
Count1ms++;
}