Go Down

Topic: Arduino chip as Stepper Controller (Read 12 times) previous topic - next topic

kf2qd

#20
Jan 31, 2012, 09:24 pm Last Edit: Jun 01, 2012, 06:18 pm by kf2qd Reason: 1
Got to playing with assembly language - took my code size from 1200 bytes to 86 bytes.

Out of necesity, Arduino adds a lot of overhead to interrupt routines. Saves all the registers and such, but it would take a lot more power to analyze the code and reduce that overhead. Writing in assembler means I had to do the optimizing and I am responsible for what can go wrong...

I am using AVRStudio 4 to write and test the code (has a simulator built in)(even has a disassembler that will load the hex files and list them )
I recommend AVR Studio 4 over 5 as 5 is just to S-L-O-W...

Here's what the code looks like in assembler.
Code: [Select]

.NoList
.INCLUDE "tn2313Adef.inc" ; Header for ATTINY2313A
.List
; ============================================
;   R E G I S T E R   D E F I N I T I O N S
; ============================================
.DEF Conf = R16 ; Multipurpose register
.DEF StepCt = R17
.DEF StepMask = R18
.DEF Direction = R19
.DEF PortBHold = R20
.DEF PortDHold = R21
.DEF PortDMask = R22
.DEF SeqBase = R23
; ============================================
;   R E S E T   A N D   I N T   V E C T O R S
; ============================================
.CSEG
.ORG $0000
rjmp Main ; Reset vector
rjmp Step ; Int vector 1
rjmp Dir ; Int vector 2
reti ; Int vector 3
reti ; Int vector 4
reti ; Int vector 5
reti ; Int vector 6
reti ; Int vector 7
; ============================================
;     I N T E R R U P T   S E R V I C E S
; ============================================
Step: add StepCt,Direction
     and StepCt,StepMask
     mov ZL,SeqBase
 add ZL,StepCt
 Lpm PortBHold,Z
 out PORTB,PortBHold
 reti
Dir:  ldi PortDMask,8
     in  PortDHold,PIND
     and PortDHold,PortDMask
     breq SinNeg
 ldi Direction ,1
     rjmp DirEx
SinNeg:  ldi Direction ,-1
DirEx:reti
; ============================================
;     M A I N    P R O G R A M    I N I T
; ============================================
Main:
; Init stack
ldi Conf, LOW(RAMEND) ; Init LSB stack
out SPL,Conf
; Init Port A
ldi Conf,0 ; Direction Port A
out DDRA,Conf
; Init Port B
ldi Conf,(1<<DDB0)|(1<<DDB1)|(1<<DDB2)|(1<<DDB3) ; Direction Port B
out DDRB,Conf
; [Add all other init routines here]
ldi Conf,(1<<SE)|(0<<ISC00)|(1<<ISC01)|(1<<ISC10)|(0<<ISC11) ; enable sleep
out MCUCR,Conf
ldi StepCt,0
ldi StepMask,7
ldi Direction,1
ldi SeqBase, StepSeq
add SeqBase,SeqBase
sei
; ============================================
;         P R O G R A M    L O O P
; ============================================
Loop:
rjmp loop ; go back to loop

StepSeq: .DB 1,3,2,6,4,12,8,9,0,0
; End of source code


kf2qd

Finally can say I have an ATMel chip - the ATtiny2313 functioning as a stepper driver.
I got it working in Arduino, the assembler version still has some strange behavious (and the assembler version of the code is hareder to troubleshoot in hardware. In the Simulator it works just fine, but in hardware.....

Here's the Arduino version.
By my count it will run in excess of 140RPM  running in Half Step mode when driven by a simple Arduino program.

Code: [Select]
/*
Step & Direction Stepper Driver
Pins 8, 9, 10, 11 are tied to transistors
for each of the motor phases.
Pins 2 is used as interruptfor the steps
and 3 is the Direction.
*/
// the following 3 arrays contain the bit patterns to drive the transistors
// to in turn drive each of the phases of the stepper
int patSimple[] = {
  B0011,B0010, B0100, B1000, B0001, B0010, B0100, B1000};
int patWave[]   = {
  B0011, B0110, B1100, B1001, B0011, B0110, B1100, B1001};
int patHalf[]   = {
  B0001, B0011, B0010, B0110, B0100, B1100, B1000, B1001};
int pinDir = 5;
volatile int ctr;
volatile int dir;

void setup()
{
  DDRB = B1111 ;  // this enables Port B Bits 0 - 3, Arduino I/O 8, 9, 10, 11 as outputs
  pinMode(pinDir, INPUT);
  ctr=0;
  dir = 0;
  attachInterrupt(0, Step, FALLING);  // Depending on the application FALLING might be a better choice.

}

void loop()
{
  // Nothing to see here... 
}

void Step()
{
  if (digitalRead(5))
  {
    ctr++ ;
  }
  else
  {
    ctr-- ;
  }
  ctr = ctr & 7;
  // 2 of the following 3 lines must be commented.
  // PORTB = patsimple[ctr];  // Simple Stepping
  // PORTB = patWave[ctr];    // Wave Stepping
  PORTB = patHalf[ctr];      // Half Stepping



And I was testing it with code that looks like this in my Arduino-
Code: [Select]
int steps;

void setup() {               
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(2, OUTPUT);     
  pinMode(3, OUTPUT);   
  digitalWrite(3,HIGH); 
}

void loop() {
  for (steps=0;steps<400;steps++)
  {
    digitalWrite(2, HIGH);   // set the LED on
    digitalWrite(2, LOW);    // set the LED off
    delay(1);              // wait for a second
  }
}


Still want to crack the assembly code...

sloppyjava

Hi, I am experimenting with the code you posted ( Reply #15 on: January 15, 2012, 05:19:57 PM ) with 4 IRF530's, an Arduino Uno, a small unipolar stepper and solder-less board and It works really well with EMC2 linux.  My goal is to drive a homebrew CNC router table with the above components.  I have very little (NO) experience with port manipulation and am somewhat apprehensive about adding another axis to the code, as I recall reading that I could bugger up the TX RX ports?  does the UNO have enough ports available to control 3 axes? I would still be happy with 2!  In any case, great work on this elegant code so far!

kf2qd

I am using the ATtiny2313 for this application. It has a few extra pins, It turns out I need 1 interrupt pin, 1 input and 4 outputs. I would also like to add 1 more input as an enable  and possibly a Ready output. The problem with trying to run more than one stepper in this application is the Interrupt inputs. Because of priority of interrupts the second interrupt would get missed if it occurred at the time as the first.

Look into some ATtiny2313 chips and use the Arduino as the programmer. That circuit is abut as inexpensive and simple as an Arduino circuit can be. If yuwant more info to use that approach I can point you to the few pieces you need to put together to do that.

sloppyjava

That would be great.  I was wondering about the ability to program with the arduino and swap the IC out to a PCB, so that sounds like it could work for me.  Any resources you can point me to would be greatly appreciated.

Go Up