Arduino stepper motor driver l6470

Hello everyone,

Over the past few days I've been working with the STMicro l6470 microstepping motor driver and attempting to interface it with the atmega328 via the arduino SPI library. So far I have been unsuccessful in getting the driver to respond to commands I send it and I believe the problem is due to my limited experience with SPI and would like some guidance.

Before i get too far here's what I've got so far:
l6470 datasheet

SPI interface:
-communication starts when CS is forced low
-The SDO is latched on the falling edges of the CK
-After each byte transmission the CS input must be raised and be kept high for at least tdisCS
in order to allow the device to decode the received command and put into the shift register
the return value.
-8 bit communication

Arduino Setup:
5v to MCU and to logic lines of l6470
12v to motors
pin10 --> Slave Select
pin11 --> SDI
pin12 --> SDO
pin13 --> CLK

The circuit i'm using is the same as on the datasheet, to keep things simple. And I know that all my power supplies are within specs. I manually set the SS (or cs) pin on setup and then toggle it low before sending the byte commands, however the driver itself does not respond in any fashion to any command I have sent so far. Originally I believed that my problems were stemming from commands that were wanting to have large (bigger than 8bit) registers set like on the run command (which i'll talk about later), but when I tried to use simple single Byte commands I was still failing to get any result.

I've written and re-written the sketch a few different times with no success. Below I've included the code I have most recently used. I should note that on here you see that the CS pin is NOT toggle back high after each byte is sent. I originally set up the code incorrectly because my experience with other SPI devices expected multple bytes to be shifted per command. According to the datasheet this is the incorrect way to communicate with the driver. The code pasted below was specifically for debugging and I feel is the easiest to read version for others. I HAVE set up this exact code with the missing cs pin toggles and get the exact same result . For now just assume that each byte is shifted individually in the code. I also raise and lower CS for receiving bytes.

#include <SPI.h>
int  cs=10; //chip select 

void setup() {
  Serial.begin(9600);                  //setup serial communication for feedback
  SPI.begin();                         //let the SPI library handle mosi, miso, and ck.
  SPI.setBitOrder(MSBFIRST);           //in accordance with datasheet for l6470. MSBFIRST
  pinMode(cs,OUTPUT);
  
  digitalWrite(cs, LOW);               //pull cs low to send command
  SPI.transfer(0xD8);                  //reset pos via byte command
  digitalWrite(cs, HIGH);              //pull it high because datasheet says aftter every byte to pull high
  delay(1);                            //give the l6470 some time to think about what we just sent it.
   
}

void loop(){
  
  //== get sttus byte command ==//
  digitalWrite(cs, LOW);
  SPI.transfer(0xD0); //get status command in hex
  unsigned int n = 1; //set these are variables jus to make sure recieve signal is changing to something else
  unsigned int m = 1;
  n = SPI.transfer(0x00);  //status Most sig byte.
  m = SPI.transfer(0x00);  //status Least sig byte.
  digitalWrite(cs, HIGH);  
  Serial.println(n);      // output status return to see
  Serial.println(m);
  
  //set max_speed register
  digitalWrite(cs, LOW);
  unsigned int maxSpeed = SPI.transfer(0x07);        //initial command byte
  unsigned int maxSpeed1 = SPI.transfer(0x00);       //MAx speed is a 10 bit register. This needs to be shifter twice to fill correct?
  unsigned int maxSpeed2 = SPI.transfer(0x00);
  digitalWrite(cs, HIGH);                            //Toggle back up
  Serial.print("Speed: ");
  Serial.println(maxSpeed);
  Serial.println(maxSpeed1);
  Serial.println(maxSpeed2);
  
  
  digitalWrite(cs, LOW);
  unsigned int elpos = SPI.transfer(0x02);
  unsigned int elpos1 = SPI.transfer(0x02);
  digitalWrite(cs, HIGH);
  Serial.print("elpos: ");
  Serial.println(elpos);
  Serial.println(elpos1);
  
  
  
  //test command
  digitalWrite(cs, LOW);
  SPI.transfer(0xD8); //reset pos
  digitalWrite(cs, HIGH);
  digitalWrite(cs, LOW);
  unsigned int speed = 0;
  SPI.transfer(0x14); //reset pos
  digitalWrite(cs, HIGH);
  
    //test command
  digitalWrite(cs, LOW);
  SPI.transfer(0x51); //Run command
  SPI.transfer(0x00);
  SPI.transfer(0x34);
  SPI.transfer(0xBC);
  digitalWrite(cs, HIGH);
   delay(1000);
   
 // HardHiz
  digitalWrite(cs, LOW);
  SPI.transfer(0xA8); //HIZ STOP
  digitalWrite(cs, HIGH);
  
  delay(1000);
  

}

I"m going to keep playing with the code to see how simple I can make the program. I will post any updates to it as a progress.

Specific questions:
-Am I transferring bytes in the correct format? Or should I define a byte variable first and send that in the SPI.transfer function? or should I convert each byte to decimal or binary?

-certain commands and registers are larger than 8bits and require multiple bytes. I have no bitwise experience with shifting bytes and would like an example of setting the run command. starting on line 61 of the code I I did try send the run command. I believe I have it set up to set the "speed" to 13,500 which should translate to about 20 steps a second. but it still didn't work and the device was never "holding" the motor. page 57 of the datasheet covers the run command structure but i wasn't sure how to send half a byte, and I believe this is where I went wrong. Did i set it up correctly and if not what should the sequence look like?

-The datasheet does not specifically lay out how to receive data that the driver is sending back to the host (the atmega). Based on my past experience with the DeadOn RTC you would shift the command byte and for each byte you were expecting you would then shift a 0x00 byte and the "SPI.transfer(0x00);" function would return the Byte transmitted by the slave. I test this setup first thing in the main loop() function of the above code (line 19) and initially set the variables = to 1. after sending the get status command and using the above described method to receive the byte, i then push it out to serial so i can review the variable which is shown as 0. So i know that the variable is getting changed somehow, but is it changing the way it should? or is my code just wrong, causing me to believe the ic is resetting the value?

Thank you again in advance for any help you can provide.
~Poent

I I hope ou keep at it I too am new to Arduino and like to work with a stepper motor so I a ordering the
l6470 starter kit .

It will take a few days to show up , but will get back with you then.

Hi there!

I've been working on some code for the L6470 chip. It's attached in a ZIP file.

I'd appreciate if you'd give it a shot and see what you think. It's written under v22 and I haven't tried it in 1.0 yet, but I think it'll compile forward without problems.

Mike

dsPin_example.zip (9.03 KB)

This chip sounds very interesting and would be perfect for the project I have in mind. I would love to get some feedback from you guys on how it performed.

Hi,
there is an Arduino Shield using L6470 and they provide an example sketch for it.
It can be found here http://altelectronics.co.uk/shop/arduino/arduino-stepper-motor-shield/prod_84.html
I hope it helps.

Hi All ..
I 'm trying to test the code but i have a question about the pins numbers....
in your code you have not specified the wires for the SPI ...
maybe i have missed something but you do not call nowhere in the code
the MOSI , MISO and SerialClock pin ....
I hope my english is correct enough ....
i'm new with SPI ...

Hi Alban !

The four pins are sufficient :

pin10 --> Slave Select
pin11 --> SDI
pin12 --> SDO
pin13 --> CLK

Best regards

Hi everybody...
I hope that you could hel me
We ran into problems reading ABS_POS on Arduinio Board.. maybe you already know about this problem It seems to be the 8th Bit from the 22 bits Position register is always Low other reset.. All the other functions are working good but of course I don´t be able to read the position values correctly

Is very weird cause ist just the Positon feedback gives wrong values, I get correct values from other Register as spped and Status, etc

In Order to find the solution i´ve tried following:
I tested all the possible solutions (taked from: SparkFun AutoDriver - Stepper Motor Driver (v13) - BOB-13752 - SparkFun Electronics) that other users have suggested with any succes.

I tried to implement new methods of the Autodrive library (https://github.com/sparkfun/L6470-AutoD ... AutoDriver) in the old Arduino code and it has not worked

I Consulted/Posted on the ST microelectronics Forum about my Problem but I could not find a solution (You will see that other custumers experimented the same issue even with the evaluation board EVAL6470H).

Posible solution ideas:
How I could sense the position without the ABS_POS function of the chip?
How could I fix in Arduino, it could sound very crazy but maybe is possible to identify erroneous values ??from the list and change .. but unfortunately I do not know how to identify them ..

I leave a Picture from the Arduino Serial Monitor..
Thanks

Edmakuit, any luck on getting this to work with the Arduino? I've tried changing some of the SPI settings with no difference. Some have mentioned changing the ABS_POS function itself, but I haven't had any luck with that.