We are still finishing the propforth release, so peter will hold off sending us samples till the next release is out. Sal is planning a set of CNC extensions as the next step in the project, so this is definitely still on the list.
I have only just been getting back to this stepper board and running some tests on a 91mm NEMA34 (34HY1801) motor @24V. It seems with the mass of an drive roller attached I can run this at up to 2400rpm. I have a particular job where I need to ramp from normal process speed up to as high a speed as possible for half a second or so.
Just wondering what kind of speeds are achievable with other steppers and motors? Has anyone done any tests in this regard?
I've got a 60mm diameter roller on the end of it which drives a 300mm long belt and there's another NEMA34 on the other side and normally the motors are running at the exact same speed. The winding is 1.2 ohms and rated at 2.8A but the average measured running current total for each motor is normally around 0.5A.
I have done a lot of tests now and have concluded that with a nominal 24DC supply that I can run this motor reliably up to 2000 RPM and I have pushed it to over 2500 RPM but it's that weak a feather could stop it. There are a lot of registers in the L6470 that aren't explained very well but I think I have enough of a handle on it for now. Here's a short video if you are interested.
Love the sound... you can hear how smooth it is. Yes this would be a very nice addition to my bot. NEMA34s really don't like to go fast. On the low end they have really great torque but they drop like cliffs as the RPMs increase. I'll bet you could get a NEMA 23 that had more torque at the higher RPMs.
I'll be anxious to see these come out. My bot is limited to 8 microsteps just because the controller can't provide more PPS while also figuring accel. With these I'm free to let the chip do the work and let the controller handle the I2C command interface without concern for stepping on the toes of the pulse generation.
I have four NEMA34 for the next rig I build. Will these be OK if we want to go fast to move to a new position, but only need torque when we want to move slow (ie with the tool engaged)?
I think I remember something about dynamically adjusting voltage or current depending on speed or load. Doe the L6470 support this?
Sal said it shouldn't be a problem for the software, I think he's building this into the stepper functions.
Prof: There are a lot of things that the chip does automatically although it does rely on what you load into the registers but it can also be run under external control quite easily. There are a couple of ways of doing this and my module brings out the discrete step clock pin also. So it's possible to setup the direction, current, etc over SPI and then issue individual step clocks from the Prop if you really want.
BTW, since I'm back in the stepper saddle I will organize to send off the sample modules to you as well as to others who have been waiting
Wow! I've pushed my NEMA34 up to 3400 RPM and beyond. The L6470 can be set to switch to full-step mode automatically above a set threshold and so I am running the motor in full-step mode at this speed. Sure is fast for a big motor. I will try a smaller motor next to see how fast I can push it.
Wow! I've pushed my NEMA34 up to 3400 RPM and beyond. The L6470 can be set to switch to full-step mode automatically above a set threshold and so I am running the motor in full-step mode at this speed. Sure is fast for a big motor. I will try a smaller motor next to see how fast I can push it.
For the last 24 hours, I have been reexamining some of my old schematics and reviewing the characteristics of both the L6470 and the L6208. During this time, I have been weighing the value of speed (full/half step) versus accuracy (microstep), and then it dawned on me about this threshold. As you know, the L6208 is intended for half/full step operation, whereas the L6470 is intended for microstepping operation, however I am now contemplating putting D/A converters on VREF_A and VREF_B of the L6208 to achieve somewhat of a programmable resolution (microstepping thru full stepping). I would assume this is similar to what you are referring to on the L6470.
I'm familiar with the L6208 and other variants etc and I don't think that there is anything that they can do that the L6470 can't. Look, if you don't use all the features and just run the L6470 in dumb full/half step mode with an external step clock you are still far better off IMO than using the L6208 in this dumb mode. Once you start using any degree of current control or micro-stepping then you are already in front as it's all built-in, you don't even need external current sense resistors. BTW, the stepping modes can be set from full-step, half-step etc to 128 microsteps. These chips run as cool as cucumbers.
Anyway, I found a bug with this auto full-step switching as it appears it doesn't actually switch to full-step but another microstep mode instead. However I am awaiting some feedback from ST about this.
I was contemplating ordering some L6470 samples from ST, I just have not done that yet. As for now, I already have several of the L6208s laying around, and a lot of the layout has been done, so I am pretty much just finishing up what I have and I will experiment a little. The main reason I am doing this now is so that I have a real world example for my exposure box thread. I am sure I will order some of the L6470s and experiment with those as well in the future. I just don't have the time available to start it all from scratch.
Bruce, that reminds me that I was going to send you a couple of samples, so sorry about the delay since I haven't been playing with these devices for quite a few weeks a I get distracted. I will send two control boards off to you tomorrow.
There is no rush. I have not had the time to devote to the PCB driller as I intended, and I don't imagine that I will get to it for at least a couple more weeks.
Didn't you see the photos, the tiny chip .... on the tiny pcb ..... on the BIG BAD stepper motor. You know that I just use a dedicated toaster oven for making up my prototypes and with a little solder paste all this tiny SMD stuff is a pushover.
Since I'm back on this thread I have included some updated Forth code. Most of this code is for interacting with the steppers and viewing results.
fl
[ifdef L6470.fth
forget L6470.fth
]
: L6470.fth ;
{
*************************************************************L6470HMicrostepper motion controller chip demo
March2012PeterJakackiHardware: PropellerCPU (P1109PuppySoloCPU module)
L6470Stepper controller (PSM6470MicroStepper module)
P1121MotorController motherboard
Software: PropForth4.6Handles 3A rms per winding. UsesSPI interface.
Define port allocations
UsingProp's EPROMI2Cas clock and data to the L6470Pullups on SDO (from L6470), BUSY, and FLAGas well as
precautionary pullups on CS and pulldown on RST*************************************************************
}
decimal
28 constant .SCL29 constant .SDA0 constant .SDI \ data from L64701 constant .BUSY \ busy flag - pullup with 10K
2 constant .CS1 \ Select master chip
3 constant .CS2 \ slave chip (or daisy chained)
4 constant .STCK1 \ step clock (optional, not used)
5 constant .STCK26 constant .FLAG \ pullup with 10K
7 constant .RST \ Chip standby/reset - pulled down with 10K
15 constant .SENSOR214 constant .SENSOR1 \ NORMALLYLOW0 constant OFF-1 constant ON
variable response
variable unit
hex
: SELECT unit ! ;
: CS unit @ ;
: MASTER .CS1SELECT ;
: SLAVE .CS2SELECT ;
: TXRAW
_sclh
CS pinout CS pinlo
8080do
_scll
response @ 2* .SDI px?1 and or response !
2dup and if _sdah else _sdal then
_sclh
2/
loop
2drop
CS pinin ;
: WAIT begin .BUSY px? until ;
: TXWAITTXRAW ;
\ Made direction a variable to be added to the command so that it could
\ be "set and forget", no need to specify each time.
\
variable dir
: FWD1 dir C! ;
: REV0 dir C! ;
: +DIR dir C@ or ; \ adds direction into the command
decimal
\ this little table holds the bit size of each register so that read and writes of longs can be automatically formatted
variable regsize -4 allot
00 c, 22 c, 09 c, 22 c,
20 c, 12 c, 12 c, 10 c,
13 c, 08 c, 08 c, 08 c,
08 c, 14 c, 08 c, 08 c,
08 c, 04 c, 05 c, 04 c,
07 c, 10 c, 08 c, 08 c,
16 c, 16 c, 00 c, 00 c,
hex
\ Writing to a register is a SetParam command with the register address as the PARAM field
\ Up to 3 bytes of data are needed but unfortunately the byte order varies depending upon the register's size
\ So a lookup is performed in the regsize table and the data arranged accordingly
: REG! \ ( dat reg -- )
0 response !
dup 1F and regsize +C@ \ determine bit size of the register ( dat reg size )
dup 9<if drop else \ 8 bits or less ? ( dat reg )
10>ifTXRAW dup 10 rshift then \ 16 bits or more ? then send: reg bits16..24TXRAW dup 8 rshift then \ 9 to 15 bits send: cmd bits8..15TXRAWTXRAW \ this is either CMD+DAT or trailing
;
\ Modify register address into a GetParam command and send null data while the TXRAW routine reads the response
: REG@ \ ( reg -- data )
0 swap 20 or REG! \ issue corresponding bytes
response @ \ pickup response assembled by TXRAW
;
hex
\ Getstatus does not wait if the L6470is busy but performs a non-invasive status read
: GetStatus \ ( -- status ) \ if no response is received (no chip) then return with 0as status
D0TXRAW0TXRAW0TXRAW0TXRAW response @ 8 rshift dup FFFFFF=if drop 0 then ;
\
: CMD \ ( dat cmd -- )
TX dup 10 rshift TX dup 8 rshift TX ff and TXGetStatus drop ;
\ : SYNCH00CMD ;
\ L6470 application commands - named similar as per programming manual
: NOP0TX ; \ also useful to cause application to wait until controller is ready
: RUN \ ( speed -- )
50+DIRCMD ;
: MOVE \ ( steps -- )
40+DIRCMD ;
: GoTo \ ( position -- ) Go to an absolute position
60CMD ;
: GoToDIR \ ( position -- )
68+DIRCMD ;
: GoUntil \ ( speed act -- )
3 lshift 82 or +DIRCMD ;
: ReleaseSW \ ( act -- )
3 lshift 92 or +DIRCMD ;
: GoHome70TX ;
: GoMark78TX ;
: ResetPosD8TX ;
: ResetDeviceC0TX ;
: SoftStopB0TX ; \ Stop after deceleration
: HardStopB8TX ; \ Stop immediately
: SoftHiZA0TX ; \ Decelerate before bridge disconnection
: HardHiZA8TX ; \ Immediate bridge disconnection
\ Register names - mainly forconvenience and readability
\ Keep these names to less than 8 characters to maintain an order NFA01 constant @POS02 constant @EPOS03 constant @MARK04 constant @SPEED \ current speed
05 constant @ACC \ acceleration
06 constant @DEC \ deceleration
07 constant @MAX \ max speed
08 constant @MIN \ min speed
09 constant @HOLD \ hold current
0A constant @RUN \ run current * adjust this for slower speeds -while running
0B constant @STACC \ accel starting current
0C constant @STDEC \ dec staring current
0D constant @INTSPD \ Intersect speed
0E constant @ACCSS \ Acceleration start slope
0F constant @ACCFS \ Accelerationfinal slope
10 constant @DECDS \ Decelerationfinal slope
11 constant @THERM \ Thermal compensation factor
12 constant @ADC \ 5 bits of ADC reading supply voltage
13 constant @OCD \ overcurrent threshold
14 constant @STALL \ stall threshold
15 constant @FSSPD \ full step speed threshold
16 constant @STEPMD \ controls number of microsteps or none
17 constant @ALARMS \ alarm mask
18 constant @CONFIG \ PWM and clock control etc
19 constant @STATUS
\ Some console friendly aliases
: STOPSoftStopGetStatus drop ; \ Stop and also read the status to clear any errors
: HALTB8TXRAW ; \ Stop immediately, override any operation
: DISCSoftHiZ ; \ Disconnect the bridge - also needed before certain commands can be written
: HOMEGoHome ;
: GOGoTo ;
hex
: CONFIG! STOPDISC@CONFIGREG! ;
: PWMDIV \ ( 1..7--)
1-0 max 07 and 6 min 0D lshift @CONFIGREG@ 1FFF and or CONFIG! ;
: PWMDEC \ ( 0..7-- ) multiply the PWM freq from 0.625 to 2in0.125 increments
7 and 0A lshift @CONFIGREG@ E3FF and or CONFIG! ;
: SLEW \ ( 0..3-- ) adjust the slew rate as180,180,290,5303 and @CONFIGREG@ FCFF and or CONFIG! ;
: VSCOMP \ ( on/off -- )
if20else0 then @CONFIGREG@ 20 invert and or CONFIG! ;
decimal
\ Initialization table values to suit motor and application
\ Multiple tables can be setup for various motors and the table pointer
\ passed to the INIT routine if necessary. Just this one at present.
\ Thisis a 34HY1801 Nema34
\
variable inits -4 allot \ variables points to start of table
decimal \ some motor properties in same table but not part of L6470 registers
\ first 5 values are not loaded into registers but represent motor constants
200 w, \ steps/rev
231 w, \ rpmcon
0 w,
0 w,
0 w,
\ REG5400 w, \ Acceleration400 w, \ Deceleration452 w, \ Maximum speed (for sm7)
0 w, \ Minimum20 w, \ Holding current
32 w, \ Run current
64 w, \ Acceleration starting current
32 w, \ Deceleration starting current
1032 w, \ Intersect speed
128 w, \ Start slope
19 w, \ Accelerationfinal slope
64 w, \ Decelerationfinal slope
0 w, \ Thermal compensation
0 w, \ ADC (read only)
15 w, \ Over-current threshold
127 w, \ StallThreshold (set to max)
550 w, \ Full step speed (changes from microstep)
7 w, \ Step mode
hex
FF w, \ Alarm enables
1E80 w, \ Config \ 2e880 w, 0 w, 0 w, \ reserved
: INIT@ 2* inits +W@ ;
hex
: !REGSHALTDISC195do i INIT@ i REG! loop ;
variable status
: INIT
.RST dup pinout dup pinlo pinhi \ Hardware reset - pulse line low
_sclo _sclh _sdao \ UseI2C lines as outputs for clock and data in (L6470)
.CS2 dup pinhi pinout \ chip selects
.CS1 dup pinhi pinout
SLAVE!REGSGetStatus status 2+W!
MASTER!REGSGetStatus status W!
;
1
hex
: STEPS \ ( steps -- )
@STEPMDREG@ lshift 3FFFFF min MOVE ;
: TURNS \ ( turns -- )
0INIT@ *STEPS ;
: READY? \ ( -- rdyflg )
GetStatus2 and ;
: BUSY? \ ( -- bsyflg )
READY? 0= ;
decimal
: RPM \ ( rpm -- ) Run motor at speed to match rpms
1INIT@ *RUN ;
hex
\ Rough conversion from ADC reading to voltage (pretty close)
: VOLTS@ADCREG@ 9*2/2/2/ ;
\ Simplyfor console diagnostics to see the status register conditions
: ShowStatus
dup if
dup 8000 and if cr ." Step Clock Mode" then
dup 4000 and 0=if cr ." Step Loss B" then
dup 2000 and 0=if cr ." Step Loss A" then
dup 1000 and 0=if cr ." Over Current" then
dup 0800 and 0=if cr ." Thermal Shutdown" then
dup 0400 and 0=if cr ." Thermal Warning" then
dup 0200 and 0=if cr ." Under voltage" then
dup 0100 and if cr ." Wrong command" then
dup 80 and if cr ." Command not performed" then
\
cr ." Speed = "@SPEEDREG@ 1INIT@ / . ." RPM"
dup 60 and 5 rshift
dup 0=if ." stopped" then
dup 1=if ." accelerating" then
dup 2=if ." decelerating" then
3=if ." constant" then
dup 10 and if ." forward"else ." reverse" then
dup 8 and if cr ." Switch Event" then
dup 4 and if cr ." Switch Closed" then
dup 2 and 0=if cr ." Busy" then
dup 1 and if cr ." Bridge disconnected" then
cr ." Steps/full step = "@STEPMDREG@ 1 swap lshift .
cr ." Input Voltage = "VOLTS decimal . ." V"else
." - No device "
then
drop
;
\ *********************DEMO & DEBUG**********************
\
\ Short diagnostic functions which simplify keyboard entry
\ ListRegisters ( in current number base )
\ Use the name for the register as provided in the compiled constant names (tricky)
' @POS _forthpfa>nfa constant regstr
: .NAME1-4 lshift regstr + dup C@ 0F and swap 1+ over .str 0A swap - spaces ;
hex
: LR
." REG NAME MASTER SLAVE DEFAULT "
\ 01: 0020571A 00000000000000E7
1A 1do cr i .byte 3A emit space i .NAMEMASTER i REG@ .long space SLAVE i REG@ .long
4 spaces i INIT@ .long loop cr MASTER ;
\ List the status of the chips
: L \ List the status of the chip(s) for diagnostics
\ busy and flag pins are common
ina COG@ dup 2 and 0=if ." =busy " then 40 and 0=if ." =flag " then
SLAVEGetStatus dup if cr ." SLAVE " dup ShowStatus then drop
MASTERGetStatus dup if cr ." MASTER " dup ShowStatus then drop
cr
;
\ Stop both motors
: SSLAVESTOPMASTERSTOP ;
\ set step mode 0..7 (up the max on full step)
: SMDISC dup @STEPMDREG! if 1C0 else 2FF then @MAXREG! ;
\ write config register
: CFGDISC@CONFIGREG! ;
\ SetRUN current
: RC@RUNREG! ; \ SETRUNCURRENT
\ Some extra test functions
decimal
\ spin the motor back and forth at max speed
: DEMO
begin FWD2000RPM3000 ms REV2000RPM3000 ms key? until STOP ;
Peter, when you apply solder paste for the Q44 are you saying it's easy? I bought three smt Props and solder paste but I hesitate because I assume I'll get it wrong a few times.
I have threatened to do a video to show how easy it is, so I will see about doing one now. However you will find that rather than being ultra-careful I just run a bead of paste across the middle of the pads so that it spans the pads. When I place the Prop or the L6470 I smudge it in a little then when it goes into the preheated toaster oven set at max it takes around 3 minutes for the solder to start to reflow. I leave mine in for about 4 minutes and sometimes 5 if it looks like it needs it as the toaster elements are a bit rough with temperature regulation. However I have never really had any real problems and sometimes I might have to clean up a few bridges either with the end of a flat iron tip or if that doesn't work then a splodge of flux then the iron again. Very rarely do I need the solder wick. Rather than placing the pcb on the rack in the oven I place it on aluminum foil thats been folded up into about four or more layers to act as a tray. When you remove this tray from the oven using a flat piece of metal as a pizza shovel then you find that the foil cools down very quickly plus it also cushions the pcbs a bit from vibration. I have been using the solid tray that comes with the oven lately and as long as I'm careful not to knock it then it seems to work well too.
The pcbs you see in the photos in this thread have been made this way.
There's probably lot's of little things I forget to mention so a video should clear it up a bit.
Since I'm back on this thread I have included some updated Forth code. Most of this code is for interacting with the steppers and viewing results.
Great stuff, thanks for sharing!
Can I ask questions about your code? Mostly little stuff to establish common formatting and use conventions. Forth code is easy, the thought process behind it is what throws me.
Is there a coding standard you follow, I would like to look at what being used as a "Propforth coding standard" starts to evolve.
For example, what does the period represent? That the label is a prop I/O pin? Usually I see period prefixed to a label to indicate that a value will displayed on the screen (like period pops and displays the top stack item), have you seen that before?
Also fetch and store words: I see that you append @ to labels for constants, is there some generalization we can make when we see these in your code?
My thought is that at some point we might do a group review of code that we wish to add to the extensions or change in the kernel, so we make thing more clear and easier to follow. With out getting too cumbersome, I'd like to start on a "style guide" if we can make some consensus. (Sal continues to write code "stream of consciousness" until we establish a standard to which we can compare).
I wouldn't take any of my stuff as any kind of standard, it just works for me. The periods that are prepended to the constants are a bit of a carry over from assembler I think where I couldn't do much with symbol names but just enough to give me a hint that it is a pin constant although it could be confused with the Forth print function. However my variables are lower case to separate them from actual application code which is either upper-case or CamelCase as I do_detest_the_annoying_underscore. There are many times when I have a variable called for instance "sample" and the word that uses the variable with the same name except capitalized in some fashion such as "SAMPLE". Long names are descriptive and "nice" I guess but being more succinct is far more desirable and also a lot easier to remember and to type into the terminal. That's also why I have aliases for some words to make it easier to type with one hand while the other holds a probe etc.
Now as for the @ symbol prepended to the constants well that's to signify an address of some kind like saying "AT this address" so @ACC is the address of the acceleration register. The @ after a word is always read as FETCH of course. I'm also not adverse to placing a long line of code if it makes sense to.
I aim for readability (at least for me) but stack manipulation gets in the way of that but then again, where would Forth be without the stack? Interestingly I normally implement a separate stack for the loop parameters in my Forths rather than using the return stack. That way I can factor out code and still reference the loop parameters without touching the return stack (always a recipe for disaster I find).
Forth on the Prop is very useful but also very cumbersome compared to more conventional processors so I don't mind if things aren't all that standard, plus I never did like any of the Forth standards formulated by committees, they are too full of compromises and/or they try to put everyone's ingredients into the same pot. I also can't get over the fact that although Forth's real strength is in real-time and embedded systems the focus in the standards seem to be bloated and PC-centric.
I'll save talk of "coding standards" until we start peer reviewing extensions to add to the main archive, if that ever comes about.
Not to get too much further off topic (I could move this to another thread if you wish) is your third stack along the lines of vannorman and koopman? http://www.ece.cmu.edu/~koopman/forth/rochester_90b.pdf
Sal and I talked about this for goofy stuff like float and software multitasking, and Sal advised to "not go nuts" until we go the kernel working.
I am using 'Trinamic' chipset (TMC428 & TMC249).
And I want to design a new 'Microstepper'.
The L6470 specifications are very good.
And the price and size of this solution is a 'winner'.
Before purchasing the evaluation board, I am wondering if this chip can also control a basic 'brush DC Motor'
With the internal H bridge, it could easily drive 2 brush DC Motor or 1 super brush DC Motor.
But in the specification I cannot find this information.
If you already have the evaluation board, Could you tell me if this feature is possible ?
I don't use brush DC motor very often, but it could be a plus.
While the L6470 is IMO a very good microstepper controller and driver I doubt very much that it would be a good solution for DC motors. The only way to directly control what the outputs will do is to write directly to the electrical position register EL_POS and even then I don't think it's a great solution. So it's no wonder you didn't find it in the specification because it's not specified or designed to wash dishes or drive DC motors. But all that depends upon what degree of "plus" you are after. I will probably try some DC motors just for the fun of it and who knows???
I did not expect the L6470 to drive brush DC motors.
But it was a possibility.
I noticed the L6460 chip.
It is a dual solution Microstepper/brush DC motors.
But there is a 1/16 limitation on the Microstepper side.
Anyway I also found a Texas Instrument solution:
DRV8412 (or32) + F28035 microcontroller.
It is a chipset solution and I need to add some external components to get a current feedback.
The price of this solution is x2 the one with L6470 (the pcb size is also bigger).
Hi ,
Been a while since this tread has had activity - has there been any further developments on the task of demonstrating the use of l6470s in a cnc capacity ?
thanks
chaz
Here's some updated code I use for this chip on my P1121 dual stepper pcb with the PuppySolo. This is loaded just like any other PropForth extension by pasting the text into a terminal (at 230400 baud) and then backing up the compiled code with the "saveforth" command. After that I just load my simple application on top of that without having to touch the driver again. This is more than a driver though as it is setup for diagnostics and formatting results.
I have a couple of P1121 sets here that I am sending Tubular and possibly a set to Prof Braino so they can play with these on their CNC machines and report back.
EDIT: I can setup a unit hooked-up to a couple of motors running PropForth and connect via Bluetooth back to an XPORT module (or maybe a Spinneret) that would be accessible via TELNET and also have a webcam running. While viewing the webcam stream someone could TELNET and start typing commands and even enter code if they want. If you want to telnet the best Windows terminal to use IMO is TeraTerm (via Sourceforge). Let me know if you are interested and I will set it all up over the weekend, maybe with something interesting attached to the motors. What's the best way of getting the TELNET data so others can see it? I guess maybe just plant a monitor in the webcam view?
fl
[ifdef L6470
forget L6470
]
: L6470 ." L6470 MicroStepper V1.1 120602" ;
{
L6470Microstepper driver module - load in before application code and issue "saveforth" to lock into PropForth2012PeterJakackiUsing: PropForth5.2 (beta)
Compiled including diagnostics etc takes around 3.3kB
Implemented on PuppySolo- working configuraton uses two L6470 modules
.BUSY and .FLAG lines are monitored (and used) but are superfluous as status register can be read
Step clock STCK lines could be useful forCNC modes where steps have to be synchronized
.RSTis probably not needed either but is a quick way to reset all stepper drivers.
}
decimal
0 constant .MISO \ MISO data from L6470- multiple outputs are commoned with 220R in each output.
1 constant .BUSY \ busy flag - pullup with 10K
2 constant .CS1 \ Select master chip
3 constant .CS2 \ slave chip (or daisy chained)
4 constant .STCK1 \ step clock (optional, not used here)
5 constant .STCK26 constant .FLAG \ pullup with 10K
7 constant .RST \ Chip standby/reset - pulled down with 10K
28 constant .SCK \ SCLis shared with SCK29 constant .MOSI \ SDAis shared with MOSI0 constant OFF \ I like to be able to say OFFVALVE and sensible stuff like that
-1 constant ON
variable response \ holds the last response
wvariable unit \ remember which unit was selected (MASTER or SLAVE)
hex
: !PIN dup pinhi pinout ;
: SELECT unit W! ;
: CS unit W@ ;
: MASTER .CS1SELECT ;
: SLAVE .CS2SELECT ;
\ Transmit serial data to L6470- couold benefit from somePASM eventually
: TXRAW \ ( data -- ) \ Sequence: CSLO+ 8x(SCLLO+RD+WR+SCLHI) +CSHI 80us/bit
_sclh
CS pinout CS pinlo
8080 \ Start with mask =MSB=80 and loop 8 times from 0 to 7do
_scll \ clock low then read MISO data
response L@ 2* .MISO px?1 and or response L!
\ dup both data and mask and test bit and setMOSI
2dup and if _sdah else _sdal then
_sclh \ clock the data into the L6470 on low-to-high
2/ \ shift mask right
loop
2drop \ discard the data and mask (yeah, us Forthersget down and dirty and do our own garbage collection!)
CS pinin \ Let the CS float high (allowing other cogs to take control perhaps)
;
\ This could just do a readstatus register instead (using TXRAW)
: WAIT begin .BUSY px? until ;
: TXWAITTXRAW ;
\ Made direction a variable to be added to the command so that it could
\ be "set and forget", no need to specify each time.
\
wvariable dir
: FWD1 dir C! ;
: REV0 dir C! ;
: +DIR dir C@ or ; \ adds direction into the command
decimal
\ this little table holds the bit size of each register so that read and writes of longs can be automatically formatted
variable regsize -4 allot
00 c, 22 c, 09 c, 22 c,
20 c, 12 c, 12 c, 10 c,
13 c, 08 c, 08 c, 08 c,
08 c, 14 c, 08 c, 08 c,
08 c, 04 c, 05 c, 04 c,
07 c, 10 c, 08 c, 08 c,
16 c, 16 c, 00 c, 00 c,
hex
\ Writing to a register is a SetParam command with the register address as the PARAM field
\ Up to 3 bytes of data are needed but unfortunately the byte order varies depending upon the register's size
\ So a lookup is performed in the regsize table and the data arranged accordingly
: REG! \ ( dat reg -- )
0 response L!
dup 1F and regsize +C@ \ determine bit size of the register ( dat reg size )
dup 9<if drop else \ 8 bits or less ? ( dat reg )
10>ifTXRAW dup 10 rshift then \ 16 bits or more ? then send: reg bits16..24TXRAW dup 8 rshift then \ 9 to 15 bits send: cmd bits8..15TXRAWTXRAW \ this is either CMD+DAT or trailing
;
\ Modify register address into a GetParam command and send null data while the TXRAW routine reads the response
: REG@ \ ( reg -- data )
0 swap 20 or REG! \ issue corresponding bytes
response L@ \ pickup response assembled by TXRAW
;
hex
\ Getstatus does not wait if the L6470is busy but performs a non-invasive status read
: GetStatus \ ( -- status ) \ if no response is received (no chip) then return with 0as status
D0TXRAW0TXRAW0TXRAW0TXRAW response L@ 8 rshift dup FFFFFF=if drop 0 then ;
\ Sends a command to the L6470
: CMD \ ( dat cmd -- ) \ Send"cmd" then 3 bytes of data high byte first
TX dup 10 rshift TX dup 8 rshift TXFF and TXGetStatus drop ;
\ L6470 application commands - named similar as per programming manual
: NOP0TX ; \ also useful to cause application to wait until controller is ready
: RUN \ ( speed -- )
50+DIRCMD ;
\ Manual step clock command
: STEPCK58+DIRTX ;
\ Issue step clocks - make sure L6470isinSTEPCK mode
: XSTEP .STCK1 dup pinhi pinlo ;
: XSTEPS swap 0doXSTEP dup 0do loop loop drop ;
: MOVE \ ( steps -- ) \ automatically accels and decels
40+DIRCMD ;
: GoTo \ ( position -- ) Go to an absolute position
60CMD ;
: GoToDIR \ ( position -- )
68+DIRCMD ;
: GoUntil \ ( speed act -- ) \ not used here as it uses a homing switch3 lshift 82 or +DIRCMD ;
: ReleaseSW \ ( act -- )
3 lshift 92 or +DIRCMD ;
: GoHome70TX ;
: GoMark78TX ;
: ResetPosD8TX ;
: ResetDeviceC0TX ;
: SoftStopB0TX ; \ Stop after deceleration
: HardStopB8TX ; \ Stop immediately
: SoftHiZA0TX ; \ Decelerate before bridge disconnection
: HardHiZA8TX ; \ Immediate bridge disconnection
\ Register names - mainly forconvenience and readability
\ Keep these names to less than 8 characters to maintain an indexed NFA used by LRfor diagnostics
00 constant @REGS01 constant @POS02 constant @EPOS03 constant @MARK04 constant @SPEED \ current speed
05 constant @ACC \ acceleration
06 constant @DEC \ deceleration
07 constant @MAX \ max speed
08 constant @MIN \ min speed
09 constant @HOLD \ hold current
0A constant @RUN \ run current * adjust this for slower speeds -while running
0B constant @STACC \ accel starting current
0C constant @STDEC \ dec staring current
0D constant @INTSPD \ Intersect speed
0E constant @STSLP \ start slope -BEMF compensation curve
0F constant @ACCFS \ Accelerationfinal slope
10 constant @DECDS \ Decelerationfinal slope
11 constant @THERM \ Thermal compensation factor
12 constant @ADC \ 5 bits of ADC reading supply voltage
13 constant @OCD \ overcurrent threshold
14 constant @STALL \ stall threshold
15 constant @FSSPD \ full step speed threshold
16 constant @STEPMD \ controls number of microsteps or none
17 constant @ALARMS \ alarm mask
18 constant @CONFIG \ PWM and clock control etc
19 constant @STATUS
decimal
\ Initialization table values to suit motor and application
\ Multiple tables can be setup for various motors and the table pointer
\ passed to the INIT routine if necessary. Just this one at present.
\ Thisis a 34HY1801 Nema34in general-purpose mode
\
variable inits -4 allot \ variables points to start of table
decimal \ some motor properties in same table but not part of L6470 registers
\ first 5 values are not loaded into registers but represent motor constants
200 w, \ steps/rev
13334 w, \ rpmmul
60 w, \ rpmdiv
0 w,
0 w,
\ REG5600 w, \ @ACCAcceleration400 w, \ @DECDeceleration452 w, \ @MAXMaximum speed (for sm7)
0 w, \ @MINMinimum20 w, \ @HOLDHolding current
50 w, \ @RUNRun current
100 w, \ @STACCAcceleration starting current
50 w, \ @STDECDeceleration starting current
1032 w, \ @INTSPDIntersect speed
80 w, \ @STSLPStart slope
40 w, \ @ACCFSAccelerationfinal slope
\ register 1064 w, \ @DECFSDecelerationfinal slope
0 w, \ @THERMThermal compensation
0 w, \ @ADCADC (read only)
15 w, \ @OCDOver-current threshold
127 w, \ @STALLStallThreshold (set to max)
550 w, \ @FSSPDFull step speed (changes from microstep)
7 w, \ @STEPMDStep mode
hex
FF w, \ @ALARMSAlarm enables
\ 18
1EA0 w, \ @CONFIGConfig \ 2e880 w, 0 w, 0 w, \ reserved
variable @inits \ pointer to init table
: INIT@ 2*@initsL@ +W@ ;
hex
\ Some console friendly aliases
: STOPSoftStopGetStatus drop ; \ Stop and also read the status to clear any errors
: HALTB8TXRAW ; \ Stop immediately, override any operation, don't wait
: DISCSoftHiZ ; \ Disconnect the bridge - also needed before certain commands can be written
: HOMEGoHome ;
: GOGoTo ;
: CONFIG! STOPDISC@CONFIGREG! ;
: PWMDIV \ ( 1..7--)
1-0 max 07 and 6 min 0D lshift @CONFIGREG@ 1FFF and or CONFIG! ;
: PWMDEC \ ( 0..7-- ) multiply the PWM freq from 0.625 to 2in0.125 increments
7 and 0A lshift @CONFIGREG@ E3FF and or CONFIG! ;
: SLEW \ ( 0..3-- ) adjust the slew rate as180,180,290,5303 and @CONFIGREG@ FCFF and or CONFIG! ;
: VSCOMP \ ( on/off -- )
if20else0 then @CONFIGREG@ 20 invert and or CONFIG! ;
: LSCOMP \ ( rpm -- ) 300RPM =4194
d292 min STOP d8388 d600 */ d4096 +@MINREG! ;
\ InitializeL6470 registers using init table values
: !REGSHALTDISC195do i INIT@ i REG! loop ;
variable status
\ InitializeL6470 chips using parameter table address supplied (0=default)
: !L6470 \ ( tbl -- ) Initialize the L6470 stepper chip using the table supplied ( or default=0)
dup 0=if drop inits then @initsL!
.RST dup pinout dup pinlo pinhi \ Hardware reset - pulse line low
_sclo _sclh _sdao \ UseI2C lines as outputs for clock and data in (L6470)
.CS2!PIN \ chip selects
.CS1!PIN
.STCK1!PIN
.STCK2!PINSLAVE!REGSGetStatus status 2+W!
MASTER!REGSGetStatus status W!
;
\ Move motor n steps in last selected direction
: STEPS \ ( steps -- )
@STEPMDREG@ lshift h3FFFFF min MOVE ;
\ Using the steps/turn data in the init table, step the motor n turns
: TURNS \ ( turns -- )
0INIT@ *STEPS ;
: READY? \ ( -- rdyflg )
GetStatus2 and ;
: BUSY? \ ( -- bsyflg )
READY? 0= ;
: RPM \ ( rpm -- ) Run motor at speed to match rpms
d13334 d60 */RUN ;
\ *********************DIAGNOSTICS**************************
hex
\ Rough conversion from ADC reading to voltage (pretty close)
: VOLTS@ADCREG@ 9*2/2/2/ ;
\ Littleextensiontohelpanalysethebitinanumber (TOS) thenselectnextbitvariablebit
: BIT? dupbitL@ andbitL@ 2/ bitL! ;
\ Simplyforconsolediagnosticstoseethestatusregisterconditions
: ShowStatusdupif 8000 bitL!
BIT? ifcr ." StepClockMode" thenBIT? 0= ifcr ." StepLossB" thenBIT? 0= ifcr ." StepLossA" thenBIT? 0= ifcr ." OverCurrent" thenBIT? 0= ifcr ." ThermalShutdown" thenBIT? 0= ifcr ." ThermalWarning" thenBIT? 0= ifcr ." Undervoltage" thenBIT? ifcr ." Wrongcommand" thenBIT? ifcr ." Commandnotperformed" then
\
cr ." Speed = " @SPEEDREG@ 2 INIT@ 1 INIT@ */ . ." RPM"
dup 60 and 5 rshiftdup 0= if ." stopped" thendup 1 = if ." accelerating" thendup 2 = if ." decelerating" then
3 = if ." constant" then
\ 10 bitL!
BIT? if ." forward" else ." reverse" thenBIT? ifcr ." SwitchEvent" thenBIT? ifcr ." SwitchClosed" thenBIT? 0= ifcr ." Busy" thenBIT? ifcr ." Bridgedisconnected" thencr ." Steps/fullstep = " @STEPMDREG@ 1 swaplshift .
cr ." InputVoltage = " VOLTSdecimal . ." V"
else
." - Nodevice "
thendrop
;
\ ********************* DEMO & DEBUG **********************
\
\ Shortdiagnosticfunctionswhichsimplifykeyboardentry - especiallyviabluetoothsmartphones !
\ ListRegisters ( incurrentnumberbase )
\ Usethenamefortheregisterasprovidedinthecompiledconstantnames (tricky)
' @POS_forthpfa>nfaconstantregstr
: .NAME 1- 4 lshiftregstr + dupC@ 0Fandswap 1+ over .str 0Aswap - spaces ;
hex
\ ListnamesandcontentsofregistersofbothMASTERandSLAVEaswellastheirdefaultvalues
: LR
." REGNAMEMASTERSLAVEDEFAULT "
\ 01: 0020571A 00000000 000000E7
1A 1 docri .byte 3Aemitspacei .NAMEMASTERiREG@ .longspaceSLAVEiREG@ .long
4 spacesiINIT@ .longloopcrMASTER ;
\ Listthestatusofthechips
: L \ Listthestatusofthechip(s) fordiagnostics
\ busyandflagpinsarecommoninaCOG@ dup 2 and 0= if ." =busy " then 40 and 0= if ." =flag " thenSLAVEGetStatusdupifcr ." --------SLAVE-------- " dupShowStatusthendropcrMASTERGetStatusdupifcr ." --------MASTER-------- " dupShowStatusthendropcr ;
\ Stopbothmotors - veryusefulwhentesting
: SCSSLAVESTOPMASTERSTOPSELECT ;
\ setstepmode 0..7 (upthemaxonfullstep) example: 4 SM ( setsstepmodeto 4 = 16 )
: SMDISCdup @STEPMDREG! if 1C0else 2FFthen @MAXREG! ;
\ writeconfigregisterasin: 2EA8CFG!
: CFG! DISC @CONFIGREG! ;
\ SetRUNcurrentasin: 30 RC
: RC @RUNREG! ; \ SETRUNCURRENT
That's awesome Peter, look forward to having a play soon. If/when you need them back just let me know.
Regarding the webcam demo, for a long time I've wanted to do something similar. I think it would really work well even just with a monitor in the corner. I have a canon vc-c1 camera with pan, tilt and 26x zoom, autofocus, great picture (its the same optics used in camcorders I think). Puts out composite video, and is controlled using RS232 stream. If this is any use I'm happy to send it up. Or I could set it up down here with the modules you send down.
Agreed re TeraTerm it's an outstanding little program especially at high baud rates. Hard to believe its been around for as long as it has, still keeps working great.
Hi Tubular, I will send you two sets so you can work with 4 axis control and if you hook them up via telnet and webcam that would be great too. I will still have a go at setting my end up though as it will be running PropForth so it will be very easy for anyone to start to make things happen from the first few seconds, just type away. I will tie in the webcam to a webpage that has some instructions and examples and links etc.
Anyone have any ideas how best to echo a telnet session onto the same webpage? The fallback is setting up a monitor in the webcam view.
I have a couple of P1121 sets here that I am sending Tubular and possibly a set to Prof Braino so they can play with these on their CNC machines and report back.
I'd be happy to do some work on these. If you send out a second pair, I will forward them to Sal.
Since I've been using these chips I thought I'd give the forum some feedback. There seems to be a lack of documentation in regard to interaction of the many parameters so this can be a little challenging sometimes because when you think you know what you are doing it doesn't work. Anyway for you CNC guys there is no reason why you can't use the chips in "manual" step clock mode as the chip has a lot of fine features and is amazingly small for what it does. This is a "cool" chip, you've seen that the only heatsinking I've been using is the thermal vias to the copper on the opposite side of the pcb.
I've only just recently been using them in this manual mode where I issue the step clock pulses and all other parameters are done over SPI and I have been very impressed with the results. Now I find that ST have released the L6474 which is a dumbed down version in the same package, same pinout etc and half the price almost. The difference with the L6474 is that it "only" does 16 microsteps but it also has a separate DIR pin in place of the SW pin so you can set it up via SPI and just use these two pins most of the time. Since my SPI routines are fast I'm finding it's no problem to set the direction and current via SPI and just use the step clock.
I have posted code here and also on my Tachyon pages.
Oh, and for anyone who might be waiting on some of these modules sorry but please give me a nudge, I've been way too distracted to catch-up and ship these modules off. I do have plenty of stock so if anyone wants to purchase them I am happy to sell the L6470 modules to forum members for $29 USD each + $10 airmail.
Comments
Just wondering what kind of speeds are achievable with other steppers and motors? Has anyone done any tests in this regard?
That said a DOL started 2 pole induction motor would hit 2900 rpm pretty quickly, but I assume you need accurate positioning too.
What kind of drive roller diameter? What kind of power is that stepper, 60 watts or so?
I'll be anxious to see these come out. My bot is limited to 8 microsteps just because the controller can't provide more PPS while also figuring accel. With these I'm free to let the chip do the work and let the controller handle the I2C command interface without concern for stepping on the toes of the pulse generation.
I'm over here, patiently waiting (drums fingers!)
I think I remember something about dynamically adjusting voltage or current depending on speed or load. Doe the L6470 support this?
Sal said it shouldn't be a problem for the software, I think he's building this into the stepper functions.
BTW, since I'm back in the stepper saddle I will organize to send off the sample modules to you as well as to others who have been waiting
For the last 24 hours, I have been reexamining some of my old schematics and reviewing the characteristics of both the L6470 and the L6208. During this time, I have been weighing the value of speed (full/half step) versus accuracy (microstep), and then it dawned on me about this threshold. As you know, the L6208 is intended for half/full step operation, whereas the L6470 is intended for microstepping operation, however I am now contemplating putting D/A converters on VREF_A and VREF_B of the L6208 to achieve somewhat of a programmable resolution (microstepping thru full stepping). I would assume this is similar to what you are referring to on the L6470.
Bruce
Anyway, I found a bug with this auto full-step switching as it appears it doesn't actually switch to full-step but another microstep mode instead. However I am awaiting some feedback from ST about this.
I was contemplating ordering some L6470 samples from ST, I just have not done that yet. As for now, I already have several of the L6208s laying around, and a lot of the layout has been done, so I am pretty much just finishing up what I have and I will experiment a little. The main reason I am doing this now is so that I have a real world example for my exposure box thread. I am sure I will order some of the L6470s and experiment with those as well in the future. I just don't have the time available to start it all from scratch.
I am sure the L6470 is a much better chip.
Bruce
There is no rush. I have not had the time to devote to the PCB driller as I intended, and I don't imagine that I will get to it for at least a couple more weeks.
Bruce
I just received three of the L6470HTR. Talk about small, these things are tiny
Since I'm back on this thread I have included some updated Forth code. Most of this code is for interacting with the steppers and viewing results.
fl [ifdef L6470.fth forget L6470.fth ] : L6470.fth ; { ************************************************************* L6470H Microstepper motion controller chip demo March 2012 Peter Jakacki Hardware: Propeller CPU (P1109 PuppySolo CPU module) L6470 Stepper controller (PSM6470 MicroStepper module) P1121 Motor Controller motherboard Software: PropForth 4.6 Handles 3A rms per winding. Uses SPI interface. Define port allocations Using Prop's EPROM I2C as clock and data to the L6470 Pullups on SDO (from L6470), BUSY, and FLAG as well as precautionary pullups on CS and pulldown on RST ************************************************************* } decimal 28 constant .SCL 29 constant .SDA 0 constant .SDI \ data from L6470 1 constant .BUSY \ busy flag - pullup with 10K 2 constant .CS1 \ Select master chip 3 constant .CS2 \ slave chip (or daisy chained) 4 constant .STCK1 \ step clock (optional, not used) 5 constant .STCK2 6 constant .FLAG \ pullup with 10K 7 constant .RST \ Chip standby/reset - pulled down with 10K 15 constant .SENSOR2 14 constant .SENSOR1 \ NORMALLY LOW 0 constant OFF -1 constant ON variable response variable unit hex : SELECT unit ! ; : CS unit @ ; : MASTER .CS1 SELECT ; : SLAVE .CS2 SELECT ; : TXRAW _sclh CS pinout CS pinlo 80 8 0 do _scll response @ 2* .SDI px? 1 and or response ! 2dup and if _sdah else _sdal then _sclh 2/ loop 2drop CS pinin ; : WAIT begin .BUSY px? until ; : TX WAIT TXRAW ; \ Made direction a variable to be added to the command so that it could \ be "set and forget", no need to specify each time. \ variable dir : FWD 1 dir C! ; : REV 0 dir C! ; : +DIR dir C@ or ; \ adds direction into the command decimal \ this little table holds the bit size of each register so that read and writes of longs can be automatically formatted variable regsize -4 allot 00 c, 22 c, 09 c, 22 c, 20 c, 12 c, 12 c, 10 c, 13 c, 08 c, 08 c, 08 c, 08 c, 14 c, 08 c, 08 c, 08 c, 04 c, 05 c, 04 c, 07 c, 10 c, 08 c, 08 c, 16 c, 16 c, 00 c, 00 c, hex \ Writing to a register is a SetParam command with the register address as the PARAM field \ Up to 3 bytes of data are needed but unfortunately the byte order varies depending upon the register's size \ So a lookup is performed in the regsize table and the data arranged accordingly : REG! \ ( dat reg -- ) 0 response ! dup 1F and regsize + C@ \ determine bit size of the register ( dat reg size ) dup 9 < if drop else \ 8 bits or less ? ( dat reg ) 10 > if TXRAW dup 10 rshift then \ 16 bits or more ? then send: reg bits16..24 TXRAW dup 8 rshift then \ 9 to 15 bits send: cmd bits8..15 TXRAW TXRAW \ this is either CMD+DAT or trailing ; \ Modify register address into a GetParam command and send null data while the TXRAW routine reads the response : REG@ \ ( reg -- data ) 0 swap 20 or REG! \ issue corresponding bytes response @ \ pickup response assembled by TXRAW ; hex \ Getstatus does not wait if the L6470 is busy but performs a non-invasive status read : GetStatus \ ( -- status ) \ if no response is received (no chip) then return with 0 as status D0 TXRAW 0 TXRAW 0 TXRAW 0 TXRAW response @ 8 rshift dup FFFFFF = if drop 0 then ; \ : CMD \ ( dat cmd -- ) TX dup 10 rshift TX dup 8 rshift TX ff and TX GetStatus drop ; \ : SYNCH 0 0 CMD ; \ L6470 application commands - named similar as per programming manual : NOP 0 TX ; \ also useful to cause application to wait until controller is ready : RUN \ ( speed -- ) 50 +DIR CMD ; : MOVE \ ( steps -- ) 40 +DIR CMD ; : GoTo \ ( position -- ) Go to an absolute position 60 CMD ; : GoToDIR \ ( position -- ) 68 +DIR CMD ; : GoUntil \ ( speed act -- ) 3 lshift 82 or +DIR CMD ; : ReleaseSW \ ( act -- ) 3 lshift 92 or +DIR CMD ; : GoHome 70 TX ; : GoMark 78 TX ; : ResetPos D8 TX ; : ResetDevice C0 TX ; : SoftStop B0 TX ; \ Stop after deceleration : HardStop B8 TX ; \ Stop immediately : SoftHiZ A0 TX ; \ Decelerate before bridge disconnection : HardHiZ A8 TX ; \ Immediate bridge disconnection \ Register names - mainly for convenience and readability \ Keep these names to less than 8 characters to maintain an order NFA 01 constant @POS 02 constant @EPOS 03 constant @MARK 04 constant @SPEED \ current speed 05 constant @ACC \ acceleration 06 constant @DEC \ deceleration 07 constant @MAX \ max speed 08 constant @MIN \ min speed 09 constant @HOLD \ hold current 0A constant @RUN \ run current * adjust this for slower speeds - while running 0B constant @STACC \ accel starting current 0C constant @STDEC \ dec staring current 0D constant @INTSPD \ Intersect speed 0E constant @ACCSS \ Acceleration start slope 0F constant @ACCFS \ Acceleration final slope 10 constant @DECDS \ Deceleration final slope 11 constant @THERM \ Thermal compensation factor 12 constant @ADC \ 5 bits of ADC reading supply voltage 13 constant @OCD \ overcurrent threshold 14 constant @STALL \ stall threshold 15 constant @FSSPD \ full step speed threshold 16 constant @STEPMD \ controls number of microsteps or none 17 constant @ALARMS \ alarm mask 18 constant @CONFIG \ PWM and clock control etc 19 constant @STATUS \ Some console friendly aliases : STOP SoftStop GetStatus drop ; \ Stop and also read the status to clear any errors : HALT B8 TXRAW ; \ Stop immediately, override any operation : DISC SoftHiZ ; \ Disconnect the bridge - also needed before certain commands can be written : HOME GoHome ; : GO GoTo ; hex : CONFIG! STOP DISC @CONFIG REG! ; : PWMDIV \ ( 1..7 --) 1- 0 max 07 and 6 min 0D lshift @CONFIG REG@ 1FFF and or CONFIG! ; : PWMDEC \ ( 0..7 -- ) multiply the PWM freq from 0.625 to 2 in 0.125 increments 7 and 0A lshift @CONFIG REG@ E3FF and or CONFIG! ; : SLEW \ ( 0..3 -- ) adjust the slew rate as 180,180,290,530 3 and @CONFIG REG@ FCFF and or CONFIG! ; : VSCOMP \ ( on/off -- ) if 20 else 0 then @CONFIG REG@ 20 invert and or CONFIG! ; decimal \ Initialization table values to suit motor and application \ Multiple tables can be setup for various motors and the table pointer \ passed to the INIT routine if necessary. Just this one at present. \ This is a 34HY1801 Nema34 \ variable inits -4 allot \ variables points to start of table decimal \ some motor properties in same table but not part of L6470 registers \ first 5 values are not loaded into registers but represent motor constants 200 w, \ steps/rev 231 w, \ rpmcon 0 w, 0 w, 0 w, \ REG 5 400 w, \ Acceleration 400 w, \ Deceleration 452 w, \ Maximum speed (for sm7) 0 w, \ Minimum 20 w, \ Holding current 32 w, \ Run current 64 w, \ Acceleration starting current 32 w, \ Deceleration starting current 1032 w, \ Intersect speed 128 w, \ Start slope 19 w, \ Acceleration final slope 64 w, \ Deceleration final slope 0 w, \ Thermal compensation 0 w, \ ADC (read only) 15 w, \ Over-current threshold 127 w, \ Stall Threshold (set to max) 550 w, \ Full step speed (changes from microstep) 7 w, \ Step mode hex FF w, \ Alarm enables 1E80 w, \ Config \ 2e88 0 w, 0 w, 0 w, \ reserved : INIT@ 2* inits + W@ ; hex : !REGS HALT DISC 19 5 do i INIT@ i REG! loop ; variable status : INIT .RST dup pinout dup pinlo pinhi \ Hardware reset - pulse line low _sclo _sclh _sdao \ Use I2C lines as outputs for clock and data in (L6470) .CS2 dup pinhi pinout \ chip selects .CS1 dup pinhi pinout SLAVE !REGS GetStatus status 2+ W! MASTER !REGS GetStatus status W! ; 1 hex : STEPS \ ( steps -- ) @STEPMD REG@ lshift 3FFFFF min MOVE ; : TURNS \ ( turns -- ) 0 INIT@ * STEPS ; : READY? \ ( -- rdyflg ) GetStatus 2 and ; : BUSY? \ ( -- bsyflg ) READY? 0= ; decimal : RPM \ ( rpm -- ) Run motor at speed to match rpms 1 INIT@ * RUN ; hex \ Rough conversion from ADC reading to voltage (pretty close) : VOLTS @ADC REG@ 9 * 2/ 2/ 2/ ; \ Simply for console diagnostics to see the status register conditions : ShowStatus dup if dup 8000 and if cr ." Step Clock Mode" then dup 4000 and 0= if cr ." Step Loss B" then dup 2000 and 0= if cr ." Step Loss A" then dup 1000 and 0= if cr ." Over Current" then dup 0800 and 0= if cr ." Thermal Shutdown" then dup 0400 and 0= if cr ." Thermal Warning" then dup 0200 and 0= if cr ." Under voltage" then dup 0100 and if cr ." Wrong command" then dup 80 and if cr ." Command not performed" then \ cr ." Speed = " @SPEED REG@ 1 INIT@ / . ." RPM" dup 60 and 5 rshift dup 0= if ." stopped" then dup 1 = if ." accelerating" then dup 2 = if ." decelerating" then 3 = if ." constant" then dup 10 and if ." forward" else ." reverse" then dup 8 and if cr ." Switch Event" then dup 4 and if cr ." Switch Closed" then dup 2 and 0= if cr ." Busy" then dup 1 and if cr ." Bridge disconnected" then cr ." Steps/full step = " @STEPMD REG@ 1 swap lshift . cr ." Input Voltage = " VOLTS decimal . ." V" else ." - No device " then drop ; \ ********************* DEMO & DEBUG ********************** \ \ Short diagnostic functions which simplify keyboard entry \ List Registers ( in current number base ) \ Use the name for the register as provided in the compiled constant names (tricky) ' @POS _forthpfa>nfa constant regstr : .NAME 1- 4 lshift regstr + dup C@ 0F and swap 1+ over .str 0A swap - spaces ; hex : LR ." REG NAME MASTER SLAVE DEFAULT " \ 01: 0020571A 00000000 000000E7 1A 1 do cr i .byte 3A emit space i .NAME MASTER i REG@ .long space SLAVE i REG@ .long 4 spaces i INIT@ .long loop cr MASTER ; \ List the status of the chips : L \ List the status of the chip(s) for diagnostics \ busy and flag pins are common ina COG@ dup 2 and 0= if ." =busy " then 40 and 0= if ." =flag " then SLAVE GetStatus dup if cr ." SLAVE " dup ShowStatus then drop MASTER GetStatus dup if cr ." MASTER " dup ShowStatus then drop cr ; \ Stop both motors : S SLAVE STOP MASTER STOP ; \ set step mode 0..7 (up the max on full step) : SM DISC dup @STEPMD REG! if 1C0 else 2FF then @MAX REG! ; \ write config register : CFG DISC @CONFIG REG! ; \ Set RUN current : RC @RUN REG! ; \ SET RUN CURRENT \ Some extra test functions decimal \ spin the motor back and forth at max speed : DEMO begin FWD 2000 RPM 3000 ms REV 2000 RPM 3000 ms key? until STOP ;
The pcbs you see in the photos in this thread have been made this way.
There's probably lot's of little things I forget to mention so a video should clear it up a bit.
Great stuff, thanks for sharing!
Can I ask questions about your code? Mostly little stuff to establish common formatting and use conventions. Forth code is easy, the thought process behind it is what throws me.
Is there a coding standard you follow, I would like to look at what being used as a "Propforth coding standard" starts to evolve.
For example, what does the period represent? That the label is a prop I/O pin? Usually I see period prefixed to a label to indicate that a value will displayed on the screen (like period pops and displays the top stack item), have you seen that before?
Also fetch and store words: I see that you append @ to labels for constants, is there some generalization we can make when we see these in your code?
My thought is that at some point we might do a group review of code that we wish to add to the extensions or change in the kernel, so we make thing more clear and easier to follow. With out getting too cumbersome, I'd like to start on a "style guide" if we can make some consensus. (Sal continues to write code "stream of consciousness" until we establish a standard to which we can compare).
Thanks!
Now as for the @ symbol prepended to the constants well that's to signify an address of some kind like saying "AT this address" so @ACC is the address of the acceleration register. The @ after a word is always read as FETCH of course. I'm also not adverse to placing a long line of code if it makes sense to.
I aim for readability (at least for me) but stack manipulation gets in the way of that but then again, where would Forth be without the stack? Interestingly I normally implement a separate stack for the loop parameters in my Forths rather than using the return stack. That way I can factor out code and still reference the loop parameters without touching the return stack (always a recipe for disaster I find).
Forth on the Prop is very useful but also very cumbersome compared to more conventional processors so I don't mind if things aren't all that standard, plus I never did like any of the Forth standards formulated by committees, they are too full of compromises and/or they try to put everyone's ingredients into the same pot. I also can't get over the fact that although Forth's real strength is in real-time and embedded systems the focus in the standards seem to be bloated and PC-centric.
Not to get too much further off topic (I could move this to another thread if you wish) is your third stack along the lines of vannorman and koopman?
http://www.ece.cmu.edu/~koopman/forth/rochester_90b.pdf
Sal and I talked about this for goofy stuff like float and software multitasking, and Sal advised to "not go nuts" until we go the kernel working.
I am using 'Trinamic' chipset (TMC428 & TMC249).
And I want to design a new 'Microstepper'.
The L6470 specifications are very good.
And the price and size of this solution is a 'winner'.
Before purchasing the evaluation board, I am wondering if this chip can also control a basic 'brush DC Motor'
With the internal H bridge, it could easily drive 2 brush DC Motor or 1 super brush DC Motor.
But in the specification I cannot find this information.
If you already have the evaluation board, Could you tell me if this feature is possible ?
I don't use brush DC motor very often, but it could be a plus.
Regards,
dli
I did not expect the L6470 to drive brush DC motors.
But it was a possibility.
I noticed the L6460 chip.
It is a dual solution Microstepper/brush DC motors.
But there is a 1/16 limitation on the Microstepper side.
Anyway I also found a Texas Instrument solution:
DRV8412 (or32) + F28035 microcontroller.
It is a chipset solution and I need to add some external components to get a current feedback.
The price of this solution is x2 the one with L6470 (the pcb size is also bigger).
Regards.
dli
Been a while since this tread has had activity - has there been any further developments on the task of demonstrating the use of l6470s in a cnc capacity ?
thanks
chaz
I have a couple of P1121 sets here that I am sending Tubular and possibly a set to Prof Braino so they can play with these on their CNC machines and report back.
EDIT: I can setup a unit hooked-up to a couple of motors running PropForth and connect via Bluetooth back to an XPORT module (or maybe a Spinneret) that would be accessible via TELNET and also have a webcam running. While viewing the webcam stream someone could TELNET and start typing commands and even enter code if they want. If you want to telnet the best Windows terminal to use IMO is TeraTerm (via Sourceforge). Let me know if you are interested and I will set it all up over the weekend, maybe with something interesting attached to the motors. What's the best way of getting the TELNET data so others can see it? I guess maybe just plant a monitor in the webcam view?
fl [ifdef L6470 forget L6470 ] : L6470 ." L6470 MicroStepper V1.1 120602" ; { L6470 Microstepper driver module - load in before application code and issue "saveforth" to lock into PropForth 2012 Peter Jakacki Using: PropForth 5.2 (beta) Compiled including diagnostics etc takes around 3.3kB Implemented on PuppySolo - working configuraton uses two L6470 modules .BUSY and .FLAG lines are monitored (and used) but are superfluous as status register can be read Step clock STCK lines could be useful for CNC modes where steps have to be synchronized .RST is probably not needed either but is a quick way to reset all stepper drivers. } decimal 0 constant .MISO \ MISO data from L6470 - multiple outputs are commoned with 220R in each output. 1 constant .BUSY \ busy flag - pullup with 10K 2 constant .CS1 \ Select master chip 3 constant .CS2 \ slave chip (or daisy chained) 4 constant .STCK1 \ step clock (optional, not used here) 5 constant .STCK2 6 constant .FLAG \ pullup with 10K 7 constant .RST \ Chip standby/reset - pulled down with 10K 28 constant .SCK \ SCL is shared with SCK 29 constant .MOSI \ SDA is shared with MOSI 0 constant OFF \ I like to be able to say OFF VALVE and sensible stuff like that -1 constant ON variable response \ holds the last response wvariable unit \ remember which unit was selected (MASTER or SLAVE) hex : !PIN dup pinhi pinout ; : SELECT unit W! ; : CS unit W@ ; : MASTER .CS1 SELECT ; : SLAVE .CS2 SELECT ; \ Transmit serial data to L6470 - couold benefit from some PASM eventually : TXRAW \ ( data -- ) \ Sequence: CS LO + 8x(SCL LO + RD + WR + SCL HI) + CS HI 80us/bit _sclh CS pinout CS pinlo 80 8 0 \ Start with mask = MSB = 80 and loop 8 times from 0 to 7 do _scll \ clock low then read MISO data response L@ 2* .MISO px? 1 and or response L! \ dup both data and mask and test bit and set MOSI 2dup and if _sdah else _sdal then _sclh \ clock the data into the L6470 on low-to-high 2/ \ shift mask right loop 2drop \ discard the data and mask (yeah, us Forthers get down and dirty and do our own garbage collection!) CS pinin \ Let the CS float high (allowing other cogs to take control perhaps) ; \ This could just do a readstatus register instead (using TXRAW) : WAIT begin .BUSY px? until ; : TX WAIT TXRAW ; \ Made direction a variable to be added to the command so that it could \ be "set and forget", no need to specify each time. \ wvariable dir : FWD 1 dir C! ; : REV 0 dir C! ; : +DIR dir C@ or ; \ adds direction into the command decimal \ this little table holds the bit size of each register so that read and writes of longs can be automatically formatted variable regsize -4 allot 00 c, 22 c, 09 c, 22 c, 20 c, 12 c, 12 c, 10 c, 13 c, 08 c, 08 c, 08 c, 08 c, 14 c, 08 c, 08 c, 08 c, 04 c, 05 c, 04 c, 07 c, 10 c, 08 c, 08 c, 16 c, 16 c, 00 c, 00 c, hex \ Writing to a register is a SetParam command with the register address as the PARAM field \ Up to 3 bytes of data are needed but unfortunately the byte order varies depending upon the register's size \ So a lookup is performed in the regsize table and the data arranged accordingly : REG! \ ( dat reg -- ) 0 response L! dup 1F and regsize + C@ \ determine bit size of the register ( dat reg size ) dup 9 < if drop else \ 8 bits or less ? ( dat reg ) 10 > if TXRAW dup 10 rshift then \ 16 bits or more ? then send: reg bits16..24 TXRAW dup 8 rshift then \ 9 to 15 bits send: cmd bits8..15 TXRAW TXRAW \ this is either CMD+DAT or trailing ; \ Modify register address into a GetParam command and send null data while the TXRAW routine reads the response : REG@ \ ( reg -- data ) 0 swap 20 or REG! \ issue corresponding bytes response L@ \ pickup response assembled by TXRAW ; hex \ Getstatus does not wait if the L6470 is busy but performs a non-invasive status read : GetStatus \ ( -- status ) \ if no response is received (no chip) then return with 0 as status D0 TXRAW 0 TXRAW 0 TXRAW 0 TXRAW response L@ 8 rshift dup FFFFFF = if drop 0 then ; \ Sends a command to the L6470 : CMD \ ( dat cmd -- ) \ Send "cmd" then 3 bytes of data high byte first TX dup 10 rshift TX dup 8 rshift TX FF and TX GetStatus drop ; \ L6470 application commands - named similar as per programming manual : NOP 0 TX ; \ also useful to cause application to wait until controller is ready : RUN \ ( speed -- ) 50 +DIR CMD ; \ Manual step clock command : STEPCK 58 +DIR TX ; \ Issue step clocks - make sure L6470 is in STEPCK mode : XSTEP .STCK1 dup pinhi pinlo ; : XSTEPS swap 0 do XSTEP dup 0 do loop loop drop ; : MOVE \ ( steps -- ) \ automatically accels and decels 40 +DIR CMD ; : GoTo \ ( position -- ) Go to an absolute position 60 CMD ; : GoToDIR \ ( position -- ) 68 +DIR CMD ; : GoUntil \ ( speed act -- ) \ not used here as it uses a homing switch 3 lshift 82 or +DIR CMD ; : ReleaseSW \ ( act -- ) 3 lshift 92 or +DIR CMD ; : GoHome 70 TX ; : GoMark 78 TX ; : ResetPos D8 TX ; : ResetDevice C0 TX ; : SoftStop B0 TX ; \ Stop after deceleration : HardStop B8 TX ; \ Stop immediately : SoftHiZ A0 TX ; \ Decelerate before bridge disconnection : HardHiZ A8 TX ; \ Immediate bridge disconnection \ Register names - mainly for convenience and readability \ Keep these names to less than 8 characters to maintain an indexed NFA used by LR for diagnostics 00 constant @REGS 01 constant @POS 02 constant @EPOS 03 constant @MARK 04 constant @SPEED \ current speed 05 constant @ACC \ acceleration 06 constant @DEC \ deceleration 07 constant @MAX \ max speed 08 constant @MIN \ min speed 09 constant @HOLD \ hold current 0A constant @RUN \ run current * adjust this for slower speeds - while running 0B constant @STACC \ accel starting current 0C constant @STDEC \ dec staring current 0D constant @INTSPD \ Intersect speed 0E constant @STSLP \ start slope - BEMF compensation curve 0F constant @ACCFS \ Acceleration final slope 10 constant @DECDS \ Deceleration final slope 11 constant @THERM \ Thermal compensation factor 12 constant @ADC \ 5 bits of ADC reading supply voltage 13 constant @OCD \ overcurrent threshold 14 constant @STALL \ stall threshold 15 constant @FSSPD \ full step speed threshold 16 constant @STEPMD \ controls number of microsteps or none 17 constant @ALARMS \ alarm mask 18 constant @CONFIG \ PWM and clock control etc 19 constant @STATUS decimal \ Initialization table values to suit motor and application \ Multiple tables can be setup for various motors and the table pointer \ passed to the INIT routine if necessary. Just this one at present. \ This is a 34HY1801 Nema34 in general-purpose mode \ variable inits -4 allot \ variables points to start of table decimal \ some motor properties in same table but not part of L6470 registers \ first 5 values are not loaded into registers but represent motor constants 200 w, \ steps/rev 13334 w, \ rpmmul 60 w, \ rpmdiv 0 w, 0 w, \ REG 5 600 w, \ @ACC Acceleration 400 w, \ @DEC Deceleration 452 w, \ @MAX Maximum speed (for sm7) 0 w, \ @MIN Minimum 20 w, \ @HOLD Holding current 50 w, \ @RUN Run current 100 w, \ @STACC Acceleration starting current 50 w, \ @STDEC Deceleration starting current 1032 w, \ @INTSPD Intersect speed 80 w, \ @STSLP Start slope 40 w, \ @ACCFS Acceleration final slope \ register 10 64 w, \ @DECFS Deceleration final slope 0 w, \ @THERM Thermal compensation 0 w, \ @ADC ADC (read only) 15 w, \ @OCD Over-current threshold 127 w, \ @STALL Stall Threshold (set to max) 550 w, \ @FSSPD Full step speed (changes from microstep) 7 w, \ @STEPMD Step mode hex FF w, \ @ALARMS Alarm enables \ 18 1EA0 w, \ @CONFIG Config \ 2e88 0 w, 0 w, 0 w, \ reserved variable @inits \ pointer to init table : INIT@ 2* @inits L@ + W@ ; hex \ Some console friendly aliases : STOP SoftStop GetStatus drop ; \ Stop and also read the status to clear any errors : HALT B8 TXRAW ; \ Stop immediately, override any operation, don't wait : DISC SoftHiZ ; \ Disconnect the bridge - also needed before certain commands can be written : HOME GoHome ; : GO GoTo ; : CONFIG! STOP DISC @CONFIG REG! ; : PWMDIV \ ( 1..7 --) 1- 0 max 07 and 6 min 0D lshift @CONFIG REG@ 1FFF and or CONFIG! ; : PWMDEC \ ( 0..7 -- ) multiply the PWM freq from 0.625 to 2 in 0.125 increments 7 and 0A lshift @CONFIG REG@ E3FF and or CONFIG! ; : SLEW \ ( 0..3 -- ) adjust the slew rate as 180,180,290,530 3 and @CONFIG REG@ FCFF and or CONFIG! ; : VSCOMP \ ( on/off -- ) if 20 else 0 then @CONFIG REG@ 20 invert and or CONFIG! ; : LSCOMP \ ( rpm -- ) 300RPM = 4194 d292 min STOP d8388 d600 */ d4096 + @MIN REG! ; \ Initialize L6470 registers using init table values : !REGS HALT DISC 19 5 do i INIT@ i REG! loop ; variable status \ Initialize L6470 chips using parameter table address supplied (0=default) : !L6470 \ ( tbl -- ) Initialize the L6470 stepper chip using the table supplied ( or default = 0) dup 0= if drop inits then @inits L! .RST dup pinout dup pinlo pinhi \ Hardware reset - pulse line low _sclo _sclh _sdao \ Use I2C lines as outputs for clock and data in (L6470) .CS2 !PIN \ chip selects .CS1 !PIN .STCK1 !PIN .STCK2 !PIN SLAVE !REGS GetStatus status 2+ W! MASTER !REGS GetStatus status W! ; \ Move motor n steps in last selected direction : STEPS \ ( steps -- ) @STEPMD REG@ lshift h3FFFFF min MOVE ; \ Using the steps/turn data in the init table, step the motor n turns : TURNS \ ( turns -- ) 0 INIT@ * STEPS ; : READY? \ ( -- rdyflg ) GetStatus 2 and ; : BUSY? \ ( -- bsyflg ) READY? 0= ; : RPM \ ( rpm -- ) Run motor at speed to match rpms d13334 d60 */ RUN ; \ ********************* DIAGNOSTICS ************************** hex \ Rough conversion from ADC reading to voltage (pretty close) : VOLTS @ADC REG@ 9 * 2/ 2/ 2/ ; \ Little extension to help analyse the bit in a number (TOS) then select next bit variable bit : BIT? dup bit L@ and bit L@ 2/ bit L! ; \ Simply for console diagnostics to see the status register conditions : ShowStatus dup if 8000 bit L! BIT? if cr ." Step Clock Mode" then BIT? 0= if cr ." Step Loss B" then BIT? 0= if cr ." Step Loss A" then BIT? 0= if cr ." Over Current" then BIT? 0= if cr ." Thermal Shutdown" then BIT? 0= if cr ." Thermal Warning" then BIT? 0= if cr ." Under voltage" then BIT? if cr ." Wrong command" then BIT? if cr ." Command not performed" then \ cr ." Speed = " @SPEED REG@ 2 INIT@ 1 INIT@ */ . ." RPM" dup 60 and 5 rshift dup 0= if ." stopped" then dup 1 = if ." accelerating" then dup 2 = if ." decelerating" then 3 = if ." constant" then \ 10 bit L! BIT? if ." forward" else ." reverse" then BIT? if cr ." Switch Event" then BIT? if cr ." Switch Closed" then BIT? 0= if cr ." Busy" then BIT? if cr ." Bridge disconnected" then cr ." Steps/full step = " @STEPMD REG@ 1 swap lshift . cr ." Input Voltage = " VOLTS decimal . ." V" else ." - No device " then drop ; \ ********************* DEMO & DEBUG ********************** \ \ Short diagnostic functions which simplify keyboard entry - especially via bluetooth smartphones ! \ List Registers ( in current number base ) \ Use the name for the register as provided in the compiled constant names (tricky) ' @POS _forthpfa>nfa constant regstr : .NAME 1- 4 lshift regstr + dup C@ 0F and swap 1+ over .str 0A swap - spaces ; hex \ List names and contents of registers of both MASTER and SLAVE as well as their default values : LR ." REG NAME MASTER SLAVE DEFAULT " \ 01: 0020571A 00000000 000000E7 1A 1 do cr i .byte 3A emit space i .NAME MASTER i REG@ .long space SLAVE i REG@ .long 4 spaces i INIT@ .long loop cr MASTER ; \ List the status of the chips : L \ List the status of the chip(s) for diagnostics \ busy and flag pins are common ina COG@ dup 2 and 0= if ." =busy " then 40 and 0= if ." =flag " then SLAVE GetStatus dup if cr ." --------SLAVE-------- " dup ShowStatus then drop cr MASTER GetStatus dup if cr ." --------MASTER-------- " dup ShowStatus then drop cr ; \ Stop both motors - very useful when testing : S CS SLAVE STOP MASTER STOP SELECT ; \ set step mode 0..7 (up the max on full step) example: 4 SM ( sets step mode to 4 = 16 ) : SM DISC dup @STEPMD REG! if 1C0 else 2FF then @MAX REG! ; \ write config register as in: 2EA8 CFG! : CFG! DISC @CONFIG REG! ; \ Set RUN current as in: 30 RC : RC @RUN REG! ; \ SET RUN CURRENT
Regarding the webcam demo, for a long time I've wanted to do something similar. I think it would really work well even just with a monitor in the corner. I have a canon vc-c1 camera with pan, tilt and 26x zoom, autofocus, great picture (its the same optics used in camcorders I think). Puts out composite video, and is controlled using RS232 stream. If this is any use I'm happy to send it up. Or I could set it up down here with the modules you send down.
Agreed re TeraTerm it's an outstanding little program especially at high baud rates. Hard to believe its been around for as long as it has, still keeps working great.
Anyone have any ideas how best to echo a telnet session onto the same webpage? The fallback is setting up a monitor in the webcam view.
I'd be happy to do some work on these. If you send out a second pair, I will forward them to Sal.
I've only just recently been using them in this manual mode where I issue the step clock pulses and all other parameters are done over SPI and I have been very impressed with the results. Now I find that ST have released the L6474 which is a dumbed down version in the same package, same pinout etc and half the price almost. The difference with the L6474 is that it "only" does 16 microsteps but it also has a separate DIR pin in place of the SW pin so you can set it up via SPI and just use these two pins most of the time. Since my SPI routines are fast I'm finding it's no problem to set the direction and current via SPI and just use the step clock.
I have posted code here and also on my Tachyon pages.
Oh, and for anyone who might be waiting on some of these modules sorry but please give me a nudge, I've been way too distracted to catch-up and ship these modules off. I do have plenty of stock so if anyone wants to purchase them I am happy to sell the L6470 modules to forum members for $29 USD each + $10 airmail.