Stepper motor library

Hi there,
I have just added into github a library that can be used with the Arduino Uno Rev3 and X-NUCLEO-IHM01A1 stepper motor shields.

It allows to drive up to three stepper motors provided to have one X-NUCLEO-IHM01A1 shield by motor.

The github repository is here:

You will find some sketch examples for different configurations (one, two or three motors...).

The library has the following features:

  • Uno and X-NUCLEO-IHM01A1 shields configuration (GPIOs, PWM s, IRQs...)
  • Speed profile configuration (acceleration, deceleration, ...)
  • Motion commands (move, goto,...)
  • Alarms reporting (over current, over temperature,...)
  • Microstepping handling (up to 1/16)
  • Daisy chaining via SPI to handle up to three stepper motors
  • Read, write of the motor driver chip (L6474) registers

More details are also provided in the readme.md of the repository.

Michel_f:
I have just added into github a library t

It would be much more convenient if you just add the library as an attachment to a forum post.

...R

Here it is!
The attached zip contains:

  • the library in folder: \libraries\L6474
  • 4 sketches in their respective folder:
  • L6474SketchFor1MotorShield.ino: examples of driving one stepper motor in configuration with 1 X-NUCLEO-IHM01A1 shield
  • L6474SketchFor2MotorShields.ino: examples of driving two stepper motors in in configuration with 2 X-NUCLEO-IHM01A1 shields
  • L6474SketchFor3MotorsShields.ino: examples of driving three stepper motors in configuration with 3 X-NUCLEO-IHM01A1 shields
  • L6474SketchRegisterHandling.ino: examples of L6474 control functions (access to the registers) with 1 X-NUCLEO-IHM01A1 shield
  • And a readme.txt which gives additionnal details

StepperMotorLibraryAndSketchesForL6474.zip (28.5 KB)

I had not heard of that stepper driver before and Google found this PDF .

It is interesting because it can supply 3 amps.

However that document does not provide a good overview of its capabilities. Perhaps you can write a description or a link to something more useful.

Personally I don't like things being on Arduino shields because they get in the way of other things.

...R

In association with the l6474 library that I previously posted, I wrote an additionnal sketch example to drive one motor thanks to Uart commands. I attached it to this post.
It only supports the driving of one motor but it could be easily enhanced to handle the 3 motors as the library allows it.

To use it:

  • You have to install the L6474 library
  • The Uno must have a X-Nucleo-Ihm01A1 on top of it. A stepper motor has to be connected to the bridges of the expansion board and its external power supply must be enabled.
  • The terminal port must be configured to 9600 baud, new line handled with option “CR+LF” and I recommend to enable local echo.
  • Then, just download the sketch to the Arduino Uno with the IDE.
    -If your setup is correct, as this step you should see the token :”>>:” at the serial terminal. It means that the Uno firmware is expecting some instructions.
  • Then you have to enter one of the following command line:
    C1 → to get the acceleration in pps2 (pulse by second2)
    C2 → to get the current speed in pps (pulse by second)
    C3 → to Get the deceleration in pps2
    C4 → to Get the shield state
    C5 → to Get the shield the FW version (ACCELERATING, DECELERATING, STEADY or INACTIVE)
    C6 → to Get the Mark position
    C7 → to Get the max speed in pps
    C8 → to Get the min speed in pps
    C9 → to Get the current position
    C10 → to go to home position
    C11 → to go to mark position
    C12 → to go to position
    C13 → to make a hard stop
    C14 → to move of steps in forward direction if is 0,
    in backward direction if is 1
    C15 → to reset all shields
    C16 → to run in forward direction if is 0,
    in backward direction if is 1
    C17 → to set the acceleration to
    C18 → to set the deceleration to
    C19 → to set current position to be the home position
    C20 → to set current position to be the mark position
    C21 → to set max speed to in pps
    C22 → to set min speed to in pps
    C23 → to make a soft stop
    C24 → to wait while the motor is active
    C25 → to send a disable command (bridges off)
    C26 → to send a enable command (bridges on)
    C27 → to send a get param command with as register address
    C28 → to send a get status command (read and clear status register)
    C29 → to send a nop command
    C30 → to send a set param command with as register address,
    as value
    C31 → to read status register (no clear is done)
    C32 → to reset the shield
    C33 → to release the reset
    C34 → to set the step mode to full step if is 1
    to half step if is 2
    to 1/4 step if is 4
    to 1/8 step if is 8
    to 1/16 step if is 16
    C35 → to set direction: forward direction if is 0,
    backward direction if is 1

L6474SketchFor1MotorShieldDrivenByUart.zip (3.19 KB)

Robin2:
It would be much more convenient if you just add the library as an attachment to a forum post.

...R

Jeez, how about some manners?

Is it so hard to click on the github link provided, then click on a the button to download a zip ?

This looks like a very thorough , clear and well documented library , with examples.

So let's start with : many thanks Michel_f ! :smiley:

To make this more use, we need the circuit for the board and the datasheet for the L6474

The board is little more than a breakout board for the chip so the doc for the board is pretty empty but provides the circuit layout.

Most of the stuff we need to know is in the chip datasheet and this seems very closely matched to what is in the library provided. Nice.

Now one thing I don’t get is the “daisy-chain”. So if Michel_f or anyone can elaborate it would be helpful.

It seems that the zero resistors in R7 and R12 can be moved to the normally empty positions R8 or R9 , this will break the link to the main arduino MISO and MOSI lines and then connection to the two pin “SPI motor” connector.

But I don’t see how this can work to daisy-chain the driver boards.

It seems from the spec sheet that SDO output is held after the clock falls to allow onward ripple of the signal from SDO to SDI on the next board. But there’s no real explanation of how this should work, maybe it is deemed to be obvious by those familiar with the chip.

Now I may be missing the point but it would seem that if two or more boards are daisy-chained, it is no longer possible to get individual return codes ( eg GetStatus response ) from each chip. All chips have to be activated with CS for the chain to work, so none can be interrogated.

Any explanations on how this can be done and what the limitations are would be helpful.

ardnut:
Jeez, how about some manners?

The comment you quoted was / is perfectly polite. And I stand by what I said. It is easier to access stuff intended for users of this Forum if it is posted in this Forum.

I don't think I am the only one with that opinion.

...R

https://github.com/MotorDriver/L6474/archive/master.zip

It seems like the Arduino (non)-IDE does not like the hyphen in L6474-master, it barfs. Something about only letters and numbers. (Yeah, well the IDE sucks, but that's well known. "only letters and numbers", for real! ) Suggest rezipping.

I can install the lib by a manual zip extraction but I don't get the example appearing in the IDE menus.

build the single motor example, plugged a board in and got my stepper motor up and running in no time.

Excellent. ;D

This at least provides a test-bed to experimenting with the SPI command structure. Next I want to strip this down to the bare bones and see whether I can integrate it into grbl.

The SPI lib is fairly light since most of it happens in hardware. The L6474 lib is quite large but most of it seems to be readability constants, and most of that should get stripped by the compiler.

GRBL is a bit of a squeeze already so this could be tricky.

Now hopefully someone will be able to provide some info on this daisy-chain idea for stacking the boards.

The daisy chaining is used to send commands via the SPI from the Uno to several X-NUCLEO-IHM01A1 boards.
The purpose of these commands can be to enable/disable the briges, set the parameters of the L6474 (to dynamically adjust the torques for examples), to know the position, to get the alarm status (over current detection, over temperature,...) of the L6474

So, to use daisy chaining you will first need to have 2 or 3 X-NUCLEO-IHM01A1 boards.
These boards have two crossover pins that are combined with some shunt (0K) resistors to propagate the SDO of one board to the SDI of the following one.

By default, the shunt resistors board are set for 1 board configuration (R1, R4, R7, R12 resistors mounted).

For 2 boards configuration,

  • the first board you have to move these resistors to have R1, R4, R7, R10 resistors mounted
  • the second must have R2, R5, R8, R12 resistors mounted

For 3 boards configuration,

  • the first must have R1, R4, R7, R10 resistors mounted
  • the second must have R2, R5, R8, R11 resistors mounted
  • the third must have R3, R6, R9, R12 resistors mounted

(to have more details you can have a look in paragraph 2.2 of ST document " UM1857: Stepper motor driver expansion board based on L6474 " that you can find here: http://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/DM00156746.pdf)

Once the shunt resistors are correctly mounted, you only have to plug on board on top of the other to have a 2 or 3 boards configuration.

Resistors R25 and R24 could also be moved to use another CS (chip select) line or Clock line. But in my case, I used the default configuration.

Moreover, to fully understand daisy chaining you have to know that:

  • all boards share the same clock and chip select.
  • the SDO of the Uno is linked to the SDI of the first shield
  • then each SDO of one shield is linked to the SDI of the following shield (thanks to the two additional crossover pins)
  • the SDO of the last shieled is linked to the SDI of the UNO
  • the data are transmitted byte by byte.
  • When the CS is high, the SPI works as a delay line: at each clock enabling , a byte is read from the SDI and pushed to the SDO
  • When the CS is released, the L6474 will interpret the available byte at the SDI and insert the answer at the SDO

And if you want the full details, you can have a look of this application note (still from ST):
"AN4290: dSPIN, cSPIN and easySPIN family communication protocol":

and specifically at figure 9 where there is a time diagram with the clock and several devices!

From the point of view of a library user, the daisy chaining is hidden, and its use is quite simple as you only have to specify the index (from 0 to 2) of the targetted board to use it!

For example, if you want to get the status of the first board you have to write:
uint16_t statusRegister = myL6474.CmdGetStatus(0);
to get the status of the second shield:
uint16_t statusRegister = myL6474.CmdGetStatus(1);
to get the status of the third shield:
uint16_t statusRegister = myL6474.CmdGetStatus(2);

To set the torque regulation current of the first shield board to 625 mA (caution only multiple of 31.25 are supported):
myL6474.CmdSetParam(0, L6474_TVAL, 625);

To set the torque regulation current of the third shield board to 1000 mA
myL6474.CmdSetParam(2, L6474_TVAL, 1000);

Hello, sorry to bring a post back from the dead, but I have purchased an IHM03A1, and it is very similar to the IHM01A1. I'm hoping to use this library, and adapt it slightly by remapping a couple of pins. Does anyone know what I need to do? Will it be easier to start from scratch? I would prefer to use ST's library, but I don't want to have to buy their board, install their SDK, and learn Python when I'm just starting to get used to the Arduino platform.

IHM03A1:

IHM01A1:

jmak01:
Hello, sorry to bring a post back from the dead, but I have purchased an IHM03A1, and it is very similar to the IHM01A1. I'm hoping to use this library, and adapt it slightly by remapping a couple of pins. Does anyone know what I need to do? Will it be easier to start from scratch? I would prefer to use ST's library, but I don't want to have to buy their board, install their SDK, and learn Python when I'm just starting to get used to the Arduino platform.

Hi, did you get anywhere with this? The chip driving the stepper is different (L6474 versus powerSTEP01) which may be quite different chips in terms of the required software. The latter is certainly a grunt device (perhaps 10A versus 3A for the L6474).

Hi RobWardNZ jmAK01:

I ran into the same issue as you. Someone already posted the library for powerSTEP01.

Please check it here : GitHub - Megunolink/powerSTEP01_Arduino_Library: Arduino library support for the SparkFun AutoDriver board based on the ST Micro L6470 stepper driver.

Hope it works for you !

Thanks
-Kazi

ardnut:
Jeez, how about some manners?

Is it so hard to click on the github link provided, then click on a the button to download a zip ?

This looks like a very thorough , clear and well documented library , with examples.

So let’s start with : many thanks Michel_f ! :smiley:

I think you over-react - people here get down to the facts ASAP so as to maximize their usefulness - if
you are looking for social nicities there are other forums for that, here we talk Arduino problems and
solutions. I refer you to Eric S Raymonds guide. How To Ask Questions The Smart Way

MarkT:
I think you over-react -

It's a nice link - I have bookmarked it.

But you seem to the 2 years late for the party. :slight_smile:

...R

No new post - This finding belongs to the powerSTEP01 Library discussion …

The library was derived from a former library and some definitions of status bits have changed. This was not changed in the current version I downloaded some weeks before (file “powerSTEP01SPINConstants.h” version from Jan.2017). Please change the status Bit usage:
old:

// * = removed lines
// * #define STATUS_NOTPERF_CMD             0x0080 // Last command not performed.
// * #define STATUS_WRONG_CMD               0x0100 // Last command not valid.
// * #define STATUS_TH_WRN                  0x0400 // Thermal warning
// * #define STATUS_TH_SD                   0x0800 // Thermal shutdown
// * #define STATUS_OCD                     0x1000 // Overcurrent detected
// * #define STATUS_STEP_LOSS_A             0x2000 // Stall detected on A bridge
// * #define STATUS_STEP_LOSS_B             0x4000 // Stall detected on B bridge
// * #define STATUS_SCK_MOD                 0x8000 // Step clock mode is active

// Status register motor status field
// * #define STATUS_MOT_STATUS_STOPPED       (0x0000)<<13 // Motor stopped
// * #define STATUS_MOT_STATUS_ACCELERATION  (0x0001)<<13 // Motor accelerating
// * #define STATUS_MOT_STATUS_DECELERATION  (0x0002)<<13 // Motor decelerating
// * #define STATUS_MOT_STATUS_CONST_SPD     (0x0003)<<13 // Motor at constant speed

There is only one bit now for command failure; 0x0100 has a new meaning and some bits were shifted; motor status was shifted faulty; temperature status is now 2bits with 4 stati. Note that some names had to be changed due to different meaning, following name conventions in the data-sheet.
new:

 // * Changed due to transfer error from former chip,  pl, 08'2017:
#define STATUS_CMD_ERR_OR               0x0080 // command error 
#define STATUS_STCK_MOD                 0x0100 // step clock mode
#define STATUS_UVLO_ADC                 0x0400 // ADC undervoltage
#define STATUS_OCD                      0x2000 // overcurrent detection
#define STATUS_STALL_B                  0x4000 // stall detection only in voltage mode
#define STATUS_STALL_A                  0x8000 // stall detection only in voltage mode

#define STATUS_MOT_STATUS_STOPPED       (0x0000)<<5  // Motor stopped
#define STATUS_MOT_STATUS_ACCELERATION  (0x0001)<<5  // Motor accelerating
#define STATUS_MOT_STATUS_DECELERATION  (0x0002)<<5  // Motor decelerating
#define STATUS_MOT_STATUS_CONST_SPD     (0x0003)<<5  // Motor at constant speed

// added for temperature:
// Status register termperature status field
#define STATUS_TH                        0x1800      // field thermal status
#define STATUS_TH_NORMAL                (0x0000)<<11 // normal temperature
#define STATUS_TH_WARNING               (0x0001)<<11 // warning temperature
#define STATUS_TH_BRIDGE_SHUTDOWN       (0x0010)<<11 // bridge shutdown
#define STATUS_TH_DEVICE_SHUTDOWN       (0x0011)<<11 // device shutdown

@authors: Please check the code above with ST DocID025022 Rev 5 page 71ff; if accepted change the library accordingly. Maybe I was using a wrong source file - then please correct the post.

peetsi:
@authors: Please check the code above with ST DocID025022 Rev 5 page 71ff; if accepted change the library accordingly. Maybe I was using a wrong source file - then please correct the post.

I don’t know who you are referring to but it would be wise to work on the assumption that I am the only person who reads this.

…R