Shop OBEX P1 Docs P2 Docs Learn Events
L6470 Microstepper (128 step) sample Forth code - Page 2 — Parallax Forums

L6470 Microstepper (128 step) sample Forth code

2

Comments

  • prof_brainoprof_braino Posts: 4,313
    edited 2012-02-23 14:06
    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.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-20 22:56
    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?
  • TubularTubular Posts: 4,703
    edited 2012-03-20 23:27
    I think you're into brushless servo kind of territory, assuming the normal process speed is slow.

    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?
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-20 23:51
    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.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-22 06:47
    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.

    34HY1801 torque curves.png
    512 x 474 - 45K
  • photomankcphotomankc Posts: 943
    edited 2012-03-22 10:35
    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'm over here, patiently waiting (drums fingers!) :)
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-03-22 19:00
    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.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-22 20:01
    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 :)
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-25 21:23
    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.
  • idbruceidbruce Posts: 6,197
    edited 2012-03-26 02:09
    Peter
    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.

    Bruce
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-26 06:49
    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.
  • idbruceidbruce Posts: 6,197
    edited 2012-03-26 07:01
    Peter

    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
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-26 07:11
    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.
  • idbruceidbruce Posts: 6,197
    edited 2012-03-26 07:14
    Peter

    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
  • idbruceidbruce Posts: 6,197
    edited 2012-03-28 14:03
    Peter

    I just received three of the L6470HTR. Talk about small, these things are tiny :) How do you manage to work with them? WOW :)
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-28 16:56
    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 ;
    { 
    *************************************************************
    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 ;
    
    
  • lardomlardom Posts: 1,659
    edited 2012-03-28 20:07
    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.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-28 20:28
    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.
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-03-29 07:15
    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).

    Thanks!
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-03-29 08:05
    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.
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-03-31 08:17
    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.
  • dlidli Posts: 2
    edited 2012-04-02 02:50
    Hello,

    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
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-04-02 05:25
    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???
  • dlidli Posts: 2
    edited 2012-04-02 06:51
    Ok thank you for the answer.

    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
  • chazschazs Posts: 1
    edited 2012-06-14 12:08
    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
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-06-15 07:13
    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.
    P1121 Stepper PCB-x.jpeg


    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
    
    1024 x 738 - 233K
  • TubularTubular Posts: 4,703
    edited 2012-06-15 16:39
    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.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-06-15 18:58
    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.
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-06-16 14:08
    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.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-10-05 07:11
    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.
Sign In or Register to comment.