ucbus-stepper-log.md
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.
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.
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.
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]);
}