Sparkfun Autodriver and Teensy 4.0

Status
Not open for further replies.

OhioJim

Well-known member
My telescope project is nearing completion. The last step is to get the stepper motors working.

I have 2 Sparkfun L6470 Autodrivers connected to SPI port #2 on the t4.0 and have been trying to use the SparkFunAutoDriver.h library. I also have a GPS disciplined oscillator to provide a precise 16MHz for the Autodrivers.

The two drivers are wired in daisy chain fashion according to the tutorial on the Sparkfun website.

There are 3 problems I have run into.

1. I set the configuration to use an external 16MHz oscillator, but when I read back the configuration it is the default value.

2. The second driver board (#0) in the daisy chain is not functioning. The way it is wired there is only 1 chip select for both boards??? And there is line in the sketch for telling the library what pin to use for this. The example code I am working from uses 6 motors, and uses the same chip select for all of them.

3. I can tell the first board to move the motor and it does. The test code posted below is supposed to move the motor 100 steps forward and then 100 steps reverse. The motor moves, but the sequence appears random. I have not been able to discern a distinct pattern. It moves forward several times in a row (with a pause in between), then decides it will move reverse several times. As I stated, the pattern appears random.

The two motors are named DECmotor and RAmotor. DECmotor is the one that works. Note that the farthest from the t4.0 in the daisy chain is #0, and #1 is the closest. DECmotor is #1.

Any ideas?

Code:
#include <SparkFunAutoDriver.h>
#include <SparkFundSPINConstants.h>

#include <SPI.h>

// Create our AutoDriver instances. The parameters are the position in the chain of
//  boards (with board 0 being located at the end of the chain, farthest from the
//  controlling processor), CS pin, and reset pin.
#define motorCS 36
#define motorReset 31
#define motorBusy 32
#define NUM_BOARDS 2

// Numbering starts from the board farthest from the
//  controller and counts up from 0. Thus, board "4" is the
//  board which is plugged directly into the controller
//  and board "0" is the farthest away.
AutoDriver RAmotor(0, motorCS, motorReset);
AutoDriver DECmotor(1, motorCS, motorReset);

#define SPISPEED 2500000

void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600);
  Serial.println("Hello world");  
  // Start by setting up the SPI port and pins. The
  //  Autodriver library does not do this for you!
    pinMode(motorCS, OUTPUT);
    digitalWrite(motorCS, HIGH); // tied low is also OK.
    pinMode(motorBusy, INPUT);
    pinMode(motorReset, OUTPUT);
    digitalWrite(motorReset, LOW);
    delay(100); // LOW at least 4 clock cycles of onboard clock. 100 microseconds is enough
    digitalWrite(motorReset, HIGH); // now reset to default values

    delay(500);
    SPI2.begin(); //start the spi-bus


    // Configure the boards to the settings we wish to use
  //  for them. See below for more information about the
  //  settings applied.
  configureBoards();
}

// For ease of reading, we're just going to configure all the boards
//  to the same settings. It's working okay for me.
void configureBoards()
{
 
  Serial.println("Configuring motors...");

    // Before we do anything, we need to tell each board which SPI
    //  port we're using. Most of the time, there's only the one,
    //  but it's possible for some larger Arduino boards to have more
    //  than one, so don't take it for granted.
    DECmotor.SPIPortConnect(&SPI2);
     RAmotor.SPIPortConnect(&SPI2);
    // Set the Overcurrent Threshold to 6A. The OC detect circuit
    //  is quite sensitive; even if the current is only momentarily
    //  exceeded during acceleration or deceleration, the driver
    //  will shutdown. This is a per channel value; it's useful to
    //  consider worst case, which is startup. These motors have a
    //  1.8 ohm static winding resistance; at 12V, the current will
    //  exceed this limit, so we need to use the KVAL settings (see
    //  below) to trim that value back to a safe level.
    DECmotor.setOCThreshold(OC_6000mA);
    RAmotor.setOCThreshold(OC_6000mA);
   
    // KVAL is a modifier that sets the effective voltage applied
    //  to the motor. KVAL/255 * Vsupply = effective motor voltage.
    //  This lets us hammer the motor harder during some phases
    //  than others, and to use a higher voltage to achieve better
    //  torqure performance even if a motor isn't rated for such a
    //  high current. This system has 3V motors and a 12V supply.
    DECmotor.setRunKVAL(192);  // 128/255 * 12V = 6V
    DECmotor.setAccKVAL(192);  // 192/255 * 12V = 9V
    DECmotor.setDecKVAL(192);
    DECmotor.setHoldKVAL(128);  // 32/255 * 12V = 1.5V
    RAmotor.setRunKVAL(192);  // 128/255 * 12V = 6V
    RAmotor.setAccKVAL(192);  // 192/255 * 12V = 9V
    RAmotor.setDecKVAL(192);
    RAmotor.setHoldKVAL(128);  // 32/255 * 12V = 1.5V
     
    // When a move command is issued, max speed is the speed the
    //  motor tops out at while completing the move, in steps/s
    DECmotor.setMaxSpeed(30);
    RAmotor.setMaxSpeed(30);
    DECmotor.setMinSpeed(0.0);
    RAmotor.setMinSpeed(0.0);
    DECmotor.setLoSpdOpt(1);
    RAmotor.setLoSpdOpt(1);
    
    // Acceleration and deceleration in steps/s/s. Increasing this
    //  value makes the motor reach its full speed more quickly,
    //  at the cost of possibly causing it to slip and miss steps.
    DECmotor.setAcc(10);
    DECmotor.setDec(10);
    DECmotor.setSwitchMode(SW_HARD_STOP);
    DECmotor.setOscMode( EXT_16MHZ_XTAL_DRIVE );
    RAmotor.setAcc(1);
    RAmotor.setDec(1);
    RAmotor.setSwitchMode(SW_HARD_STOP);
    RAmotor.setOscMode( EXT_16MHZ_XTAL_DRIVE );

    DECmotor.configStepMode(STEP_FS_128);
    RAmotor.configStepMode(STEP_FS_128);
     RAmotor.getParam(CONFIG);
  Serial.print(CONFIG,HEX);Serial.print(" ");
  DECmotor.getParam(CONFIG);
  Serial.println(CONFIG,HEX);
  delay(2000);
}


void loop() {
  RAmotor.getParam(CONFIG);
  Serial.print(CONFIG,HEX);Serial.print(" ");
  DECmotor.getParam(CONFIG);
  Serial.println(CONFIG,HEX);
  Serial.println("Forward");
  delay(500);
  RAmotor.move(FWD, 100);
  DECmotor.move(FWD, 100);
  while (DECmotor.busyCheck()){}
  DECmotor.softStop();
  Serial.println("Reverse");
  delay(500); 
  RAmotor.move(REV, 100);
  DECmotor.move(REV, 100);
  while (DECmotor.busyCheck()){}
   DECmotor.softStop();
 
}
 
Some further information on this....

Added some statements to my code to read the autodriver status register and send it up the serial port.

It indicates that occasionally it misses a step. And it quite often runs through several forward/reverse cycles even though the motor is not running.
 
Power supply and stepper motor details are useful, can you provide this?

Also how long are the ribbon cables?
 
Power supply and stepper motor details are useful, can you provide this?

Also how long are the ribbon cables?

Ribbon cables between the Autodriver and the t4.0 are about 5 inches. Between the autodrivers and the motors themselves there is a 5 foot coiled microphone type cable. The motors are on the telescope mount which moves in 2 dimensions, and the coiled cables allow freedom of movement.

The power supply for the motors is a 13.5v 35amp supply. Plenty of power there.

The motors are labeled 14HM35-0404A (from eBay), but I am considering getting more powerful ones, as the telescope and counterbalance weigh about 30 pounds. I will have to crank the numbers and see just how much torque is needed. For testing I do not have the telescope and counterbalance mounted. Besides, the problem is the same if I remove the drive belt and run the motors unloaded.

As for the length of the motor cables, the motors will run really slow. A fast slew will be 20-30 steps per second, so cable length should not be a factor here.
 
Datasheet links? I need to know the _full_ tech specs, not just part numbers, in order to see what's what. In particular
motors are often available with multiple winding versions, and this is what I need to know - is the motor's winding impedance
compatible with the supply voltage? Is it compatible with the driver? Is the motor's torque curve likely to be adequate?

I should have been clearer about what I mean by details I suppose, but usually a link the datasheet for the precise part is
the simplest way to transfer the details without error.

When a stepper is stalling like this there are several possible causes, mis-wiring is a common one, lack of supply voltage,
incorrectly set current on the driver, lack of damping and/or microstepping, damaged driver (*).

(*) Never connect or disconnect motor from the driver when the driver is powered up - this often trashes the driver
instantly. Never use anything but a solid connection between motor and driver (for same reason).
 
Sorry, I have never used their controllers and have done almost nothing with motors like this, so take with grain of salt. But in many cases like this my first guess is either bad hardware and/or bad wiring, and in some cases power issues. And of course maybe issues with library.

So if it were me, I would probably try breaking up this debugging into a few separate steps, like:

a) only connect the first controller and motors - Does it work? That is does it properly step you motors +100, -100...
b) If so do the same for second controller

c) probably was part of a) but can I set the parameters and retrieve them. Like which timer to use...

Part of what concerned me was you said you had both boards connected to the same CS pin? I don't think that is correct. If you look at the instructions for connecting multiple boards, you see:
autodriver_hookup_cc.png

That they run the CS pin to only one board, and then there is a place on the first board to then connect it up to the second board.

They also mention that on the first board you must make a jumper on the first board...

Again I have no experience with these boards and the like, but that is what I would look at.

Good luck
 
Datasheet links? I need to know the _full_ tech specs, not just part numbers, in order to see what's what. In particular
motors are often available with multiple winding versions, and this is what I need to know - is the motor's winding impedance
compatible with the supply voltage? Is it compatible with the driver? Is the motor's torque curve likely to be adequate?

I should have been clearer about what I mean by details I suppose, but usually a link the datasheet for the precise part is
the simplest way to transfer the details without error.

When a stepper is stalling like this there are several possible causes, mis-wiring is a common one, lack of supply voltage,
incorrectly set current on the driver, lack of damping and/or microstepping, damaged driver (*).

(*) Never connect or disconnect motor from the driver when the driver is powered up - this often trashes the driver
instantly. Never use anything but a solid connection between motor and driver (for same reason).

I don't have any datasheets, but I will see if I can find them. All I know is the NEMA designation, which indicates it is a NEMA 14 with 4 wires, and a current rating of 0.4 amps. It was purchased on eBay, and appears to be of Chinese manufacture (a red flag???).

As for torque, that can't be the problem since it does the same thing when I run the motors without a load.

The power supply for the motors is rated at 13.7 volts and 35 amps, so that is not the problem. And the L6470 provides for setting the max voltage and current to the motors. I measured the winding resistance as about 24 ohms, which comes out to 9.6 volts at 0.4 amps. So I set the driver parameters to 10 volts and 0.750 maximum amps. Didn't make any difference.
 
Which means there is only one CS pin for both boards!

Yes maybe looking at schematic it may simply pass it on. - BUT, did you change the the hardware SDO jumper on the first board (closest one to the Teensy?)...
Otherwise probably both SDO (MISO) pins for both boards probably try to talk back to each other at the same time, and probably causes lots of confusion.

Again from their setting up two boards: Software...
Code:
// Create our AutoDriver instances. The parameters are the position in the chain of
//  boards (with board 0 being located at the end of the chain, farthest from the
//  controlling processor), CS pin, and reset pin.
AutoDriver boardA(0, 10, 8);
AutoDriver boardB(1, 10, 8);

Somehow through this chain, they use their position within this chain to know which commands are meant for which board....

EDIT: Again if it were me I would simply try one board at a time to see if they work.

And also unclear to me what benifits you get by daisy chaining these boards to each other... Other than many using the Ribbon cables are nice?
i.e. would it be worth it to just use a second CS pin for second board and hopefully not end up with both boards thinking commands are for them or both try to return data...

And of course depending on your needs could put one on SPI and the other on SPI1...
 
Last edited:
Yes maybe looking at schematic it may simply pass it on. - BUT, did you change the the hardware SDO jumper on the first board (closest one to the Teensy?)...
Yes. Verified

Otherwise probably both SDO (MISO) pins for both boards probably try to talk back to each other at the same time, and probably causes lots of confusion.
I found a page in the datasheet for the L6470, which is the chip used on the Autodriver. It appears that there is only one CS, the SPI MOSI pin goes to the first chip SDI pin. The first chip SDO pin goes to the SDI of the second chip, etc., etc. And the SDO of the last chip goes back to the MISO of the SPI port. Somehow the software has to know how to clock the data in and out. Seems to me like it would help if you had many stepper motors, but of limited usefulness with only 2 motors.



And of course depending on your needs could put one on SPI and the other on SPI1...
One SPI port is dedicated to a high speed ADC, so there is a spare. At this point it looks like that might be the best option. I was monitoring the status and config registers via the serial port, and it looks like the second board in the chain (#0---why did they do that????) is being configured differently from the first. They should both be the same.

This is all not relevant at this time anyway. I was probing around with my scope probe, looking at the signals going to the motors. It looks like one phase of the second motor (#0---why did they do that???) is either shorted or the board is dead. Anyway, I was probing around and the probe slipped and I heard a SNAP. Depending on your experience with low-voltage high-current, you know that is a much dreaded sound. Now the thing does not work at all.:( I guess I will have to order a couple new ones.

I picked the Autodriver over simpler ones because I wanted to keep the t4.0 free to do some other critical calculations in my application.
 
I took the last remaining good Autodriver and rewired for a single board.

I also stripped down the sketch so all it does is read and display the configuration register once per second.

It appears that there is some kind of communication problem, as the values displayed keep changing. I am seeing 3 different values, 0B80, 0B88, and 1788 hexidecimal. These are in a random sequence.

I was playing around with the SPI clock, and the "SPI clock divider" parameter and got different values, but still random.
 
Next step if it were me, would try just the board and no display, just do serial outputs of the values and see if that works...

If not, then I would maybe try hacking the library and hack the function:
Code:
byte AutoDriver::SPIXfer(byte data)
{
  byte dataPacket[_numBoards];
  int i;
  for (i=0; i < _numBoards; i++)
  {
    dataPacket[i] = 0;
  }
  dataPacket[_position] = data;
  digitalWrite(_CSPin, LOW);
  _SPI->beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE3));
  _SPI->transfer(dataPacket, _numBoards);
  _SPI->endTransaction();
  digitalWrite(_CSPin, HIGH);
  return dataPacket[_position];
}
And try lowering the speed from 4mhz to 1mhz and see if that makes any difference.

I would also probably also bring in the latest sources for SPI library. I did fix a problem after the last teensyduino release. I don't expect this is the issue, but...

If it works without the display, but now with, I would wonder which display(i.e. which driver) And what SPI mode does that driver need/use?

Why I ask this, is there have been some issues in past with some combination of devices... Where switching modes where the clock is off (LOW versus HIGH), can be an issue. So if MODE is 3 with this device and the display at 0, than each time the SPI switches between these modes and the clock has to be changed, the change starts at the beginning of the first output with the new setting. Sometimes this can confuse the device.... As it sees the clock wrong when its CS pin is selected...

With those types of issues, I have seen and done something like:
Just before you wish talk to the device you might try something like:

Code:
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE3));
SPI.transfer(0);
SPI.endTransaction();
With no CS pins selected, such that no device should respond to it, but will setup the clock pin for Mode 3, and then you can call off to the motor functions... But again some of this depends on if the issue was the mixing of Mode 3 with something like Mode 1...
 
when you change modes to synchronize the clock, there was a post somewhere about it on the forums, send a dummy transfer after the cloco change (SPI.transfer(0xFF)) before asserting the chip (digitalWrite(pin, LOW)). While this byte is ignored before activating the chip, the proper clock level will be set
 
Next step if it were me, would try just the board and no display, just do serial outputs of the values and see if that works...
That is what I meant by "display". Send the configure register values over the Serial link and display on my desktop.

There is a 20x4 display in my project but I am not using it for this motor test sketch.


If not, then I would maybe try hacking the library and hack the function:
I would do that only as a last resort. The assumption is that the library is working, but I may not be using it right.

And try lowering the speed from 4mhz to 1mhz and see if that makes any difference.
Did that. No difference. In fact, I lowered it to 200kHz.

I would also probably also bring in the latest sources for SPI library. I did fix a problem after the last teensyduino release. I don't expect this is the issue, but...

Good idea. I will look into it.

If it works without the display, but now with, I would wonder which display(i.e. which driver) And what SPI mode does that driver need/use?
The display in my project, which I am not using in this motor test sketch, is I2C. There is a 24 bit 8 channel ADC which is on SPI1, but not used in this sketch

Why I ask this, is there have been some issues in past with some combination of devices... Where switching modes where the clock is off (LOW versus HIGH), can be an issue. So if MODE is 3 with this device and the display at 0, than each time the SPI switches between these modes and the clock has to be changed, the change starts at the beginning of the first output with the new setting. Sometimes this can confuse the device.... As it sees the clock wrong when its CS pin is selected...

With those types of issues, I have seen and done something like:
Just before you wish talk to the device you might try something like:
Would this be needed even if there is only one device on each SPI port?
 
when you change modes to synchronize the clock, there was a post somewhere about it on the forums, send a dummy transfer after the cloco change (SPI.transfer(0xFF)) before asserting the chip (digitalWrite(pin, LOW)). While this byte is ignored before activating the chip, the proper clock level will be set

I will look into that.

My feeling is that the problem has something to do with clocking the data. There is a parameter in the library that has something to do with a SPI clock divider. Not sure what it does, but when I changed it I got different values for the config register that were in a random sequence.
 
I stripped the sketch downs so all it does is reset the Autodriver and initialize the SPI.

Then in the main loop it reads the configuration register over and over and sends it back up the Serial line.

I am getting the values 2E88, 1788, and 2E00 hexidecimal. Sequence appears random. 2E88 is the correct default value after a reset.

The 1788 is interesting because it is the correct number of bits, but the upper byte is shifted by one bit. It seems like it is dropping bits, or inserting an extra one.

There are some things that I do not care for, in the way the Autodriver is cabled. The SCK signal is 3 wires away from the closest ground wire, the two oscillator-in wires (why 2?) are inbetween. It would have been better to put SCK and GND next to each other, and move OSCIN to the other edge of the cable. If SCK is 2.5 MHz its bandwidth is 12 MHz or more and should be treated as an RF signal---intimately coupled with a ground as an RF transmission line. OSCIN is worse. In my case 16MHz with a bandwidth of at least 80 MHz.* I can't say that this is causing the problem, but it may be, because my oscilloscope is not good enough.

But that is how the board is made, and it would take a bit of surgery to change it. It might be possible, however, to butcher the cables---split out the SCK and OSC lines and add a twisted ground wire around each.


*To preserve a square wave you need a bandwidth of at least 5 times the clock rate, and preferably 7 times.
 
Maybe post your stripped down sketch on the off chance one of us will see something obvious.

Also have you posted something directly to sparkfun to see if they have any ideas?
 
Maybe post your stripped down sketch on the off chance one of us will see something obvious.

Also have you posted something directly to sparkfun to see if they have any ideas?

Yes, I did. No response from Sparkfun. Their forum doesn't seem to be very active.
 
Here is the stripped down code. Lots of things commented out, so I hope you can follow it.
Code:
#include <SparkFunAutoDriver.h>
#include <SparkFundSPINConstants.h>

#include <SPI.h>

// Create our AutoDriver instances. The parameters are the position in the chain of
//  boards (with board 0 being located at the end of the chain, farthest from the
//  controlling processor), CS pin, and reset pin.
#define motorCS 36
#define motorReset 31
#define motorBusy 32
#define NUM_BOARDS 1

// Numbering starts from the board farthest from the
//  controller and counts up from 0. Thus, board "4" is the
//  board which is plugged directly into the controller
//  and board "0" is the farthest away.
//AutoDriver RAmotor(0, motorCS, motorReset);
AutoDriver DECmotor(0, motorCS, motorReset);

#define SPISPEED 1000000

void setup() {
  // put your setup code here, to run once:
 Serial.begin(115200);
  Serial.println("Hello world");  
  // Start by setting up the SPI port and pins. The
  //  Autodriver library does not do this for you!
    pinMode(motorCS, OUTPUT);
    digitalWrite(motorCS, HIGH); // tied low is also OK.
    pinMode(motorBusy, INPUT);
    pinMode(motorReset, OUTPUT);
    digitalWrite(motorReset, LOW);
    delay(100); // LOW at least 4 clock cycles of onboard clock. 100 microseconds is enough
    digitalWrite(motorReset, HIGH); // now reset to default values

    delay(500);

  SPI2.begin(); //start the spi-bus
    SPI2.setBitOrder(MSBFIRST);
    SPI2.setClockDivider(SPI_CLOCK_DIV4);
    SPI2.setDataMode(SPI_MODE3);
    
   SPI2.transfer(0x00);
 DECmotor.SPIPortConnect(&SPI2);
    // Configure the boards to the settings we wish to use
  //  for them. See below for more information about the
  //  settings applied.
 // configureBoards();
}

// For ease of reading, we're just going to configure all the boards
//  to the same settings. It's working okay for me.
void configureBoards()
{
 
  Serial.println("Configuring motors...");

    // Before we do anything, we need to tell each board which SPI
    //  port we're using. Most of the time, there's only the one,
    //  but it's possible for some larger Arduino boards to have more
    //  than one, so don't take it for granted.
    DECmotor.SPIPortConnect(&SPI2);
    // RAmotor.SPIPortConnect(&SPI2);
     DECmotor.getParam(CONFIG);
  Serial.println(CONFIG,HEX);
    // Set the Overcurrent Threshold to 6A. The OC detect circuit
    //  is quite sensitive; even if the current is only momentarily
    //  exceeded during acceleration or deceleration, the driver
    //  will shutdown. This is a per channel value; it's useful to
    //  consider worst case, which is startup. These motors have a
    //  1.8 ohm static winding resistance; at 12V, the current will
    //  exceed this limit, so we need to use the KVAL settings (see
    //  below) to trim that value back to a safe level.
    DECmotor.setOCThreshold(OC_1125mA  );
   // RAmotor.setOCThreshold(OC_1125mA  );
    delay(100);
   
    // KVAL is a modifier that sets the effective voltage applied
    //  to the motor. KVAL/255 * Vsupply = effective motor voltage.
    //  This lets us hammer the motor harder during some phases
    //  than others, and to use a higher voltage to achieve better
    //  torqure performance even if a motor isn't rated for such a
    //  high current. This system has 3V motors and a 12V supply.
    DECmotor.setRunKVAL(255);  // 128/255 * 12V = 6V
    delay(100);
    DECmotor.setAccKVAL(255);  // 192/255 * 12V = 9V
     delay(100);
     DECmotor.setDecKVAL(255);
     delay(100);
     DECmotor.setHoldKVAL(255);  // 32/255 * 12V = 1.5V
     delay(100);
   //  RAmotor.setRunKVAL(255);  // 128/255 * 12V = 6V
     delay(100);
   //  RAmotor.setAccKVAL(255);  // 192/255 * 12V = 9V
  //  RAmotor.setDecKVAL(255);
     delay(100);
   //  RAmotor.setHoldKVAL(128);  // 32/255 * 12V = 1.5V
     delay(100); 
    // When a move command is issued, max speed is the speed the
    //  motor tops out at while completing the move, in steps/s
     delay(100);
     DECmotor.setMaxSpeed(50);
     delay(100);
   //  RAmotor.setMaxSpeed(5);
    DECmotor.setMinSpeed(0.0);
     delay(100);
  //  RAmotor.setMinSpeed(0.0);
    DECmotor.setLoSpdOpt(0);
     delay(100);
 //    RAmotor.setLoSpdOpt(0);
     delay(100);
    // Acceleration and deceleration in steps/s/s. Increasing this
    //  value makes the motor reach its full speed more quickly,
    //  at the cost of possibly causing it to slip and miss steps.
    DECmotor.setAcc(10);
     delay(100);
     DECmotor.setDec(10);
    DECmotor.setSwitchMode(SW_HARD_STOP);
     delay(100);
     DECmotor.setOscMode( EXT_16MHZ_OSCOUT_INVERT     );
 //   RAmotor.setAcc(40);
     delay(100);
  //   RAmotor.setDec(40);
 //   RAmotor.setSwitchMode(SW_HARD_STOP);
     delay(100);
 //    RAmotor.setOscMode( INT_16MHZ_OSCOUT_16MHZ     );

     delay(100);
     DECmotor.configStepMode(STEP_FS_128);
 //   RAmotor.configStepMode(STEP_FS_128);

     delay(100);
     DECmotor.configSyncPin(BUSY_PIN, SYNC_FS);
  //   RAmotor.getParam(CONFIG);

 DECmotor.softStop();
 while (DECmotor.busyCheck()){}
  int status = DECmotor.getStatus();
  Serial.println(status,HEX);
 // status = RAmotor.getStatus();
 // Serial.println(status,HEX);
  delay(2000);
}

void motorMove(int direction)
{
int param;

  param = DECmotor.getParam(CONFIG);
  Serial.print("Config: ");Serial.println(param,HEX);
//  param = RAmotor.getParam(CONFIG);
//  Serial.println(param,HEX);
  if (direction)
  {
    Serial.println();
    Serial.print("Forward ");
  }
  else
      Serial.print("Reverse ");
  delay(500);
  while (DECmotor.busyCheck()==1){}
  DECmotor.move(direction, 5);
  while (DECmotor.busyCheck()==1){}
  DECmotor.hardStop();

 // while (RAmotor.busyCheck()==1){}
//  RAmotor.move(direction, 5);
//  while (RAmotor.busyCheck()==1){}
//  RAmotor.hardStop();
 
  int status = DECmotor.getStatus();
  Serial.print("Status: ");Serial.println(status,HEX);
//  status = RAmotor.getStatus();
// Serial.println(status,HEX);

}
int i=0;
void loop() {
/*   int status = DECmotor.getStatus();
  Serial.print("Status");Serial.println(status,HEX);
  while (DECmotor.busyCheck()==1){}
  motorMove(i);
  if (i==0)
    i=1;
  else
    i=0;*/
    
 int param = DECmotor.getParam(CONFIG);
  Serial.print("Config: ");Serial.println(param,HEX);  
  delay(100);  
}
 
you should be using SPI Transactions, the older code is deprecated and may or may not be calculated same way

replace:
Code:
    SPI2.setBitOrder(MSBFIRST);
    SPI2.setClockDivider(SPI_CLOCK_DIV4);
    SPI2.setDataMode(SPI_MODE3);

with:
Code:
SPI2.beginTransaction(SPISettings(SPISPEED,MSBFIRST,SPI_MODE3))
 
you should be using SPI Transactions, the older code is deprecated and may or may not be calculated same way

replace:
Code:
    SPI2.setBitOrder(MSBFIRST);
    SPI2.setClockDivider(SPI_CLOCK_DIV4);
    SPI2.setDataMode(SPI_MODE3);

with:
Code:
SPI2.beginTransaction(SPISettings(SPISPEED,MSBFIRST,SPI_MODE3))

It made no difference.
 
Sorry, not seeing much.

I assume you have power to the board/motors, as I think I saw it would not work properly without power...

It looks like it should be properly driving the SPI2 pins, as you can see what I see using Logic Analyzer.

Obviously I don't have the board so no responses.

screenshot.jpg

And I assume that you tested the IO pins for SPI2 to make sure that you have a good connection and that you don't have a short, between pins.


So not sure what else I might be able to suggest.
 
I found where the problem is coming from. Now to figure out what causes it, and what to do about it.

My scope is barely able to see the signals, but I wrote a minimalist sketch to initialize the SPI, reset the L6470, and then in the main loop read the config register.

Looking at the MISO and MOSI lines I can see 3 bytes being transferred, with the scope being triggered from the SCK line.

Everything looks good as for the timing of the data bits and the clock. The MOSI line, sending the command to the L6470 looks good.

However, when I look at the MISO line (SDO on the L6470) it is jittering. Jittering enough to shift the bits by one position. Since I can't probe inside the L6470, it makes me wonder if the same problem is affecting the commands (coming on the MOSI line). Considering how it was behaving with the motors my guess is, yes.

This is disturbing. Is the thing bad? But that means both of them have the same problem. Is there a power problem? Maybe. I will have to look into it. Am I setting it up wrong? Possibly, but in this simple case all I do is a reset. Another thing to look into.

As for how the thing works when daisy chained, each L6470 contains an 8 bit shift register which is used for both input and output. Output from one chip goes to the input of the next, and the last one in the chain sends the output to the MISO line. The library driver knows how many L6470 there are, and clocks the proper number of bits.
 
Have you tried something like adding PU/PD resistors to MISO pin?
https://www.pjrc.com/better-spi-bus-design-in-3-steps/
That is on my list of things to try. And thanks for the link. I will check it out. And don't forget the SCK line. It looks like the L6470 is missing a clock transition. Remember the S100 buss computers? Dating myself here, but you were supposed to terminate all the buss lines with the proper resistors for best perfomance.

Sorry I am not much help here...
No problem, KurtE!. I can't tell you how many times I have solved a problem by describing it to someone.(have 50+years in electronics)

As I mentioned before would start off seeing if you can get one to work and then other, might try different SPI port on off chance there is some problem there...

Already swapped ports, so the hardware SPI itself is not the problem.

And talk to Sparkfun...
I posted on their forum, but no answer. If I can't figure this out then I will try their technical support.

BTW, since I bought these boards I see that there are some available now with 2 L6470 on a single board. Since I think I blew one when the scope probe slipped I have to buy another anyway. It would save some wiring in my box.
 
Status
Not open for further replies.
Back
Top