Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
1 result

ucbus-stepper-log.md

Blame
  • ucbus-stepper-log.md 23.92 KiB

    UCBus Stepper Driver Log

    Notes for Next Rev

    2021 01 11

    • add endstop option pinout
    • build with encoder placed,
    • choose sense R for more current potential
    • try to make SPI lines to encoder cleaner: these can go ~ 20MHz
    • fix the jtag pinout

    2020 10 06

    Consider doing a very simple version of this that is D21, A4954 dual h-bridge, AS5047 (option), no crystals, etc...

    2020 09 21

    Have these back, am testing. Have a JTAG pinout error, obviously didn't check very well. 3v3 and GND connect at the header - not cool. Only when plugged in is this an issue, I think I can just remove a pin...

    Oh lawd, that works, godbless the hotfix.

    2020 08 18

    I'd like to make a dedicated step board, there will be many of these. I should follow the existing pinout. Would like to:

    • flip it, side mount LEDs (find clk and err lines that will match later module revision) and reset button pinch
    • heatsink on the flip
    • AS5047P on the IC side
    • debug on 'top' flipped side, if space, else use module type to debug
    • add temp sensor RTD
    • smaller sense resistors, spec to go full-er width at 3v3, currently only does 1.6A or so?
    • does a slightly different A4950 exist with OCP / Temp Shutdown pin exist?
    • still some observable oddball stepper behaviour: when turnt on, then left, eventually you might hear some clicking / see motors draw less current, then spike back up. I would guess at a DAC refresh issue, but am not sure.
    • might want / probably do want the hold-down shrouds for IDCs

    For JTAG: just do 'lock' 2x5 0.050" header, don't have to solder, can use straight header once for debug, solder on if flashing more often. Less BOM cheaper PNP.

    2020 07 27

    • A4950 lower / heat pad: bigger holes to hand solder thru, or / and exposed flags on top to see that wicking has happened
    • 0.2 ohm sense resistor means maximum current per channel is 1.65A, this is OK, things get hot around there, could be nice to have more headroom.

    Components (roughly!)

    Part PN
    2x5 Shrouded ED1543-ND
    A4950 620-1400-1-ND‎
    Cap 150uF 35v SMD 6.6mm 565-5148-1-ND
    TVS Diode SMAJ30ALFDKR-ND
    2010 Current Sense Resistor, 0.2Ohm 1W do 0.1Ohm now
    1206 10uF 35v Ceramic Cap ‎GMK316BJ106KL-T‎
    0805 0.1uF 35v Ceramic Cap ‎C0805C104Z5VACTU‎
    0805 120R ‎ CRGCQ0805F120R‎
    0805 1k ‎RC0805JR-071KL‎
    0805 10k RC0805FR-0710KL‎
    Screw Terminal 3.5mm Pitch 277-1860-ND‎
    Side Headers (Debug) 1849-PM20206HBNN-ND
    Part PN
    LED Side Mount 0603 Green 160-1478-1-ND
    Red 160-1479-1-ND
    Yellow 160-1480-1-ND
    Right Angle Reset P16767CT-ND
    Latching Shrouded Connector 71918-210LF
    Big DIP 219-8LPSTRF
    0805 22uF 35v 445-14428-1-ND
    0.1 Ohm Sense R 1W 1206 P.10AUCT-ND
    Side Reset EVQ-P7J01P

    2021 01 13

    Ordering a handful more of these, so I'm adding an endstop pin.

    Deltas are:

    • add endstop pin
    • spec 100mOhm sense r, not 0.2 as previous
    • spec place for AS5047P
    • fixed the jtag pinout

    2020 08 20

    I'm getting into a redesign for these, going to melt the module circuit on board and try to fit it to an N14 footprint.

    OK, I think the schematic is there, now I just need to adjust the sense R value, add a temperature sensor, and expand the shroud document for clips... Then I'm into the routing adventure. The A5950 exists, which is bigger / fancier than the A4950, but slightly smaller current. It has a different interface (not greatly) and can report thermal events / other faults... It also has an analog sense output, for the cases where I might want to actually read the top of the sense resistor. Probably this isn't worth it for now, I'll continue with the A4950. It works.

    Can get away with a 1206 1W sense resistor, rad.

    This is going to be a pain, it's pinched.

    Also, the DIP switch... won't be accessible from the top. Yikes. I could eat it, and setup DIPs before they go down, or I could solder it on top manually, getting a bigger component to make that easier. This is the only real full stop issue... and it also saves some space.

    Yikes. Yeah, I guess DIPs on the rear are the move. Maybe eventually the bus protocol becomes mature enough to support auto-config at startup and then EEPROM / Flash memory allows local storage of 'drop #' configuration from the UI. For now, whatever, solder on top.

    To route, my biggest Q is about the motor side routing: nice GND paths for sense Rs, big traces out to motors. Heat. I think I am working this out OK... I also need to ground the bottom of the power caps... Did that through the same GND vias as the sense R is pulling from. And finally, some big GND heat-spreaders on top...

    For thermal measurement, then, I would properly put two RTD sensors on, one for each bridge. The bridges are separated by about 20mm, not sure how long it would take a heat up to spread between the two, but I guess it's short enough, I'll just tap the center with one RTD. Not even using this yet, so... that's fine.

    pwr

    That's enough for tonight! Tomorrow I am hopeful I can get through the micro support etc and the actual business. But these polygons feel good.

    2020 08 21

    Lettuce see if this can go complete today, and ... BOMs out as well? The dream.

    unorg

    I'm feeling generally unorganized with this. The IDC really crash lands right in the middle of everything. Maybe these things are just messy.

    Alright, tucking the RS485 driver up a little makes me feel better about the thing aesthetically, which anyways is whatever. I think it's about fine, I'll get into routing.

    Woof, the monster DIP and the latching connector alone really claim the whole back side of this thing.

    Routing... I think I'll do the power side first.

    It's just occurred to me that the DIP switch will prevent solid heat sinking on the bottom layer. That's a shame but I guess it'll be impetus to eliminate the need for DIPs. If I'm not careful this thing is really going to F my monolithic GND as well.

    OK, wowowee... just routing power now. Thing is a nightmare, I hope I haven't set up any gnd loops or othery mayhem...

    I am just nearly through this, have to route out one last piece of the 24v net, then do checks etc.

    Damn, I have also just seen that the screw terminals can't be mounted when a latched IDC is used. I'm OK with this, prefer to solder motor leads on directly anyways, but it'd be better to have the terminals... I think that's just going to have to be OK. Sorry everyone.

    Well, it passes the DRC. I've made all of the adjustments. I think it's just BOM and MacroFab then.

    2020 08 12

    I have a smoothieware port running inside of these, here it is making steps. Next is connecting that to a browser to send paths, then syncing smoothie instances across motors via the ucbus.

    spinning

    2020 07 28

    DAC MicroStepping

    So, moving to microstepping actually should be kind of fun. Generate a sine table, do current in divs of that to avoid awkward scalings of the table, then make DAC writes on some steps, pin inversions when crossing zero markings at 2, 4, 6, 8, etc. Party on.

    // sequence like
    // S: 1 2 3 4 5 6 7 8 
    // A: ^ ^ ^ x v v v x
    // B: ^ x v v v x ^ ^

    So... I want a sine table, then to increment through that table at each 'step' and when I hit a zero crossing, flip bits. I can start coils 90' out of phase, and just step together.

    I'd be totally fine with 1/16 microstepping, I'll write a table for 256 steps and can change the increment step to adjust.

    Great, I've this doing 256 microsteps, the code is pretty similar, but looking from a LUT and tracking position within that table.

    // sine, 0-1022 (511 center / 'zero'), 256 steps 
    uint16_t LUT[256] = {
        511,524,536,549,561,574,586,598,611,623,635,647,659,671,683,695,
        707,718,729,741,752,763,774,784,795,805,815,825,835,845,854,863,
        872,881,890,898,906,914,921,929,936,943,949,956,962,967,973,978,
        983,988,992,996,1000,1003,1007,1010,1012,1014,1016,1018,1020,1021,1021,1022,
        1022,1022,1021,1021,1020,1018,1016,1014,1012,1010,1007,1003,1000,996,992,988,
        983,978,973,967,962,956,949,943,936,929,921,914,906,898,890,881,
        872,863,854,845,835,825,815,805,795,784,774,763,752,741,729,718,
        707,695,683,671,659,647,635,623,611,598,586,574,561,549,536,524,
        511,498,486,473,461,448,436,424,411,399,387,375,363,351,339,327,
        315,304,293,281,270,259,248,238,227,217,207,197,187,177,168,159,
        150,141,132,124,116,108,101,93,86,79,73,66,60,55,49,44,
        39,34,30,26,22,19,15,12,10,8,6,4,2,1,1,0,
        0,0,1,1,2,4,6,8,10,12,15,19,22,26,30,34,
        39,44,49,55,60,66,73,79,86,93,101,108,116,124,132,141,
        150,159,168,177,187,197,207,217,227,238,248,259,270,281,293,304,
        315,327,339,351,363,375,387,399,411,424,436,448,461,473,486,498,
    };

    From that sine table, which has zero around 511 (is 0-1022 full swing), I rectify a DAC output table - I can also change C_SCALE here to adjust current.

    void STEP_A4950::init(){
        // all of 'em, outputs 
        AIN1_PORT.DIRSET.reg = AIN1_BM;
        AIN2_PORT.DIRSET.reg = AIN2_BM;
        BIN1_PORT.DIRSET.reg = BIN1_BM;
        BIN2_PORT.DIRSET.reg = BIN2_BM;
        // transform full sine table for DAC table 
        // i.e. rectify... 
        for(uint16_t i = 0; i < 256; i ++){
            if(LUT[i] > 511){
                dacLUT[i] = (LUT[i] - 511) * C_SCALE;
            } else if (LUT[i] < 511){
                dacLUT[i] = abs(511 - LUT[i]) * C_SCALE;
            } else {
                dacLUT[i] = 0;
            }
        }
        // start condition, 
        step();
    }
    void STEP_A4950::step(void){
        // increment: wrapping comes for free with uint8_t 
        if(_dir){
            _aStep ++;
            _bStep ++;
        } else {
            _aStep --;
            _bStep --;
        }
        // a phase, 
        if(LUT[_aStep] > 511){
            A_UP;
        } else if (LUT[_aStep] < 511){
            A_DOWN;
        } else {
            A_OFF;
        }
        // a DAC 
        dacs->writeDac0(dacLUT[_aStep]);
        // b phase, 
        if(LUT[_bStep] > 511){
            B_UP;
        } else if (LUT[_bStep] < 511){
            B_DOWN;
        } else {
            B_OFF;
        }
        // b DAC
        dacs->writeDac1(dacLUT[_bStep]);
    }

    micros-o1 micros-o2 micros-o3