Seguendo gli esempi riportati qui --> http://letsmakerobots.com/node/23343
e più in generale qui --> Stepper motor driver - RepRap
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.