Go Down

Topic: L6470, Autodriver, dSPIN, 2 motors, need to run independently... (Read 3279 times) previous topic - next topic

rholt

I'm using the Autodriver board which uses the L6470 chip from ST Micro.
The single board/stepper works how I'd like it to with the dSPIN commands (from ST) , and I know I can link two boards to work with SPI, but ...
I cannot figure out how to program them independently - basically send dSPIN commands over SPI to one Autodriver board, and then send different commands to the other board.
Basically I'm trying to run the wheels of a two-wheeled robot (inverted pendulum).
I understand that SPI can run commands out to different devices w/ CS (SS), but I'm not sure, in the code how I DEFINE which device has what code? (hope I'm making sense).


any help is greatly appreciated...
Russ from Coral Springs, Florida, USA
Russ from Coral Springs, Fl, USA

raschemmel

One cs per device. You have to pick a second pin to use for the chip select for the second device so you wind up with:

Code: [Select]
# define cs_M1  10
# define cs_M2  11 


or similar.
All of the other code should be the same.  How you arrange the code is up to you but however you cut the cake, only ONE chip select can be active at any given instance. You cannot read or write from the second device until you are through doing business with the first.  If you told the first to turn on it will be on when you go to turn on the second  and you will not be able to turn off the first until you have finished with the second and so forth. That being the case , it makes sense to have two blocks of code , one for each device so you don't try to read or write to both at the same time.
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

rholt

1st of all Thank You for getting back with me so quickly.
I get what you're saying and i'm trying to relate it to the 2 "L6470 AutoDriver" boards i'm using.
brute force i can use the CSN pin on each board to go to their separate Pins on the MEGA board in order to enable/disable the read/write commands.
But the boards have the ability to daisy-chain (thru jumpers) SPI from one board to another and there is a CSN in and a CSN out on each board that has to do with that daisy-chaining.
i'm thinking that maybe by jumpering this pin from one board to the other it will make both boards move both stepper motors the same way when commands are given, as if there is only one SPI address.
BUT...
If I hook everything up in daisy-chain EXCEPT the CS, then i will still have the boards work over SPI, but thru software calls selecting each individual CSN Pin, i can shoot my commands out to one board, and not the other... (and vice-versa).

Pls let me know if i'm way off. i will try this 'speriment today.
and thanks so much for your help.

If i don't hear back from ya in time, and I implement my plan, I will get back to this post either way to load some code & explain what the results were.

Russ from Coral Springs, Fl, USA
Russ from Coral Springs, Fl, USA

rholt

thanks, again, raschemmel...

UPDATE...
I've hooked 2 - "L6470 Autodriver" boards to my MEGA 2560 Arduino and 2 stepper motors. The code below works well as far as spinning wheels, Reversing direction, and different speeds. (I'm using 2 smaller NEMA 16 motors). the motors run cool as do the boards - they could run all day long.
BUT my problem is just as I though - I'm not able to run the motors independently. Using the code below, I would have thought that insterting "motor=1" and "motor=2" at different places in the code would control them independently.
I'll read up on this more since I'm SO FREAKIN' CLOSE to being able to bring both motors and Gyro/Accelerometer together for my robot! <-- that's when the fun really begins.
Anyway - I think I need someone who has worked with the Autodriver boards 'cause while I'm not an electrical engineer - i feel that maybe something needs to be done with the CSN pins on each of the boards. I've attached a pic of the board. you can see in the upper right there is a hole named CSN. the interesting thing is that this pin seems to be electrically equal to the pin closest to it in the 6-pin "IN" group. In application, I have populated the board with both 5 & 10 Pin Headers.
If I take a 6-pin ribbon cable from this board's OUT and then into the 2nd board's IN, I seem to be essentially connecting the 2 CSN pins together and therefore don't see how i could run the two boards independently.

Questions:
1) Am I correct that if I use a ribbon cable to connect the OUT of the 1st board into the IN of the second board, I am forcing them to both run as if they were the same board over SPI?

2) if this is so, then should I drop the whole ribbon cable idea and just use the boards totally independent?

3) (this is more an SPI question) if I do what i say in question 2, while i know i can define a PIN to each board's SS (CSN)... how do I code so that I'm addressing the ONE board (let's say i have CSN on PIN 1 for that and CSN on PIN 2 for the 2nd board?


if you need more info, just let me know. 

Code: [Select]
// Example V2.0 for Altelectronics Dual Motor Stepper Driver L6470 Shield
// www.altelectronics.co.uk

//dSPIN_main.ino - Contains the setup() and loop() functions.

#include <VTSerial.h>

VTSerial vtSerial;

long mynum = 0;
float myfloat = 0;
char mytext[21];


String txtMsg="";
char s;

byte temp;
byte motor=3;
int status1, status2;


void setup()
{   
  Serial.begin(9600);

// pin configurations
  pinMode(dSPIN_RESET, OUTPUT);
  pinMode(dSPIN_FLAG, INPUT);
  pinMode(dSPIN_BUSYN, INPUT);

  //toggle reset
  digitalWrite(dSPIN_RESET, LOW);
  digitalWrite(dSPIN_RESET, HIGH);
  dSPIN_init();

  motor=3; //the following setting are common for both motors
  dSPIN_SetParam(dSPIN_STEP_MODE, dSPIN_STEP_SEL_1_8 | dSPIN_SYNC_SEL_1);
  dSPIN_SetParam(dSPIN_MAX_SPEED, MaxSpdCalc(500)); //(1200));
  dSPIN_SetParam(dSPIN_FS_SPD, FSCalc(600));
  dSPIN_SetParam(dSPIN_ACC, 0x07f);//0x07f);
  dSPIN_SetParam(dSPIN_DEC, 0x07f);
  dSPIN_SetParam(dSPIN_OCD_TH, dSPIN_OCD_TH_1125mA);
  //fist driver has the internal 16 MHz oscillator enabled, and forwards his clock to the next driver via OSCOUT
  motor=2;
  dSPIN_SetParam(dSPIN_CONFIG,
                   dSPIN_CONFIG_PWM_DIV_1 | dSPIN_CONFIG_PWM_MUL_2 | dSPIN_CONFIG_SR_290V_us
                 | dSPIN_CONFIG_VS_COMP_DISABLE
                 | dSPIN_CONFIG_OC_SD_ENABLE
                 | dSPIN_CONFIG_SW_HARD_STOP | dSPIN_CONFIG_INT_16MHZ_OSCOUT_16MHZ);
 
  //second driver takes the clock forwarded from fist driver
  motor=1;               
  dSPIN_SetParam(dSPIN_CONFIG,
                   dSPIN_CONFIG_PWM_DIV_1 | dSPIN_CONFIG_PWM_MUL_2 | dSPIN_CONFIG_SR_290V_us
                 | dSPIN_CONFIG_VS_COMP_DISABLE
                 | dSPIN_CONFIG_OC_SD_ENABLE
                 | dSPIN_CONFIG_SW_HARD_STOP | dSPIN_CONFIG_EXT_16MHZ_OSCOUT_INVERT);               
  motor=3;               
                 
                 
  dSPIN_SetParam(dSPIN_KVAL_HOLD, 0x2F);
  dSPIN_SetParam(dSPIN_KVAL_RUN, 0xAF);
  dSPIN_SetParam(dSPIN_KVAL_ACC, 0xAF);
  dSPIN_SetParam(dSPIN_KVAL_DEC, 0xAF);

  dSPIN_GetStatus();
}

void loop()
{
  Serial.println("1) Moving FWD 8000");
  dSPIN_Move(FWD, 8000);
  while (digitalRead(dSPIN_BUSYN) == LOW);  // Until the movement completes, the                                         //  BUSYN pin will be low.
  dSPIN_SoftStop();                         // Inserting a soft stop between
  while (digitalRead(dSPIN_BUSYN) == LOW);  // Until the movement completes, the                                          //  motions ensures that the driver
                                         
  Serial.println("2) Moving REV 8000");
  dSPIN_Move(REV, 8000);                     // Now do it again, but backwards.
  while (digitalRead(dSPIN_BUSYN) == LOW);
  dSPIN_SoftStop();
  while (digitalRead(dSPIN_BUSYN) == LOW);  // Until the movement completes, the
 
  Serial.println("3) Moving for 3 seconds at 300 step/s");
  dSPIN_Run(FWD, SpdCalc(300));       
  delay(3000);       
  dSPIN_SoftStop();
 
  Serial.println("4) Moving for 3 seconds at 1200 step/s");
  dSPIN_Run(REV, SpdCalc(1200));
  delay(3000);       
  dSPIN_SoftStop();
 
  Serial.println("5) Moving FWD for 1 seconds at 20 step/s");
  dSPIN_Run(FWD, SpdCalc(20));
  delay(1000);       
  dSPIN_SoftStop();
 
  Serial.println("6) Moving REV for 1 seconds at 20 step/s");
  dSPIN_Run(REV, SpdCalc(20));
  delay(1000);       
  dSPIN_SoftStop();
 
  Serial.println("7) Moving REV 4000 steps @ max speed");
  while (digitalRead(dSPIN_BUSYN) == LOW);
  dSPIN_Move(REV, 4000);
  while (digitalRead(dSPIN_BUSYN) == LOW);
  dSPIN_SoftStop();
  while (digitalRead(dSPIN_BUSYN) == LOW); 
 
  Serial.println("8) Moving FWD 4000 steps @ max speed");
  dSPIN_Move(FWD, 4000);
  while (digitalRead(dSPIN_BUSYN) == LOW);
  dSPIN_SoftStop();
  while (digitalRead(dSPIN_BUSYN) == LOW);
  Serial.println("\t\t*************** END OF LOOP ************");
}
Russ from Coral Springs, Fl, USA

raschemmel

I can't find your chip select (SPI SS) pins. Are the named something else ? You should have two of them . Can you post the part of the code that shows the chip select pins . What are they called on the driver board.  ? ( I can't read the labels )

You realize that you must run the SPI config code to select the SPI SLAVE device before you can talk to it ?
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

rholt

raschemmel,
I'm a bit confused by the code that I've run across and am using.
1st of all, I originally used the AutoDriver.h library, but 2 things were happening:
1) the board would get very hot even when using a single small stepper) to the point of "runaway" while checking with my remote thermometer.
2) I was not getting the speed I wanted, and from what I had read up on the L6470's I should have been getting much higher speeds.

I guess i got a bit ahead of myself with my prior posts, I should have referenced this site from where I picked up the original code:

https://codebender.cc/example/AutoDriver/dSPIN_example:dSPIN_support

if you go there, you'll notice that there are 4 files: 3 ino sketches and the "L6470.h" header.

it seems i have to bring in all the files into a folder: "dSPIN_example".
I then open "dSPIN_example" and the other 2 "ino" sketches appear in different tabs on my Arduino IDE.
The actual "setup()" and "loop()" calls are in the "dSPIN_example.ino" sketch, as are the PIN assignments.
I remind you that I'm using the "MEGA 2560" board. and the SPI assignments I've used are as follows:
Code: [Select]
#include <SPI.h>    // include the SPI library:
#include "L6470.h"  // include the register and bit definitions

#define SLAVE_SELECT_PIN 53 //10  // Wire this to the CSN pin
#define MOSI                            51 //11  // Wire this to the SDI pin
#define MISO                            50 //12  // Wire this to the SDO pin
#define SCK                               52 //13  // Wire this to the CK pin
#define dSPIN_RESET               6  //17  // Wire this to the STBY line
#define dSPIN_BUSYN      5  //16  // Wire this to the BSYN line

#define STAT1       13  // Hooked to an LED on the test jig
#define STAT2      15  // Hooked to an LED on the test jig
#define SWITCH     8   // Hooked to the switch input and a  pB on the jig

I'm not really using the last 3 lines.

so - as you can see and to answer your question... on the Mega board, pin 53 is the Slave_Select_Pin. I've commented out the original PINS in that they were set for an UNO setup.

I think part of my problem here is that this code (all 3 sketches) don't seem to #Define a board as you would do if one used the library "AutoDriver". If you used that Library, you could define  "instances" <-- right word? to refer to the boards like:
AutoDriver boardA(10, 6);
AutoDriver boardB(14, 6);

... Which define the boards and the pins used to refer to them.

this is very frustrating in that I feel there is a simple solution to addressing each board inside the sketch, and if I can get to it, I'll be on my way.

thanks for keeping up w/this.

Russ from Coral Springs, Fl.


Russ from Coral Springs, Fl, USA

raschemmel

Quote
as you can see and to answer your question... on the Mega board, pin 53 is the Slave_Select_Pin.   


Ok, that's fine for one motor but the title of this post is
Quote
L6470, Autodriver, dSPIN, 2 motors, need to run independently...   


So, to reiterate, do you realize that you can control any number of devices with SPI but each and every time you talk to a device, you have to run code that configures the SPI interface as if it were the first time you were communicating with that device and there is no connection between one SPI device and another as far as the uC is concerned. It is as if you are in a room full of people and you are talking to all of them, but only one at a time and no one knows you are talking to the other people, sort of a like a typical singles party in California ....
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

rholt

HAH - I'll take your word on the single's parties in Ca....
AND I understand the concept of the SS addressing.
So, I'm going to make some changes.
I will define
my 1st board's CSN (or SS) as PIN 1 on my MEGA
and
my 2nd board's CNS as PIN2 on my MEGA.

from what i'm reading, in CODE, I should #define both of these pins as OUTPUT and HIGH.
then, in order to talk to the #1 board, I should set PIN 1 LOW and push out commands.
when i'm done, i should set the pin 1 HIGH again?

repeat for #2 board with PIN 2?

I may not be right this time, but I feel I'm circling in. thanks for bearing with me. (i'm the nerd in the corner of the party who seems  - like always - to be speaking to no one!

Russ in CS fla
Russ from Coral Springs, Fl, USA

raschemmel

Quote
from what i'm reading, in CODE, I should #define both of these pins as OUTPUT and HIGH.
then, in order to talk to the #1 board, I should set PIN 1 LOW and push out commands.
when i'm done, i should set the pin 1 HIGH again?


Your code for one motor should be completely independent of your code for the other motor.  You should be able to comment out all the code for one motor and have the other work perfectly and vice versa. At any point in time, whichever motor the arduino is talking to is configured (selected) in that code .

Is that a dual motor driver ?
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

rholt

raschemmel,

I get all of what you just said. And believe me, i've been doing a lot of reading.
I understand that I have to do all the setup work (configuration) for one board and then do the same for the other board.
Also, when i want one motor to go FWD and the other REV, I will have to address each board in separate code...
My basic problem is,
How, in the code, do let Board #1 know that I'm talking to IT and NOT board #2. (when i have CS for Board #1 as PIN 1 and CS for board #2 as PIN 2?
This is probably so simple for you that you don't understand my conceptual gap, here. I apologize.

So, in the Sketch Code,
I have a command:

dSPIN_Move(FWD, 25600);

What would I have to do to have this command go ONLY to board # 1?

BTW - I have 2 boards - they each drive a single bi-polar stepper.

Russ
Russ from Coral Springs, Fl, USA

rholt

digitalWrite() !!!!!
you see? It was the fact of being thick-headed...
I feel i'm on the right track, now...
remember the 3 INO sketches? in the one named "dSPIN_support.ino" towards the bottom of the code is this function:
Code: [Select]
byte dSPIN_Xfer(byte data)
{
  byte data_out;
  digitalWrite(SLAVE_SELECT_PIN,LOW);
  // SPI.transfer() both shifts a byte out on the MOSI pin AND receives a
  //  byte in on the MISO pin.
  data_out = SPI.transfer(data);
  digitalWrite(SLAVE_SELECT_PIN,HIGH);
  return data_out;
}



Then, going back to the sketch "dSPIN_commands.ino", they have all the commands listed, but they are in this form:

Code: [Select]
void dSPIN_ResetPos()
{
  [b]dSPIN_Xfer[/b](dSPIN_RESET_POS);

void dSPIN_Move(byte dir, unsigned long n_step)
{
[b] dSPIN_Xfer[/b](dSPIN_MOVE | dir);
  if (n_step > 0x3FFFFF) n_step = 0x3FFFFF;
  dSPIN_Xfer((byte)(n_step >> 16));
  dSPIN_Xfer((byte)(n_step >> 8));
  dSPIN_Xfer((byte)(n_step));
}

void dSPIN_Run(byte dir, unsigned long spd)
{
[b] dSPIN_Xfer[/b](dSPIN_RUN | dir);
  if (spd > 0xFFFFF) spd = 0xFFFFF;
  dSPIN_Xfer((byte)(spd >> 16));
  dSPIN_Xfer((byte)(spd >> 8));
  dSPIN_Xfer((byte)(spd));
}



so... each of these commands, in turn calls the "dSPIN_Xfer()" function and it, in turn, calls the digitalWrite() command which then WRITES to the designated named device...

Only in this code, there seems to be only one DEVICE named: "SLAVE_SELECT_PIN"

I get the feeling that it is in this funtion (dSPIN_Xfer()" that "SLAVE_SELECT_PIN" is the key for defining which device I want to be writing to.

feeling really, really close,
Russ
Russ from Coral Springs, Fl, USA


Go Up