読者です 読者をやめる 読者になる 読者になる

電子工作

移転しました。


小さいステッピングモータを小信号トランジスタ一段で。静止状態で、350mW使うはずだから、ぎりぎりですね。
ft232rlから電源をとっている。200mAくらいつかってるはずだけど、大丈夫ぽい。
480ステップで一回転。500Hzで信号を切り替えてるので、60rpmくらいでしょうか。120rpmだと脱調した。5V入力では。12V用なので、12Vならデータシート通りにうごくのでしょう。


でかいステッピングモータは、二相で12V1.5A流したところで、すごいトルクでびびりました。排熱がめんどうなので、小さい方でなんとかならないかなと実験中。


秋月の品揃えが年々よく成りすぎていて、買わずにいられない。
というか、他のお店に行く機会も減っているような。



ボタンでスピード調整できるようにした。


眠いんで適当です。

#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#define LEN 4
#define BTN_UP (1<<PIND4)
#define BTN_DOWN (1<<PIND5)
#define BTN_SEL (1<<PIND6)

static unsigned int spd = 1;
static uint8_t wait_cnt = 1;
static uint8_t w = 1;
static uint8_t i = 0;

uint8_t set_spd(unsigned int new_spd);
/*void wait_ms(uint16_t w){
  while(w--){
    _delay_ms(1);
  }
}
*/

//2-phase
//0x0000 InA, In-A, InB, In-B
PROGMEM prog_char one_two_phase[LEN] =
{
  0b00000101,
  0b00000110,
  0b00001010,
  0b00001001,
};

ISR(TIMER0_OVF_vect){
  static uint8_t btn_old = 0;

  //01110000
  //00110000
  uint8_t btn = ~PIND & 0x70;

  //01110000
 // if(~PIND & 0x70){
  //  PORTB |= _BV(0);
   // PORTB = 0x01;
  //}else{
    //PORTB &= ~_BV(0);
  //}

  if((btn & BTN_SEL) &&
     ((btn & BTN_SEL) == (btn_old & BTN_SEL))){
    PORTB ^= 0x01;
  }else if((btn & BTN_UP) &&
           ((btn & BTN_UP) == (btn_old & BTN_UP))){
    set_spd(++spd);
    PORTB ^= 0x01;
  }else if((btn & BTN_DOWN) &&
           ((btn & BTN_DOWN) == (btn_old & BTN_DOWN))){
    set_spd(--spd);
    PORTB ^= 0x01;
  }

  btn_old = btn;
}


ISR(TIMER1_COMPA_vect){
  //for motor spd control
  w--;

  if(w==0){
    i++;
    i %= LEN;
    PORTD = (PORTD & 0x70) | pgm_read_byte_near(one_two_phase + i);
    w = wait_cnt;
  }
}


uint8_t set_spd(unsigned int new_spd){// per 10ms
  //12rpm - 1/(60*100) rpm = 100step/s - 0.00133step/s (0.3mm/h(d=10mm))
  //10ms/step - 750*1000ms/step

  if(new_spd == 0){
    TCNT0 = 1;
    //TIMSK = _BV(TOIE0) | _BV(OCIE1A);
    OCR1A = 0xffff;
    wait_cnt = 0xff;
    w = wait_cnt;
    spd = 0;
  } else if(new_spd < 6553){//below 1min
    TCNT1 = 0;
    OCR1A = spd * 10;//~9.76ms = 1.0/(1MHz/1024)
    wait_cnt = 1;
    w = wait_cnt;
    spd = new_spd;
  }else{
    TCNT1 = 0;
    OCR1A = 6553;
    wait_cnt = spd / 655;//1% err, wait_cnt<=100
    w = wait_cnt;
    spd = new_spd;
  }
  return 1;
}


int main(void){
  //high-low
  PORTB = 0x00;
  PORTD = 0x70; // high: PD 456, low: PD 0123

  //in-out direction
  DDRB = 0x01; //
  DDRD = 0x0F; // in: PD 456, out:PD 0123 F



  //interrupt for switch
  TCNT0 = 0;
  TCCR0A = 0;
  TCCR0B = 0b100;// prescaler
  //*1024*1us~1ms * 256
  TIMSK = _BV(TOIE0) | _BV(OCIE1A);
  //OCR1A = 0x000a;//10ms
  //TCNT1 = 0;
  //CTC top:OCR1A, upd:imm, tov1:max = 0100
  TCCR1A = 0;
  TCCR1B = _BV(WGM12) | 0b101;//prescaler1024
  set_spd(1);
  sei();

  while(1){}

  return 0;
}