fab-step-log.md
Log
2020 11 05
Started in, have the schematic mostly roughed out: this'll be 1.5 sided (solid GND below a routed layer). I think... the largest challenge is just getting things around themselves without using any vias. Found a tranciever as well.
2020 11 16
Just routed out the program / power / data interface side of this.
Success going forward will rely on a a fortuitous alignment of the RS485 interface pins against a SERCOM port somewhere on 11-16... not at all sure if any such alignment exists.
2020 11 17
Lucky me, those line up. I can put the SERCOM's TXPO at 0 (for TX on SER-0) and and RXPO at 3 (for RX on SER-3) and the middle two will do data enable and rx enable, just GPIO.
So, sorted that out. I think it works OK. I can make one of these in the fab-version, and can copy the schematic onto a smaller 2-layer board to fab lots of at a board house, having pins 17-20 free for an AS5047 on the back... same RS485 interface, maybe the QFN D21, and 0805s or smaller passives, pinch traces / spaces etc.
2021 06 12
Re-routed this for UCBus compatibility, still looks like the best option despite SPI availability: SPI interrupt handlers are minimum ~ 2us, meaning byte period of 2.6us (at 3MHz) is limiting, might as well use simplicity of UART, and ability / option for it to self-configure as P2P connection, etc. RS485 UART is same pin count as TTL SPI, would rather have noise / distance immunity.
I left off some pins (SERCOM0) to potentially add an encoder here, the routing for that would be tough but probably possible.
2021 06 19
Realized today that I had 5v, 24v lines on the plug optimistically configured for easier routing: the cable symmetry results in a more awkward routing which I've corrected, just had to squish the connector / RS485 bit up 1.5mm or so, so that I could wiggle those 5v and 24v lines beneath the connector:
2022 01 10
Back here but I am not working on the closed-loop version now... need to split these repos... writing code for the actually-fab-abble version.
I think I'm just going to get right into a step-tick rather than float-tick operation.
Though this means some re-work at the head first.
It's totally easy though, I write a little step mask in the motor interface class, get that on interrupt - I am even caching two so that I can get the full 10kHz rather than 5.
I think I need a config / setup on the js side.
OK this is almost jogging - I need some motor config, then I think I actually have some driver level debug to do, not unlikely with the VREF stuff.
H-Bridge : Code Alignment
It has come to my attention that I changed the pins on all of these things, and hadn't re-written to use the timer-counter rc filters, whoops.
Looking a lot better now that I sorted that haha - looks like I still need to scope the pwm'd lines, I am maybe flipping a phase improperly.
Yeah, something like that: microsteps increment back but flipping ticks forwards so I'm somehow misaligned.
had an 'a' where a 'b' was meant to be.
Now I'm just not seeing it hold while it's microstepping...
OK it's all up, and jogs around w/ the motion system, rad.
Homing Routine
Next thing I need is a little homing routine... I think I will do homingRate
in steps / second... rather than keep any other info in the motor.
This is still kind of a pain.
Great, homing works. It's stateful, that's why it's such a pain - and has to work all asynchronously;
#include "homing.h"
#include "drivers/step_a4950.h"
endpoint_t* _homeStateEP;
uint8_t homeState = HOMESTATE_NONE;
uint32_t homeBackoffStepsTaken = 0;
// home settings
boolean homeDir = true;
unsigned long lastHomeOperation = 0;
unsigned long homeOperationPeriod = 1000; // in us
uint32_t homeBackoffDistance = 100;
void homeSetup(endpoint_t* homeStateEP){
// stash this
_homeStateEP = homeStateEP;
// make an input
PORT->Group[LIMIT_PORT].DIRCLR.reg = (1 << LIMIT_PIN);
PORT->Group[LIMIT_PORT].PINCFG[LIMIT_PIN].bit.INEN = 1;
// pullup
PORT->Group[LIMIT_PORT].OUTSET.reg = (1 << LIMIT_PIN);
}
// return true if limit switch is hit
boolean limitHit(void){
return (PORT->Group[LIMIT_PORT].IN.reg & (1 << LIMIT_PIN));
}
void writeHomeSettings(boolean dir, uint32_t stepsPerSecond, uint32_t offset){
homeDir = dir;
homeOperationPeriod = 1000000 / stepsPerSecond;
homeBackoffDistance = offset;
}
uint8_t getHomeState(void){
return homeState;
}
void startHomingRoutine(void){
homeState = HOMESTATE_APPROACH;
endpointWrite(_homeStateEP, &homeState, 1);
}
void runHomingRoutine(void){
// run this at a rate...
if(lastHomeOperation + homeOperationPeriod > micros()) return;
lastHomeOperation = micros();
// state switch;
switch(homeState){
case HOMESTATE_NONE:
break;
case HOMESTATE_APPROACH:
// check for contact,
if(limitHit()){
homeState = HOMESTATE_BACKOFF;
endpointWrite(_homeStateEP, &homeState, 1);
homeBackoffStepsTaken = 0;
} else {
step_a4950_dir(homeDir);
step_a4950_step();
}
break;
case HOMESTATE_BACKOFF:
step_a4950_dir(!homeDir);
step_a4950_step();
homeBackoffStepsTaken ++;
if(homeBackoffStepsTaken > homeBackoffDistance){
homeState = HOMESTATE_NONE;
endpointWrite(_homeStateEP, &homeState, 1);
}
break;
default:
// broken,
homeState = HOMESTATE_NONE;
endpointWrite(_homeStateEP, &homeState, 1);
break;
}
}
Now I just want to touch up the motor APIs in JS, and add the steps-per-unit adjust stuff in the motion-head, etc... I should be pretty close now.
Power State API
Just a bunch of buttons, turns out to not be so bad. Done.
New Motor API and JS Config
This should actually be chill... it's working after all, right?
I'm setting the SPUs in the motion-head now... meaning I could also calculate / guard against max rates there.
- motion-head things
- steps per unit
- max accels
- max rates
- motor things
- direction inversion
- microstepping
- axis picking
OK I've diffed all that... need to make a microstep update actually do something, then this adventure is over.
11752 / 24584 12520 / 24976
Done, for the time being. Probably needs in-mcu guards against large rates.