diff --git a/circuit/2020-11_fab-step/eagle.epf b/circuit/2020-11_fab-step/eagle.epf index a9c4b6ac6388520e581777738cffbc94ec70fdcb..bc2ff5bedbfb946622f6e940a2a3ac21b80d3d71 100644 --- a/circuit/2020-11_fab-step/eagle.epf +++ b/circuit/2020-11_fab-step/eagle.epf @@ -116,7 +116,7 @@ Layer=21 Type="Schematic Editor" Number=1 File="fab-step.sch" -View="87.6168 -43.7485 319.799 131.814" +View="35.0399 -95.0566 436.251 208.315" WireWidths=" 0.0762 0.1016 0.127 0.15 0.2 0.2032 0.254 0.3048 0.4064 0.508 0.6096 0.8128 1.016 1.27 2.54 0.1524" PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" PadDrills=" 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6" @@ -155,7 +155,7 @@ ArcDirection=0 AddLevel=2 PadsSameType=0 Layer=97 -Views=" 1: 87.6168 -43.7485 319.799 131.814" +Views=" 1: 35.0399 -95.0566 436.251 208.315" Sheet="1" [Win_4] @@ -163,7 +163,7 @@ Type="Control Panel" Number=0 [Desktop] -Screen="1920 1080" +Screen="3171 2520" Window="Win_1" Window="Win_2" Window="Win_3" diff --git a/firmware/fab-step/src/drivers/step_a4950.cpp b/firmware/fab-step/src/drivers/step_a4950.cpp index 244a8f29e2cfbdd32181e1f06e86eed7a461b875..8dde6b9b38302de7af69538494419bac47d38d0d 100644 --- a/firmware/fab-step/src/drivers/step_a4950.cpp +++ b/firmware/fab-step/src/drivers/step_a4950.cpp @@ -13,6 +13,7 @@ is; no warranty is provided, and users accept all liability. */ #include "step_a4950.h" +#include "../indicators.h" // LUT, 0-1022, 64 entries, sin w/ 511 at midpoint uint16_t LUT_1022[64] = { @@ -21,42 +22,58 @@ uint16_t LUT_1022[64] = { 511,461,411,363,315,270,227,187,150,116,86,60,39,22,10,2, 0,2,10,22,39,60,86,116,150,187,227,270,315,363,411,461, }; - +// on init / cscale, we write new values into this thing, which is where +// we actually pull currents from, for the h-bridges uint16_t LUT_CURRENTS[64]; // startup stepper hardware void step_a4950_init(void){ + // ------------------------------------------ DIR PINS // 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; - // setup DAC for CHB (dac is 10 bit) - DAC->CTRLA.bit.ENABLE = 0; - DAC->CTRLB.reg |= DAC_CTRLB_REFSEL_INT1V; // I think this is 3v3, not sure - DAC->CTRLA.bit.ENABLE = 1; - // setup TCC0-1 / PA05 - // set pin as output, - AVREF_PORT.DIRSET.reg = AVREF_BM; - // mux pin onto peripheral, it's peripheral E, and *odd numbered pin* - AVREF_PORT.PINCFG[AVREF_PIN].reg |= PORT_PINCFG_PMUXEN; - AVREF_PORT.PMUX[AVREF_PIN >> 1].reg = PORT_PMUX_PMUXO_E; + // ------------------------------------------ TCC SETUPS // s/o https://blog.thea.codes/phase-shifted-pwm-on-samd/ // unmask the peripheral, - PM->APBCMASK.reg |= PM_APBCMASK_TCC0; + PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1; // route this clk (on 0) to our peripheral GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // (?) GCLK_CLKCTRL_GEN_GCLK0 | // select 0: already generated main clk GCLK_CLKCTRL_ID_TCC0_TCC1; // route to TCC0 / TCC1 while(GCLK->STATUS.bit.SYNCBUSY); + // ------------------------------------------ AVREF TCC + // setup TCC1-1 / PA07 + // set pin as output, + AVREF_PORT.DIRSET.reg = AVREF_BM; + // mux pin onto peripheral, it's peripheral E, and *odd numbered pin* + AVREF_PORT.PINCFG[AVREF_PIN].reg |= PORT_PINCFG_PMUXEN; + AVREF_PORT.PMUX[AVREF_PIN >> 1].reg = PORT_PMUX_PMUXO_E; + // prescaler: we will probably go very fast, for now I want to see it + TCC1->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1; + TCC1->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; + while(TCC1->SYNCBUSY.bit.WAVE); + TCC1->PER.reg = 128; + while(TCC1->SYNCBUSY.bit.PER); + TCC1->CC[1].reg = 0; + TCC1->CTRLA.bit.ENABLE = 1; + // ------------------------------------------ BVREF TCC + // setup TCC0-0 / PA04 + // set pin as output, + BVREF_PORT.DIRSET.reg = BVREF_BM; + // mux pin onto peripheral, it's peripheral E, and *even numbered pin* + BVREF_PORT.PINCFG[BVREF_PIN].reg |= PORT_PINCFG_PMUXEN; + BVREF_PORT.PMUX[BVREF_PIN >> 1].reg = PORT_PMUX_PMUXE_E; // prescaler: we will probably go very fast, for now I want to see it TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1; TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; while(TCC0->SYNCBUSY.bit.WAVE); TCC0->PER.reg = 128; while(TCC0->SYNCBUSY.bit.PER); - TCC0->CC[1].reg = 0; + TCC0->CC[0].reg = 0; TCC0->CTRLA.bit.ENABLE = 1; + // ------------------------------------------ INIT // now, setup current table, default to 0.0 (disabled). step_a4950_set_cscale(0.0F); // push a step to init up/down states @@ -83,15 +100,19 @@ void step_a4950_set_cscale(float scale){ LUT_CURRENTS[i] = 0; } } + // we need to publish these updates: + step_a4950_publish_currents(); +} + +void step_a4950_set_microstep(uint8_t microstep){ + // } // step states boolean _dir = true; // current direction boolean _dirInvert = false; // invert directions ? -uint8_t lutptra = 16; // current pt. in microstep phase -uint8_t lutptrb = 0; // A leads B by 1/4 period - -uint8_t cntr = 0; +uint8_t lutptra = 16; // current pt. in microstep phase +uint8_t lutptrb = 0; // A leads B by 1/4 period void step_a4950_step(){ // step LUT ptrs thru table, @@ -117,12 +138,14 @@ void step_a4950_step(){ } else { B_OFF; } - // set vref currents: this is messy at this rev we have DAC and TC, should be two TCs - // that was a circuit bug: note division as well, >> 3 is removing smallest 3 bits - TCC0->CC[1].reg = LUT_CURRENTS[lutptra] >> 3; // TC resolution is 0-128 (7 bit) - DAC->DATA.reg = LUT_CURRENTS[lutptrb]; // DAC resolution is 0-1024 (10 bit) + step_a4950_publish_currents(); } +void step_a4950_publish_currents(void){ + // set vref currents via these rc flter / pwms + TCC1->CC[1].reg = LUT_CURRENTS[lutptra] >> 3; // TC resolution is 0-128 (7 bit) + TCC0->CC[0].reg = LUT_CURRENTS[lutptrb] >> 3; +} // set direction void step_a4950_dir(boolean dir){ if(_dirInvert){ diff --git a/firmware/fab-step/src/drivers/step_a4950.h b/firmware/fab-step/src/drivers/step_a4950.h index a521415e9cd5ddd2245bea64a07617ae02422734..63ec2304a0e1c22238dcc08a2421fd036f51c69d 100644 --- a/firmware/fab-step/src/drivers/step_a4950.h +++ b/firmware/fab-step/src/drivers/step_a4950.h @@ -17,20 +17,20 @@ is; no warranty is provided, and users accept all liability. #include <arduino.h> -// AIN1 PA06 -// AIN2 PA07 -// BIN1 PA03 -// BIN2 PA04 -#define AIN1_PIN 6 +// AIN1 PA14 +// AIN2 PA15 +// BIN1 PA05 +// BIN2 PA06 +#define AIN1_PIN 14 #define AIN1_PORT PORT->Group[0] #define AIN1_BM (uint32_t)(1 << AIN1_PIN) -#define AIN2_PIN 7 +#define AIN2_PIN 15 #define AIN2_PORT PORT->Group[0] #define AIN2_BM (uint32_t)(1 << AIN2_PIN) -#define BIN1_PIN 3 +#define BIN1_PIN 5 #define BIN1_PORT PORT->Group[0] #define BIN1_BM (uint32_t)(1 << BIN1_PIN) -#define BIN2_PIN 4 +#define BIN2_PIN 6 #define BIN2_PORT PORT->Group[0] #define BIN2_BM (uint32_t)(1 << BIN2_PIN) @@ -53,15 +53,21 @@ is; no warranty is provided, and users accept all liability. #define B_OFF BIN2_LO; BIN1_LO #define B_DOWN BIN1_LO; BIN2_HI -// BVREF via PA02 / DAC -// AVREF via PA05 / TCC0-1 RC Filt +// AVREF via PA07 / TCC1-1 +// BVREF via PA04 / TCC0-0 -#define AVREF_PIN 5 +#define AVREF_PIN 7 #define AVREF_PORT PORT->Group[0] #define AVREF_BM (uint32_t)(1 << AVREF_PIN) +#define BVREF_PIN 4 +#define BVREF_PORT PORT->Group[0] +#define BVREF_BM (uint32_t)(1 << BVREF_PIN) + void step_a4950_init(void); void step_a4950_set_cscale(float scale); +void step_a4950_publish_currents(void); +void step_a4950_set_microstep(uint8_t microstep); void step_a4950_step(); void step_a4950_dir(boolean dir); diff --git a/firmware/fab-step/src/indicators.h b/firmware/fab-step/src/indicators.h index c0fffc7f305cbfbd6d9ba09858aab7bcbe18f59c..34403457eba150b160630d771d5b6d3324ff3060 100644 --- a/firmware/fab-step/src/indicators.h +++ b/firmware/fab-step/src/indicators.h @@ -7,41 +7,24 @@ #define PIN_SETUP_OUTPUT(port, pin) PORT->Group[port].DIRSET.reg = PIN_BM(pin) // PA23 -#define CLKLIGHT_PIN 23 -#define CLKLIGHT_PORT PORT->Group[0] -#define CLKLIGHT_BM (uint32_t)(1 << CLKLIGHT_PIN) -#define CLKLIGHT_ON CLKLIGHT_PORT.OUTSET.reg = CLKLIGHT_BM -#define CLKLIGHT_OFF CLKLIGHT_PORT.OUTCLR.reg = CLKLIGHT_BM -#define CLKLIGHT_TOGGLE CLKLIGHT_PORT.OUTTGL.reg = CLKLIGHT_BM -#define CLKLIGHT_SETUP CLKLIGHT_PORT.DIRSET.reg = CLKLIGHT_BM; CLKLIGHT_OFF +#define CLKLIGHT_ON PIN_HI(0, 23) +#define CLKLIGHT_OFF PIN_LO(0, 23) +#define CLKLIGHT_TOGGLE PIN_TGL(0, 23) +#define CLKLIGHT_SETUP PIN_SETUP_OUTPUT(0, 23) // PA22 -#define BUSLIGHT_PIN 22 -#define BUSLIGHT_PORT PORT->Group[0] -#define BUSLIGHT_BM (uint32_t)(1 << BUSLIGHT_PIN) -#define BUSLIGHT_ON BUSLIGHT_PORT.OUTSET.reg = BUSLIGHT_BM -#define BUSLIGHT_OFF BUSLIGHT_PORT.OUTCLR.reg = BUSLIGHT_BM -#define BUSLIGHT_TOGGLE BUSLIGHT_PORT.OUTTGL.reg = BUSLIGHT_BM -#define BUSLIGHT_SETUP BUSLIGHT_PORT.DIRSET.reg = BUSLIGHT_BM; BUSLIGHT_OFF +#define BUSLIGHT_ON PIN_HI(0, 22) +#define BUSLIGHT_OFF PIN_LO(0, 22) +#define BUSLIGHT_TOGGLE PIN_TGL(0, 22) +#define BUSLIGHT_SETUP PIN_SETUP_OUTPUT(0, 22) // probably would use the limit conn, that's // PA03 -#define DEBUG1PIN_PIN 3 -#define DEBUG1PIN_PORT PORT->Group[0] -#define DEBUG1PIN_BM (uint32_t)(1 << DEBUG1PIN_PIN) -#define DEBUG1PIN_ON DEBUG1PIN_PORT.OUTSET.reg = DEBUG1PIN_BM -#define DEBUG1PIN_OFF DEBUG1PIN_PORT.OUTCLR.reg = DEBUG1PIN_BM -#define DEBUG1PIN_TOGGLE DEBUG1PIN_PORT.OUTTGL.reg = DEBUG1PIN_BM -#define DEBUG1PIN_SETUP DEBUG1PIN_PORT.DIRSET.reg = DEBUG1PIN_BM; DEBUG1PIN_OFF - -// the "bus light" : led pts to gnd -#define DEBUG2PIN_PIN 22 -#define DEBUG2PIN_PORT PORT->Group[0] -#define DEBUG2PIN_BM (uint32_t)(1 << DEBUG2PIN_PIN) -#define DEBUG2PIN_ON DEBUG2PIN_PORT.OUTSET.reg = DEBUG2PIN_BM -#define DEBUG2PIN_OFF DEBUG2PIN_PORT.OUTCLR.reg = DEBUG2PIN_BM -#define DEBUG2PIN_TOGGLE DEBUG2PIN_PORT.OUTTGL.reg = DEBUG2PIN_BM -#define DEBUG2PIN_SETUP DEBUG2PIN_PORT.DIRSET.reg = DEBUG2PIN_BM; DEBUG2PIN_OFF +#define DEBUG1PIN_ON PIN_HI(0, 3) +#define DEBUG1PIN_OFF PIN_LO(0, 3) +#define DEBUG1PIN_TOGGLE PIN_TGL(0, 3) +#define DEBUG1PIN_SETUP PIN_SETUP_OUTPUT(0, 3) +// deadies for sysError #define ERRLIGHT_ON #define ERRLIGHT_OFF diff --git a/firmware/fab-step/src/main.cpp b/firmware/fab-step/src/main.cpp index bda9e3f3aaa96d7d4438ffb32fd48e4b89d3b45d..d15ba6a0f07f85dfc84cc1ca5b1240fc4afeef4a 100644 --- a/firmware/fab-step/src/main.cpp +++ b/firmware/fab-step/src/main.cpp @@ -2,96 +2,150 @@ #include "indicators.h" #include "config.h" -//#include "drivers/step_a4950.h" +#include "drivers/step_a4950.h" #include "osape-d21/osape/osap/osap.h" #include "osape-d21/vertices/vt_usbSerial.h" #include "osape-d21/vertices/ucbus/vt_ucBusDrop.h" #include "osape-d21/vertices/ucbus/ucBusDrop.h" -// bus light on PA22, to flip: +uint8_t axisPick = 0; +boolean invert = false; -EP_ONDATA_RESPONSES onDemoData(uint8_t* data, uint16_t len){ - DEBUG2PIN_TOGGLE; +// -------------------------------------------------------- AXIS PICK EP + +EP_ONDATA_RESPONSES onAxisPickData(uint8_t* data, uint16_t len){ + if(data[0] > 3){ + axisPick = 0; + } else { + axisPick = data[0]; + } return EP_ONDATA_ACCEPT; } -vertex_t* demoEP = osapBuildEndpoint("demo", onDemoData, nullptr); +endpoint_t* axisPickEp = osapBuildEndpoint("axisPick", onAxisPickData); + +// -------------------------------------------------------- AXIS INVERSION EP + +EP_ONDATA_RESPONSES onAxisInvertData(uint8_t* data, uint16_t len){ + data[0] ? invert = true : invert = false; + return EP_ONDATA_ACCEPT; +} -/* +endpoint_t* axisInvertEp = osapBuildEndpoint("axisInvert", onAxisInvertData); -// -------------------------------------------------------- Axis Pick +// -------------------------------------------------------- MICROSTEP EP -boolean onAxisPickData(uint8_t* data, uint16_t len){ - ERRLIGHT_TOGGLE; - return true; +EP_ONDATA_RESPONSES onMicrostepData(uint8_t* data, uint16_t len){ + step_a4950_set_microstep(data[0]); + return EP_ONDATA_ACCEPT; } -vertex_t* axisPickEp = osapBuildEndpoint("axisPick", onAxisPickData, nullptr); +endpoint_t* microstepEp = osapBuildEndpoint("microstep", onMicrostepData); -// -------------------------------------------------------- Axis Invert +// -------------------------------------------------------- SPU EP -vertex_t* axisInvertEp = osapBuildEndpoint("axisInvert", nullptr, nullptr); +EP_ONDATA_RESPONSES onSPUData(uint8_t* data, uint16_t len){ + // doesn't do anything w/ step-on-tick situation + return EP_ONDATA_ACCEPT; +} -// -------------------------------------------------------- SPU +endpoint_t* spuEp = osapBuildEndpoint("SPU", onSPUData, nullptr); -vertex_t* spuEp = osapBuildEndpoint("steps per unit", nullptr, nullptr); +// -------------------------------------------------------- CSCALE DATA -// -------------------------------------------------------- CScale +EP_ONDATA_RESPONSES onCScaleData(uint8_t* data, uint16_t len){ + chunk_float32 cscalec = { .bytes = { data[0], data[1], data[2], data[3] } }; + if(cscalec.f > 1.0F){ + cscalec.f = 1.0F; + } else if (cscalec.f < 0.0F){ + cscalec.f = 0.0F; + } + step_a4950_set_cscale(cscalec.f); + return EP_ONDATA_ACCEPT; +} -vertex_t* cScaleEp = osapBuildEndpoint("currentScale", nullptr, nullptr); +endpoint_t* cScaleEp = osapBuildEndpoint("CScale", onCScaleData); -// -------------------------------------------------------- Homing +// -------------------------------------------------------- HOME ROUTINE + +EP_ONDATA_RESPONSES onHomeData(uint8_t* data, uint16_t len){ + return EP_ONDATA_ACCEPT; +} + +endpoint_t* homeEp = osapBuildEndpoint("Home", onHomeData); + +// -------------------------------------------------------- HOME STATE -*/ +endpoint_t* homeStateEp = osapBuildEndpoint("HomeState"); + +// -------------------------------------------------------- Homing // -------------------------------------------------------- SETUP void setup() { CLKLIGHT_SETUP; - //BUSLIGHT_SETUP; + BUSLIGHT_SETUP; DEBUG1PIN_SETUP; - // setup demo light - DEBUG2PIN_SETUP; // osap setup... - osapSetup(); + osapSetup("fab-step"); vt_usbSerial_setup(); osapAddVertex(vt_usbSerial); vt_ucBusDrop_setup(false, 2); osapAddVertex(vt_ucBusDrop); - // demo endpoint (?) - osapAddVertex(demoEP); - // startup stepper HW - // step_a4950_init(); - // step_a4950_set_cscale(0.25F); - // startup 1st vertex as usbserial entrance, - //vt_usbSerial_setup(); - //osapAddVertex(vt_usbSerial); // 0 - //osapAddVertex(spiBusDummy); // 1 - //osapAddVertex(axisPickEp); // 2 - //osapAddVertex(axisInvertEp); // 3 + // motor API + // axis pick + osapAddEndpoint(axisPickEp); // 2 + // axis invert + osapAddEndpoint(axisInvertEp); // 3 + // microstep + osapAddEndpoint(microstepEp); // 4 + // SPU + osapAddEndpoint(spuEp); // 5 + // cscale + osapAddEndpoint(cScaleEp); // 6 + // homing + osapAddEndpoint(homeEp); // 7 + osapAddEndpoint(homeStateEp); // 8 + // step hardware init + step_a4950_init(); } // -------------------------------------------------------- LOOP -#define CLK_TICK 100 +#define CLK_TICK 50 unsigned long last_tick = 0; void loop() { - // DEBUG2PIN_TOGGLE; // do osap things, osapLoop(); // blink if(millis() > last_tick + CLK_TICK){ - //step_a4950_step(); + // step_a4950_step(); last_tick = millis(); } } -void ucBusDrop_onPacketARx(uint8_t* inBufferA, volatile uint16_t len){ +uint8_t stepCache[2]; +volatile uint8_t cachePtr = 0; +volatile boolean stepValid = false; +volatile uint8_t stepMask = 0; +void ucBusDrop_onPacketARx(uint8_t* inBufferA, volatile uint16_t len){ + // refill step cache: + stepCache[0] = inBufferA[0]; stepCache[1] = inBufferA[1]; + cachePtr = 0; + stepValid = true; } void ucBusDrop_onRxISR(void){ - + // if we dont' have valid steps, bail + if(!stepValid) return; + // extract our step mask + stepMask = 0b00000011 & (stepCache[cachePtr] >> (axisPick * 2)); + // mask -> step api: + (stepMask & 0b00000001) ? step_a4950_dir(true) : step_a4950_dir(false); // dir bit, + if (stepMask & 0b00000010) step_a4950_step(); // step bit + // increment ptr -> next step mask, if over-wrap, steps no longer valid + cachePtr ++; if(cachePtr >= 2) stepValid = false; } \ No newline at end of file diff --git a/log/fab-step-log.md b/log/fab-step-log.md index c0b5d3fca21bcc92331d885ae66c53876c2d4ebb..9e8e8ec038da5eb9060dc930f024fb641ab00ce2 100644 --- a/log/fab-step-log.md +++ b/log/fab-step-log.md @@ -195,5 +195,36 @@ I = 3.3 / (0.5) -> I = 6.6 -> a lot of amps at full spec, decreasing my effectiv 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. -- pull new osape -- indicators \ No newline at end of file +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. + +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. + +- check that 'microstep' config does what it claims +- microstep image +- bring motor config back to JS side +- we need a homing routine still, write this little statemachine pls ! +- now ... we need to reconsider how / whomst makes SPU / dir configs, etc + - inversion is per-motor + - so is microstepping + - so is the axis pick + - spu is per-axis in the head \ No newline at end of file diff --git a/log/images/2022-01-10_fab-step-microstep.jpg b/log/images/2022-01-10_fab-step-microstep.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0287727bec361060f0bdaec2cc995108ae8177cc Binary files /dev/null and b/log/images/2022-01-10_fab-step-microstep.jpg differ