Does any one have experience using L6474 chip from STmicro?
It seems like a powerful chip and ST provide a Uno pin-compatible breakout board at a very affordable price. However, it looks like a bit of nightmare to drive more than one board ( chip ) from a single SPI interface.
Someone ( of unknown merit/competence ) has been good enough to provide a library and some examples. Looks thorough on the face of it and I've tested the one motor example.
It seems that there is provision to "daisy-chain" several chips feeding MISO ( slave output ) of one chip into MOSI on the next, with the Uno just feeding to the first chip's MOSI.
Now I'm presumably missing a trick somewhere but I can't see how this works and although I do have some hardware to test, I don't have a logic analyser to watch and capture every pulse.
Can someone explain?
For example there is a GetStatus command that sends one byte and receives two in response.
Say I have three chips stacked ( they piggyback each other ) and connected in daisy-chain config , how is it possible for this command to be sent exclusively to, say, the second board and for that board to get the response back to Uno via the third one in the chain?
There some SMC null resistors to use as links which allow separate step, dir and CS lines for each chip. They have to share MOSI, MISO, SCK but these can also be moved to daisy-chain the boards rather than have all fed in parallel from the Arduino pins 12,13,14. In daisychain all CS are connected together to Uno.
If its SPI you common SCLK, MISO and MOSI and provide separate chip-select pins - check
the datasheet to be sure though. Daisy-chaining MISO->MISO I have never seen.
Incidentally this chip looks like more effort to use than a DRV8825 which can do the
same sort of stuff without SPI being needed? Still DMOS outputs, still will get blisteringly
HOT if you try to run it at the "nominal" max current...
For high current use I've found the DRV8711 which uses external MOSFETs to give
much much lower on-resistance and cool running. That also takes SPI programming though.
yeah, I was looking at buying some 8825 boards but they don't provide enough current. I have some 4A motors that I want to exploit.
maybe this "daisy-chain" thing is a bit of a red herring, though it is explicitly mentioned in the data sheet it's very cursory, which makes it difficult to see how it is supposed to be used.
I would expect to use individual CS lines and common the rest. I've no objection to using SPI. Most of it is implemented in hardware anyway so the coding overhead is (should be) pretty minimal.
I've been looking at tons of different chips to implement this for motors needing a bit more power than the usual postage stamp sized hobbyist driver boards provide.
My initial intent was to use discrete NMOS devices but several of the useful features of these kind of chips ( like current limit and temperature control ) are only provided where the power devices are on chip.
The other PITA for prototyping, which limits choice, is the ludicrously small pin spacing many of these chips use. Also heat-sinking through the PCB is a good solution for production but less convenient for lashing up a one-off. Those were a major reasons I chose the ST eval boards. Practicality at a minimal cost.
I'll have a look at the TI chip. Since it's just driving MOS gates, it should not require too much in terms of heat sinking. I'll have to buy a head mounted magnifying glass to do the soldering though and it probably means using OSPARK or similar to fabricate the PCBs before I can even test the motors.
I detailed how to place the shunt resistors depending of the number of boards in your configuration.
Whatever, to summarize how the daisy chaining works:
all X-NUCLEO-IHM01A1 share the same clock and chip select.
the SDO (or MOSI) of the Uno is linked to the SDI (MISO) 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 of the shield and the shunt resistors)
the SDO of the last shield 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
That daisy-chaining is not standard SPI (normally a status byte is echoed back as the command byte is sent). I presume you have no way to get separate fault codes back from each chip?
At each byte which is sent on the SPI to the L6474, you have a byte which is echoed back. But for most commands, the value of this byte is 0. Only commands as get_status, get_param will generate answers different from 0. I don't know if it is standard or not...
By the way, you can have the status of each chip by using either the get_status commands or by directly reading its status register by using the get_param command. The difference between these two ways is that
in the case of the get_status command, the error flags of the status register are cleared
in the case of only reading the status register via a get_param, the error flags are not cleared.
Moreover, if while receiving a new SPI command or while running a motor, an error is detected, the concerned chip will reset its flag pin. If you are using several L6474 shields, their flag pins are connected to the same Uno pin (digital pin 2). But it is still possible to know which chip raises the error.
Indeed, in the library, I attached interrupt 0 to the falling transition of this pin and I propose a registration function "AttachFlagInterrupt" which allows the user to have its own code called when a flag pin is reset:
/* Attach the function MyFlagInterruptHandler to the flag interrupt */
myL6474.AttachFlagInterrupt(MyFlagInterruptHandler);
Then in his callback, the user can send a get status command to each of the 6474 to know which chip is in error:
void MyFlagInterruptHandler(void)
{
/* Get the value of the status register of the first L6474 chip via the command GET_STATUS */
uint16_t statusRegister = myL6474.CmdGetStatus(0);
/* Check NOTPERF_CMD flag: if set, the command received by SPI can't be performed */
if ((statusRegister & L6474_STATUS_NOTPERF_CMD) == L6474_STATUS_NOTPERF_CMD)
{
// SPI Command received by first L6474 can't be performed: Code to be customised
}
/* Get the value of the status register of the second L6474 chip via the command GET_STATUS */
uint16_t statusRegister = myL6474.CmdGetStatus(1);
/* Check NOTPERF_CMD flag: if set, the command received by SPI can't be performed */
if ((statusRegister & L6474_STATUS_NOTPERF_CMD) == L6474_STATUS_NOTPERF_CMD)
{
// SPI Command received by second L6474 can't be performed: Code to be customised
}
}
There is a complete example of the different flags check in the sketch: L6474SketchFor1MotorShield.ino
The demos make the motors move OK ( non SPI part of code ) but only ever seem to give a zero status byte from the SPI commands, even when there is a under-voltage UVLO condition that has stopped the motors and illuminated the D2 warming LED on the boards.
This lib looks thorough and clearly laid out, but I'm wondering whether the SPI code is fully tested.