ATtiny2313 Unipolar Stepper Controller Driver

Seguendo gli esempi riportati qui → http://letsmakerobots.com/node/23343
e più in generale qui → http://reprap.org/wiki/Stepper_motor_driver
Scopiazzando un po’ il codice da qui → GitHub - TinHead/Valkyrie-CNC-source-code: Reprap based g-code interpreter adapted for my own toy (creato per motori Unipolari) ho creato un driver per il pilotaggio dei motori stepper 28BJY-48 5V

che di solito vengono forniti in abbinata a una scheda che monta un ULN2003.

L’idea è quella di semplificare il pilotaggio permettendo, come nei driver più comuni, di inviare al controller solo il comando di ENABLE, la direzione DIR e il passo STEP.
Poiche tutti i firmware per REPRAP o interpreti G-CODE come GRBL (GitHub - grbl/grbl: An open source, embedded, high performance g-code-parser and CNC milling controller written in optimized C that will run on a straight Arduino) usano questi tre comandi per il controllo degli stepper.

Esempio…

Il cuore del sistema è il microcontrollore ATtiny2313. Devo ancora decidere se mandarlo a 8Mhz interni o spingermi fino a 20Mhz con quarzo esterno.
Inoltre devo ancora realizzare il PBC.

Allego qui il codice:

// Step/Dir/Enable driver code

// ATMEL ATTINY2313
//
//                   +-\/-+
// RESET(D 17) PA2  1|    |29  VCC
// RX   (D  0) PD0  2|    |19  PB7 (D  16)
// TX   (D  1) PD1  3|    |18  PB6 (D  15)
// XTL2 (D  2) PA1  4|    |17  PB5 (D  14)
// XTL1 (D  3) PA0  5|    |16  PB4 (D  13)*
// INT0 (D  4) PD2  6|    |15  PB3 (D  12)*
// INT1 (D  5) PD3  7|    |14  PB2 (D  11)*
//      (D  6) PD4  8|    |13  PB1 (D  10)
//     *(D  7) PD5  9|    |12  PB0 (D  9)
//             GND 10|    |11  PD6 (D  8)
//                   +----+
//
// * indicates PWM port

// Control INPUTS
#define INPUTPORT PORTD
#define EN_PIN PD0
#define DIR_PIN PD1
#define STEP_PIN PD2

#define LEDPORT PORTD
#define DBG_LED PD6
#define STP_LED PD4

// reference voltage pins */
#define	REF1  PB4
#define	REF2  PB3

//inhibit pins
#define STPPORT PORTB
#define	IN0_1  PB7	// Orange
#define	IN1_1  PB6	// Yellow  
#define	IN0_2  PB1	// Pink
#define	IN1_2  PB0	// Blue

/* Helper macros */
#define read_pin(port, pin) (port & (1<<pin))
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)

const uint8_t step_table[8][4] = {
  {1, 0, 0, 0},
  {1, 1, 0, 0},
  {0, 1, 0, 0},
  {0, 1, 1, 0},
  {0, 0, 1, 0},
  {0, 0, 1, 1},
  {0, 0, 0, 1},
  {1, 0, 0, 1}
};

int32_t step_number = 0;
uint8_t enabled = 0;

/* has to be volatile for interrupt use*/
volatile uint8_t step_cmd = 0;

void setup(void)
{
  // init stuff
  init_ports();
  init_drivers();
  init_interrupts();

  bitClear(LEDPORT, STP_LED);
  //blink led to see init
  bitSet(LEDPORT, DBG_LED);
  delay(200);
  bitClear(LEDPORT, DBG_LED);
}


// main loop
void loop(void)
{
  if (!read_pin(INPUTPORT, EN_PIN))
  {
    if (enabled == 0)
    {
      enable();
      enabled = 1;
    }
  }
  else
  {
    disable();
    enabled = 0;
  }

  if (step_cmd)
  {
    bitSet(LEDPORT, STP_LED);
    step(read_pin(INPUTPORT, DIR_PIN));
    step_cmd = 0;
    bitClear(LEDPORT, STP_LED);
  }
}  // End Loop


void init_ports(void)
{
  // setup input/output ports

  // initialize inputs
  set_input(DDRD, EN_PIN);
  set_input(DDRD, DIR_PIN);
  set_input(DDRD, STEP_PIN);

  // initialize outputs
  set_output(DDRB, REF1);
  set_output(DDRB, REF2);
  set_output(DDRB, IN0_1);
  set_output(DDRB, IN0_2);
  set_output(DDRB, IN1_1);
  set_output(DDRB, IN1_2);

  //debug led
  set_output(DDRD, DBG_LED);
  set_output(DDRD, STP_LED);
}


void init_interrupts(void)
{
  //setup interrupts for the step pin
  cli();
  MCUCR |= (1 << ISC01);
  GIMSK |= (1 << INT0);
  sei();
}

/* Interrupt handlers*/
ISR(INT0_vect)
{
  if (step_cmd == 0)
  {
    step_cmd = 1;
  }
}


void init_drivers(void)
{
  //setup initial driver state
  // setup inhibit pins disabled
  bitClear(STPPORT, IN0_1);
  bitClear(STPPORT, IN1_1);
  bitClear(STPPORT, IN0_2);
  bitClear(STPPORT, IN1_2);

  // enable reference voltage pins
  bitSet(LEDPORT, REF1);
  bitSet(LEDPORT, REF2);

  //enble pull-up on the step pin
  bitSet(INPUTPORT, EN_PIN);
  bitSet(INPUTPORT, DIR_PIN);
  bitSet(INPUTPORT, STEP_PIN);
}


/* control functions*/
void enable(void)
{
  // enable drivers - sets the inhibit pins to max power
  bitClear(STPPORT, IN0_1);
  bitClear(STPPORT, IN1_1);
  bitClear(STPPORT, IN0_2);
  bitClear(STPPORT, IN1_2);
  bitSet(LEDPORT, DBG_LED);
}

void disable(void)
{
  // disable drivers - sets the inhibit pins to high = off
  bitSet(STPPORT, IN0_1);
  bitSet(STPPORT, IN1_1);
  bitSet(STPPORT, IN0_2);
  bitSet(STPPORT, IN1_2);
  bitClear(LEDPORT, DBG_LED);
}

void step_micro(int32_t next_step)
{
  //step using the values in the array for the step
  uint8_t step = next_step % 8;
  bitWrite(STPPORT, IN0_1, step_table[step][0]);
  bitWrite(STPPORT, IN1_1, step_table[step][1]);
  bitWrite(STPPORT, IN0_2, step_table[step][2]);
  bitWrite(STPPORT, IN1_2, step_table[step][3]);
}

void step(uint8_t direction)
{
  // decrement the number of steps, moving one step each time:
  if (direction == 1)
  {
    step_number++;
  }
  else
  {
    step_number--;
  }
  step_micro (step_number);
}

con due domande.

E’ più veloce inserire uno switch case come nella libreria stepper o come ho fatto io con 4 scritture prelevate da un array?
Mi conviene proseguire con il tiny2313 o passare all’ATtiny84?

Pubblicherò più avanti foto della breadboard e un video di funzionamento.

E' proprio bruttino il codice, con SetBit cambi un pin alla volta e nel tempo di attesa il motore "soffre" nel senso che non ti darà le massime prestazioni. Cambia utilizzando le porte tutti i bit in un colpo solo

Ciao

Quindi switch case e

STPPORT = 0b00001001;

per esempio. E cosi per otto volte.

Però è meno configurabile come porte? A quel punto tolgo tutti i #define e fisso ingressi e uscite del micro.

p.s. In effetti facendo un PCB avrei comunque i piedini non più configurabili. Stanotte ci lavoro.

STPPORT = 0x....

devi chiamarlo una sola volta col valore giusto che ti setta tutte le porte in un colpo e non chiamarlo 8 volte altrimenti sei punto a capo..

Penso flz intenda invece di questo:

void step_micro(int32_t next_step)
{ //step using the values in the array for the step
  uint8_t step = next_step % 8;
  bitWrite(STPPORT, IN0_1, step_table[step][0]);
  bitWrite(STPPORT, IN1_1, step_table[step][1]);
  bitWrite(STPPORT, IN0_2, step_table[step][2]);
  bitWrite(STPPORT, IN1_2, step_table[step][3]);
}

Passi da byte temporaneo e poi spari in registro, occhio ai bit che non vuoi settare però

void step_micro(int32_t next_step)
{ //step using the values in the array for the step
  uint8_t step = next_step % 8;
  byte tmp=STPPORT;         // leggi valore bit registro
  // cambio solo quelli voluti
  bitWrite(tmp, IN0_1, step_table[step][0]);
  bitWrite(tmp, IN1_1, step_table[step][1]);
  bitWrite(tmp, IN0_2, step_table[step][2]);
  bitWrite(tmp, IN1_2, step_table[step][3]);
  STPPORT= tmp;   // risparo il registro
}

flz47655: STPPORT = 0x....

devi chiamarlo una sola volta col valore giusto che ti setta tutte le porte in un colpo e non chiamarlo 8 volte altrimenti sei punto a capo..

Ovvio...

void step_micro(int32_t next_step)
{ //step using the values in the array for the step
  uint8_t step = next_step % 8;
  switch(step){
      case 0:
          STPPORT = 0b00001000;
          break;
      case 1:
          STPPORT = 0b00001100;
          break;
      case 2:
          STPPORT = 0b00000100;
          break;
      case 3:
          STPPORT = 0b00000110;
          break;
      case 4:
          STPPORT = 0b00000010;
          break;
      case 5:
          STPPORT = 0b00000011;
          break;
      case 6:
          STPPORT = 0b00000001;
          break;
      case 7:
          STPPORT = 0b00001001;
          break;
      }
}
STPPORT = 0b00001000;

Però cosi mi azzeri anche i pin che non usi per lo stepper. Oppure non importa, tanto è un pcb dedicato ?

A me piace compattare, io voto per lo switch:

void step_micro(int32_t next_step)
{ //step using the values in the array for the step
  uint8_t step = next_step % 8;
  switch(step) {
      case 0: STPPORT = 0b00001000; break;
      case 1: STPPORT = 0b00001100; break;
      case 2: STPPORT = 0b00000100; break;
  ...
  }
}

Al momento non importa. Se migro su ATtiny24, che ha meno pin, allora dovrò settare solo i pin dedicati.

Il codice originale compilato con il core tiny di CodingBadly (0020-0150) su IDE 1.5.6-r2 occupa 1024byte (50%) Adesso con le modifiche credo che occupi anche meno.

Lo sto ancora testando…

// Step/Dir/Enable driver code

// ATMEL ATTINY2313
//
//                   +-\/-+
// RESET(D 17) PA2  1|    |29  VCC
// RX   (D  0) PD0  2|    |19  PB7 (D  16)
// TX   (D  1) PD1  3|    |18  PB6 (D  15)
// XTL2 (D  2) PA1  4|    |17  PB5 (D  14)
// XTL1 (D  3) PA0  5|    |16  PB4 (D  13)*
// INT0 (D  4) PD2  6|    |15  PB3 (D  12)*
// INT1 (D  5) PD3  7|    |14  PB2 (D  11)*
//      (D  6) PD4  8|    |13  PB1 (D  10)
//     *(D  7) PD5  9|    |12  PB0 (D  9)
//             GND 10|    |11  PD6 (D  8)
//                   +----+
//
// * indicates PWM port

// Control INPUTS
#define INPUTPORT PORTD
#define EN_PIN PD4
#define DIR_PIN PD3
#define STEP_PIN PD2

#define LEDPORT PORTD
#define DBG_LED PD5
#define STP_LED PD6

//inhibit pins
#define STPPORT PORTB
#define	IN0_1  PB3	// Orange
#define	IN1_1  PB2	// Yellow  
#define	IN0_2  PB1	// Pink
#define	IN1_2  PB0	// Blue

/* Helper macros */
#define read_pin(port, pin) (port & (1<<pin))
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)

int32_t step_number = 0;
uint8_t enabled = 0;

/* has to be volatile for interrupt use*/
volatile uint8_t step_cmd = 0;

void setup(void)
{
  // init stuff
  init_ports();
  init_drivers();
  init_interrupts();

  bitClear(LEDPORT, STP_LED);
  //blink led to see init
  bitSet(LEDPORT, DBG_LED);
  delay(200);
  bitClear(LEDPORT, DBG_LED);
}


// main loop
void loop(void)
{
  if (!read_pin(INPUTPORT, EN_PIN))
  {
    if (enabled == 0)
    {
      enable();
      enabled = 1;
    }
  }
  else
  {
    disable();
    enabled = 0;
  }

  if (step_cmd)
  {
    bitSet(LEDPORT, STP_LED);
    step(read_pin(INPUTPORT, DIR_PIN));
    step_cmd = 0;
    bitClear(LEDPORT, STP_LED);
  }
}  // End Loop


void init_ports(void)
{
  // setup input/output ports

  // initialize inputs
  set_input(DDRD, EN_PIN);
  set_input(DDRD, DIR_PIN);
  set_input(DDRD, STEP_PIN);

  // initialize outputs
  set_output(DDRB, IN0_1);
  set_output(DDRB, IN0_2);
  set_output(DDRB, IN1_1);
  set_output(DDRB, IN1_2);

  //debug led
  set_output(DDRD, DBG_LED);
  set_output(DDRD, STP_LED);
}


void init_interrupts(void)
{
  //setup interrupts for the step pin
  cli();
  MCUCR |= (1 << ISC01);
  GIMSK |= (1 << INT0);
  sei();
}

/* Interrupt handlers*/
ISR(INT0_vect)
{
  if (step_cmd == 0)
  {
    step_cmd = 1;
  }
}


void init_drivers(void)
{
  //setup initial driver state
  // setup inhibit pins disabled
  bitClear(STPPORT, IN0_1);
  bitClear(STPPORT, IN1_1);
  bitClear(STPPORT, IN0_2);
  bitClear(STPPORT, IN1_2);

  //enble pull-up on the step pin
  bitSet(INPUTPORT, EN_PIN);
  bitSet(INPUTPORT, DIR_PIN);
  bitSet(INPUTPORT, STEP_PIN);
}


/* control functions*/
void enable(void)
{
  // enable drivers - sets the inhibit pins to max power
  bitClear(STPPORT, IN0_1);
  bitClear(STPPORT, IN1_1);
  bitClear(STPPORT, IN0_2);
  bitClear(STPPORT, IN1_2);
  bitSet(LEDPORT, DBG_LED);
}

void disable(void)
{
  // disable drivers - sets the inhibit pins to high = off
  bitSet(STPPORT, IN0_1);
  bitSet(STPPORT, IN1_1);
  bitSet(STPPORT, IN0_2);
  bitSet(STPPORT, IN1_2);
  bitClear(LEDPORT, DBG_LED);
}

void step_micro(int32_t next_step)
{ //step using the values in the array for the step
  uint8_t step = next_step % 8;
  switch (step) {
    case 0:
      STPPORT = 0b00001000;
      break;
    case 1:
      STPPORT = 0b00001100;
      break;
    case 2:
      STPPORT = 0b00000100;
      break;
    case 3:
      STPPORT = 0b00000110;
      break;
    case 4:
      STPPORT = 0b00000010;
      break;
    case 5:
      STPPORT = 0b00000011;
      break;
    case 6:
      STPPORT = 0b00000001;
      break;
    case 7:
      STPPORT = 0b00001001;
      break;
  }
}

void step(uint8_t direction)
{
  // decrement the number of steps, moving one step each time:
  if (direction == 1)
  {
    step_number++;
  }
  else
  {
    step_number--;
  }
  step_micro (step_number);
}

Allego anche il PCB

stepper controller board.sch (898 KB)

stepper controller board.brd (123 KB)

Uffff. Non riesco a cambiare velocità di elaborazione; mi rimane a 1Mhz.. ]:D ]:D

Se provo a modificare i fuse caricando un bootloader VUOTO mi scrive:

Arduino:1.5.5 (Windows 7), Scheda:"ATtiny x313, ATtiny2313 @ 8 MHz"

***failed;  
avrdude: verification error, first mismatch at byte 0x0000
         0x3f != 0xff
avrdude: verification error; content mismatch

Ho provato con la Arduino Leonardo collegando lo stepper ai pin A0, A1, A2, e A3.
Ho scoperto che il motore gira. :grin: (si tratta di un mini stepper 28BJY48-5V)
Il motore ha 2048 passi per completare un giro e col microstepping (messo passo) ce ne voglio 4096.

Per farlo funzionare tra un passo e l’altro ci vuole un intervallo di 2 millisecondi, con mezzo passo 1.
Senza delay, o con delay inferiori, tipo delayMicroseconds(800) al posto di delay(1), non funziona (non gira)

Ecco lo sketch che ho provato.
Basta aprire la seriale e scrivere il numero di passi

#define STPPORT PORTF
#define	IN1  PORTF4	// Orange
#define	IN2  PORTF5	// Yellow  
#define	IN3  PORTF6	// Pink
#define	IN4  PORTF7	// Blue
long step_number = 0;

void setup() {
  DDRF = DDRF | B11110000;

  // initialize the serial port:
  Serial.begin(9600);
  while(!Serial);
  // delay(1000);
}

void loop() {
  Serial.flush();
  delay(500);
  Serial.println("Insert step number...");


  while (Serial.available() == 0);
  int steptogo = Serial.parseInt();

  MyStepper(steptogo);

  // SPEGNE IL MOTORE
  digitalWrite(A0, LOW);
  digitalWrite(A1, LOW);
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
}


void MyStepper(int steps_to_move) {
  int steps_left = abs(steps_to_move);

  if (steps_to_move > 0)
    while (steps_left > 0) {
      step(1);
      steps_left--;
    }

  if (steps_to_move < 0)
    while (steps_left > 0) {
      step(0);
      steps_left--;
    }
}


void step(byte dir)
{
  if (dir == 1)
  {
    step_number++;
  }
  else
  {
    step_number--;
  }
  step_micro4(step_number);
  // step_micro8(step_number);
}


void step_micro8(int32_t next_step)
{ //step using the values in the array for the step
  byte mystep = next_step % 8;
  //Serial.print("MyStep: " );
  //Serial.println(mystep);
  switch (mystep) {
  case 0:
    // STPPORT = STPPORT | (1<<IN1) & ~(1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
    STPPORT = 0b10000000;
    break;
  case 1:
    // STPPORT = STPPORT | (1<<IN1) | (1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
    STPPORT = 0b11000000;
    break;
  case 2:
    // STPPORT = STPPORT & ~(1<<IN1) | (1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
    STPPORT = 0b01000000;
    break;
  case 3:
    //   STPPORT = STPPORT & ~(1<<IN1) | (1<<IN2) | (1<<IN3) & ~(1<<IN4);
    STPPORT = 0b01100000;
    break;
  case 4:
    //  STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) | (1<<IN3) & ~(1<<IN4);
    STPPORT = 0b00100000;
    break;
  case 5:
    // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) | (1<<IN3) | (1<<IN4);
    STPPORT = 0b00110000;
    break;
  case 6:
    // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) & ~(1<<IN3) | (1<<IN4);
    STPPORT = 0b00010000;
    break;
  case 7:
    //  STPPORT = STPPORT | (1<<IN1) & ~(1<<IN2) & ~(1<<IN3) | (1<<IN4);
    STPPORT = 0b10010000;
    break;
  }
  delay(1);
}


void step_micro4(int32_t next_step)
{ //step using the values in the array for the step
  byte mystep = next_step % 4;
  //Serial.print("MyStep: " );
  //Serial.println(mystep);
  switch (mystep) {
  case 0:
    // STPPORT = STPPORT | (1<<IN1) & ~(1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
    STPPORT = 0b10000000;
    break;
  case 1:
    // STPPORT = STPPORT & ~(1<<IN1) | (1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
    STPPORT = 0b01000000;
    break;
  case 2:
    //  STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) | (1<<IN3) & ~(1<<IN4);
    STPPORT = 0b00100000;
    break;
  case 3:
    // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) & ~(1<<IN3) | (1<<IN4);
    STPPORT = 0b00010000;
    break;

  }
  delay(2);
}

PaoloP: E' più veloce inserire uno switch case come nella libreria stepper o come ho fatto io con 4 scritture prelevate da un array?

Come già ti hanno consigliato, fai un'assegnazione con una maschera di bit.

Mi conviene proseguire con il tiny2313 o passare all'ATtiny84?

Dipende. Se userai la seriale forse è meglio restare sul Tiny, che ce l'ha in HW. Se il tuo programma crescerà molto, forse il Tiny84 potrebbe risultarti più comodo nel caso vorresti aggiungere delle caratteristiche al tuo programma. 2K li riempi velocemente usando il core di Arduino.

Leo, il mio è un controller stupido, 800byte sono anche troppi. Arriva un impulso e avanza di un passo, fine.

Il problema è che a parte il 2313, il mini stepper ha dei grossi limiti. Inutile scrivere il registro alla velocità della luce se poi devo mettere una pausa di 2 millisecondi. :sweat_smile: Userò lo switch case con 4 scritture per ogni caso.

Ecco lo sketch funzionante con la Leonardo

#define STPPORT PORTF
#define	IN1  PORTF4	// Orange
#define	IN2  PORTF5	// Yellow  
#define	IN3  PORTF6	// Pink
#define	IN4  PORTF7	// Blue
unsigned int step_number = 0;

void setup() {
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  // DDRF = DDRF | B11110000;

  Serial.begin(9600);
}

void loop() {
  Serial.flush();
  delay(500);
  Serial.println("Insert step number...");


  while (Serial.available() == 0);
  int steptogo = Serial.parseInt();

  MyStepper(steptogo);

  // SPEGNE IL MOTORE
  digitalWrite(A0, LOW);
  digitalWrite(A1, LOW);
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
}


void MyStepper(int steps_to_move) {
  long steps_left = abs(steps_to_move);

  if (steps_to_move > 0)
    while (steps_left > 0) {
      step(1);
      delay(1);
      steps_left--;
    }

  if (steps_to_move < 0)
    while (steps_left > 0) {
      step(0);
      delay(1);
      steps_left--;
    }
}


void step(byte dir)
{
  if (dir == 1)
  {
    step_number++;
  }
  else
  {
    step_number--;
  }
  // Serial.println(step_number);
  // step_micro4(step_number);
  step_micro8(step_number);
}


void step_micro8(unsigned int next_step)
{ //step using the values in the array for the step
  byte mystep = next_step % 8;
  // Serial.print("MyStep: " );
  // Serial.println(mystep);
  switch (mystep) {
    case 0:
      bitWrite(STPPORT, IN1, 1);
      bitWrite(STPPORT, IN2, 0);
      bitWrite(STPPORT, IN3, 0);
      bitWrite(STPPORT, IN4, 0);
      // STPPORT = STPPORT | (1<<IN1) & ~(1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
      STPPORT = 0b10000000;
      break;
    case 1:
      bitWrite(STPPORT, IN1, 1);
      bitWrite(STPPORT, IN2, 1);
      bitWrite(STPPORT, IN3, 0);
      bitWrite(STPPORT, IN4, 0);
      // STPPORT = STPPORT | (1<<IN1) | (1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
      // STPPORT = 0b11000000;
      break;
    case 2:
      bitWrite(STPPORT, IN1, 0);
      bitWrite(STPPORT, IN2, 1);
      bitWrite(STPPORT, IN3, 0);
      bitWrite(STPPORT, IN4, 0);
      // STPPORT = STPPORT & ~(1<<IN1) | (1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
      // STPPORT = 0b01000000;
      break;
    case 3:
      bitWrite(STPPORT, IN1, 0);
      bitWrite(STPPORT, IN2, 1);
      bitWrite(STPPORT, IN3, 1);
      bitWrite(STPPORT, IN4, 0);
      // STPPORT = STPPORT & ~(1<<IN1) | (1<<IN2) | (1<<IN3) & ~(1<<IN4);
      // STPPORT = 0b01100000;
      break;
    case 4:
      bitWrite(STPPORT, IN1, 0);
      bitWrite(STPPORT, IN2, 0);
      bitWrite(STPPORT, IN3, 1);
      bitWrite(STPPORT, IN4, 0);
      // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) | (1<<IN3) & ~(1<<IN4);
      // STPPORT = 0b00100000;
      break;
    case 5:
      bitWrite(STPPORT, IN1, 0);
      bitWrite(STPPORT, IN2, 0);
      bitWrite(STPPORT, IN3, 1);
      bitWrite(STPPORT, IN4, 1);
      // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) | (1<<IN3) | (1<<IN4);
      // STPPORT = 0b00110000;
      break;
    case 6:
      bitWrite(STPPORT, IN1, 0);
      bitWrite(STPPORT, IN2, 0);
      bitWrite(STPPORT, IN3, 0);
      bitWrite(STPPORT, IN4, 1);
      // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) & ~(1<<IN3) | (1<<IN4);
      // STPPORT = 0b00010000;
      break;
    case 7:
      bitWrite(STPPORT, IN1, 1);
      bitWrite(STPPORT, IN2, 0);
      bitWrite(STPPORT, IN3, 0);
      bitWrite(STPPORT, IN4, 1);
      // STPPORT = STPPORT | (1<<IN1) & ~(1<<IN2) & ~(1<<IN3) | (1<<IN4);
      // STPPORT = 0b10010000;
      break;
  }
}


void step_micro4(unsigned int next_step)
{ //step using the values in the array for the step
  byte mystep = next_step % 4;
  // Serial.print("MyStep: " );
  // Serial.println(mystep);
  switch (mystep) {
    case 0:
      bitWrite(STPPORT, IN1, 0);
      bitWrite(STPPORT, IN2, 0);
      bitWrite(STPPORT, IN3, 0);
      bitWrite(STPPORT, IN4, 1);
      // STPPORT = STPPORT | (1<<IN1) & ~(1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
      // STPPORT = 0b10000000;
      break;
    case 1:
      bitWrite(STPPORT, IN1, 0);
      bitWrite(STPPORT, IN2, 0);
      bitWrite(STPPORT, IN3, 1);
      bitWrite(STPPORT, IN4, 0);
      // STPPORT = STPPORT & ~(1<<IN1) | (1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
      //STPPORT = 0b01000000;
      break;
    case 2:
      bitWrite(STPPORT, IN1, 0);
      bitWrite(STPPORT, IN2, 1);
      bitWrite(STPPORT, IN3, 0);
      bitWrite(STPPORT, IN4, 0);
      //  STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) | (1<<IN3) & ~(1<<IN4);
      // STPPORT = 0b00100000;
      break;
    case 3:
      bitWrite(STPPORT, IN1, 1);
      bitWrite(STPPORT, IN2, 0);
      bitWrite(STPPORT, IN3, 0);
      bitWrite(STPPORT, IN4, 0);
      // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) & ~(1<<IN3) | (1<<IN4);
      //STPPORT = 0b00010000;
      break;

  }
}

Il delay(1) è obbligatorio.
La velocità massima dello stepper, 4096 step a giro, è di circa 15 rpm.

Tanto ho fatto… per poi tornare indietro.
Lo stepper è talmente lento che anche con il digitalWrite funziona benissimo. Sempre a max 15 rpm ovvio, il delay(1) non si può togliere o ridurre.

Codice testato su Arduino Leonardo.

// #define STPPORT PORTF
// #define	IN1  PORTF4	// Orange
// #define	IN2  PORTF5	// Yellow  
// #define	IN3  PORTF6	// Pink
// #define	IN4  PORTF7	// Blue

const byte motor_pin_1 = A0;
const byte motor_pin_2 = A1;
const byte motor_pin_3 = A2;
const byte motor_pin_4 = A3;

unsigned int step_number = 0;

void setup() {
  pinMode(motor_pin_1, OUTPUT);
  pinMode(motor_pin_2, OUTPUT);
  pinMode(motor_pin_3, OUTPUT);
  pinMode(motor_pin_4, OUTPUT);
  // DDRF = DDRF | B11110000;

  Serial.begin(9600);
}

void loop() {
  Serial.flush();
  delay(500);
  Serial.println("Insert step number...");


  while (Serial.available() == 0);
  int steptogo = Serial.parseInt();

  MyStepper(steptogo);

  // SPEGNE IL MOTORE
  digitalWrite(motor_pin_1, LOW);
  digitalWrite(motor_pin_2, LOW);
  digitalWrite(motor_pin_3, LOW);
  digitalWrite(motor_pin_4, LOW);
}


void MyStepper(int steps_to_move) {
  long steps_left = abs(steps_to_move);

  if (steps_to_move > 0)
    while (steps_left > 0) {
      step(1);
      delay(1);
      steps_left--;
    }

  if (steps_to_move < 0)
    while (steps_left > 0) {
      step(0);
      delay(1);
      steps_left--;
    }
}


void step(byte dir)
{
  if (dir == 1)
  {
    step_number++;
  }
  else
  {
    step_number--;
  }
  // Serial.println(step_number);
  // step_micro4(step_number);
  step_micro8dw(step_number);
}

/*
void step_micro8(unsigned int next_step)
 { //step using the values in the array for the step
 byte mystep = next_step % 8;
 // Serial.print("MyStep: " );
 // Serial.println(mystep);
 switch (mystep) {
 case 0:
 bitWrite(STPPORT, IN1, 1);
 bitWrite(STPPORT, IN2, 0);
 bitWrite(STPPORT, IN3, 0);
 bitWrite(STPPORT, IN4, 0);
 // STPPORT = STPPORT | (1<<IN1) & ~(1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
 STPPORT = 0b10000000;
 break;
 case 1:
 bitWrite(STPPORT, IN1, 1);
 bitWrite(STPPORT, IN2, 1);
 bitWrite(STPPORT, IN3, 0);
 bitWrite(STPPORT, IN4, 0);
 // STPPORT = STPPORT | (1<<IN1) | (1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
 // STPPORT = 0b11000000;
 break;
 case 2:
 bitWrite(STPPORT, IN1, 0);
 bitWrite(STPPORT, IN2, 1);
 bitWrite(STPPORT, IN3, 0);
 bitWrite(STPPORT, IN4, 0);
 // STPPORT = STPPORT & ~(1<<IN1) | (1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
 // STPPORT = 0b01000000;
 break;
 case 3:
 bitWrite(STPPORT, IN1, 0);
 bitWrite(STPPORT, IN2, 1);
 bitWrite(STPPORT, IN3, 1);
 bitWrite(STPPORT, IN4, 0);
 // STPPORT = STPPORT & ~(1<<IN1) | (1<<IN2) | (1<<IN3) & ~(1<<IN4);
 // STPPORT = 0b01100000;
 break;
 case 4:
 bitWrite(STPPORT, IN1, 0);
 bitWrite(STPPORT, IN2, 0);
 bitWrite(STPPORT, IN3, 1);
 bitWrite(STPPORT, IN4, 0);
 // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) | (1<<IN3) & ~(1<<IN4);
 // STPPORT = 0b00100000;
 break;
 case 5:
 bitWrite(STPPORT, IN1, 0);
 bitWrite(STPPORT, IN2, 0);
 bitWrite(STPPORT, IN3, 1);
 bitWrite(STPPORT, IN4, 1);
 // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) | (1<<IN3) | (1<<IN4);
 // STPPORT = 0b00110000;
 break;
 case 6:
 bitWrite(STPPORT, IN1, 0);
 bitWrite(STPPORT, IN2, 0);
 bitWrite(STPPORT, IN3, 0);
 bitWrite(STPPORT, IN4, 1);
 // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) & ~(1<<IN3) | (1<<IN4);
 // STPPORT = 0b00010000;
 break;
 case 7:
 bitWrite(STPPORT, IN1, 1);
 bitWrite(STPPORT, IN2, 0);
 bitWrite(STPPORT, IN3, 0);
 bitWrite(STPPORT, IN4, 1);
 // STPPORT = STPPORT | (1<<IN1) & ~(1<<IN2) & ~(1<<IN3) | (1<<IN4);
 // STPPORT = 0b10010000;
 break;
 }
 }
 */

/*
void step_micro4(unsigned int next_step)
 { //step using the values in the array for the step
 byte mystep = next_step % 4;
 // Serial.print("MyStep: " );
 // Serial.println(mystep);
 switch (mystep) {
 case 0:
 bitWrite(STPPORT, IN1, 0);
 bitWrite(STPPORT, IN2, 0);
 bitWrite(STPPORT, IN3, 0);
 bitWrite(STPPORT, IN4, 1);
 // STPPORT = STPPORT | (1<<IN1) & ~(1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
 // STPPORT = 0b10000000;
 break;
 case 1:
 bitWrite(STPPORT, IN1, 0);
 bitWrite(STPPORT, IN2, 0);
 bitWrite(STPPORT, IN3, 1);
 bitWrite(STPPORT, IN4, 0);
 // STPPORT = STPPORT & ~(1<<IN1) | (1<<IN2) & ~(1<<IN3) & ~(1<<IN4);
 //STPPORT = 0b01000000;
 break;
 case 2:
 bitWrite(STPPORT, IN1, 0);
 bitWrite(STPPORT, IN2, 1);
 bitWrite(STPPORT, IN3, 0);
 bitWrite(STPPORT, IN4, 0);
 //  STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) | (1<<IN3) & ~(1<<IN4);
 // STPPORT = 0b00100000;
 break;
 case 3:
 bitWrite(STPPORT, IN1, 1);
 bitWrite(STPPORT, IN2, 0);
 bitWrite(STPPORT, IN3, 0);
 bitWrite(STPPORT, IN4, 0);
 // STPPORT = STPPORT & ~(1<<IN1) & ~(1<<IN2) & ~(1<<IN3) | (1<<IN4);
 //STPPORT = 0b00010000;
 break;
 
 }
 }
 */


void step_micro8dw(unsigned int next_step)
{ //step using the values in the array for the step
  byte mystep = next_step % 8;
  // Serial.print("MyStep: " );
  // Serial.println(mystep);
  switch (mystep) {
  case 0:    // 1000
    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, LOW);
    break;
  case 1:    // 1100
    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, LOW);
    break;
  case 2:    //0100
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, LOW);
    break;
  case 3:    //0110
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, LOW);
    break;
  case 4:    // 0010
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, LOW);
    break;
  case 5:    // 0011
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, HIGH);
    break;
  case 6:    //0001
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, HIGH);
    break;
  case 7:    //1001
    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, HIGH);
    break;
  }
}

Adesso torno al 2313… vediamo se riesco a farlo andare prima a 8 e poi a 20 Mhz. (ma servirà?).

velocità massima dello stepper, 4096 step a giro, è di circa 15 rpm.

4096 step a giro? Ma stiamo scherzando? Quelli buoni arrivano a 200 step / giro, quello sarà da molti meno. 15 RPM è lentissimo, c'è qualcosa che non va evidentemente..

PaoloP: Leo, il mio è un controller stupido, 800byte sono anche troppi.

Ma la seriale ti serve oppure no? La usai solo per test oppure hai effettivamente bisogno di passargli un numero? Il tuo codice, ad esempio, non compila per 2 motivi: - sul core Tiny non hai il metodo parseInt; - anche sostituendolo per la prova di compilaziona con un semplice read(), la compilazione va in errore perché il codice è 2700 byte e passa. Troppa roba. Considera anche anche le digitalWrite occupano flash, ecco perché ti consigliavo di usare la scrittura diretta sulle porte per risparmiare spazio.

Il programma l'ho testato su ARDUINO LEONARDO. Al momento ho interrotto lo sviluppo per il tiny. E' per provare il motore. Passo via seriale il numero di passi positivi o negativi e lui si muove.

Lo stepper è il 28BJY-48

Ha 64 passi. Diventano 2048 o 4096 (con mezzi passi) a causa del riduttore.

La velocità massima al mozzo, non del motore interno, è di 15 rpm. Più veloce non và. Quella del motore interno dovrebbe essere di 480 rpm.

--> http://robocraft.ru/files/datasheet/28BYJ-48.pdf

Avevi scritto 28BJT-48 5V all'inizio e venivano fuori solo transistor BJT ]:D

Se ha un riduttore allora va bene, 480 RPM per il passo passo sono un numero verosimile, con la riduzione diventano 7.5 RPM o 15 RPM in base al controllo che applichi.

Perché non provi a controllarlo in corrente adesso che ci hai smanettato?

flz47655: Perché non provi a controllarlo in corrente adesso che ci hai smanettato?

What's Forfora? :~