Skip to content
Snippets Groups Projects
Select Git revision
  • e7f756a9551983097f4608e3d1749186b0848ad9
  • master default protected
2 results

README.md

Blame
  • fab-step-log.md NaN GiB
    ## 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. 
    
    ![routing](images/2020-11-16_routing.png)
    
    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. 
    
    ![routing](images/2020-11-17_routing.png)
    
    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. 
    
    ![route](images/2021-06-12_routed.png)
    ![schem](images/2021-06-12_schem.png)
    
    ## 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:
    
    ![route](images/2021-06-19_routed.png)
    ![schem](images/2021-06-19_schem.png)
    
    ## 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. 
    
    ![step](images/2022-01-10_fab-step-microstep.jpg)
    
    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;
    
    ```cpp
    #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.