├── .DS_Store ├── .gitignore ├── README.md ├── firmware ├── .DS_Store └── stepServo │ ├── .cproject │ ├── .project │ ├── A4954.cpp │ ├── A4954.h │ ├── A5995.cpp │ ├── A5995.h │ ├── Adafruit_GFX.cpp │ ├── Adafruit_GFX.h │ ├── Adafruit_SSD1306.cpp │ ├── Adafruit_SSD1306.h │ ├── Flash.cpp │ ├── Flash.h │ ├── angle.h │ ├── as5047d.cpp │ ├── as5047d.h │ ├── board.h │ ├── calibration.cpp │ ├── calibration.h │ ├── command.cpp │ ├── command.h │ ├── commands.cpp │ ├── commands.h │ ├── eeprom.cpp │ ├── eeprom.h │ ├── fet_driver.cpp │ ├── fet_driver.h │ ├── ftoa.cpp │ ├── ftoa.h │ ├── gfxfont.h │ ├── glcdfont.c │ ├── nonvolatile.cpp │ ├── nonvolatile.h │ ├── nzs.cpp │ ├── nzs.h │ ├── nzs_lcd.cpp │ ├── nzs_lcd.h │ ├── planner.cpp │ ├── planner.h │ ├── sine.cpp │ ├── sine.h │ ├── stepper_controller.cpp │ ├── stepper_controller.h │ ├── stepper_nano_zero.ino │ ├── syslog.cpp │ ├── syslog.h │ ├── utils.cpp │ └── utils.h ├── hardware ├── NZS_A4954_R2.0.PrjPcb ├── NZS_A4954_R2_0.PcbDoc ├── Nano_stepper.SchDoc ├── Nano_zero_stepper_Schematics.pdf ├── Status Report.Txt ├── panel-RoundHoles.TXT ├── panel-SlotHoles.TXT ├── panel-macro.APR_LIB ├── panel.1 ├── panel.DRR ├── panel.EXTREP ├── panel.GBL ├── panel.GBO ├── panel.GBP ├── panel.GBS ├── panel.GD1 ├── panel.GKO ├── panel.GM1 ├── panel.GM13 ├── panel.GM15 ├── panel.GM2 ├── panel.GM3 ├── panel.GML ├── panel.GPB ├── panel.GPT ├── panel.GTL ├── panel.GTO ├── panel.GTP ├── panel.GTS ├── panel.LDP ├── panel.REP ├── panel.RUL └── panel.apr └── stl ├── Helm.SLDPRT ├── Helm.STL ├── cover1.SLDPRT ├── cover1.STL ├── cover2.SLDPRT └── cover2.STL /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 小步步伺服驱动板 Step Servo 2 | 3 | learn more at http://stepservo.cc -------------------------------------------------------------------------------- /firmware/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/firmware/.DS_Store -------------------------------------------------------------------------------- /firmware/stepServo/.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /firmware/stepServo/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | NZS 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.core.ccnature 24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 26 | 27 | 28 | 29 | arduino 30 | 2 31 | C:/Users/tramp_000/AppData/Local/Arduino15/packages/arduino/hardware/samd/1.6.8/cores/arduino 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /firmware/stepServo/A4954.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #include "A4954.h" 13 | #include "wiring_private.h" 14 | #include "syslog.h" 15 | #include "angle.h" 16 | #include "Arduino.h" 17 | #include "sine.h" 18 | 19 | static uint8_t pinState=0; 20 | 21 | #pragma GCC push_options 22 | #pragma GCC optimize ("-Ofast") 23 | 24 | 25 | 26 | 27 | #define DAC_MAX (0x01FFL) 28 | // Wait for synchronization of registers between the clock domains 29 | static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused)); 30 | static void syncTCC(Tcc* TCCx) { 31 | //int32_t t0=1000; 32 | while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK) 33 | { 34 | // t0--; 35 | // if (t0==0) 36 | // { 37 | // break; 38 | // } 39 | // delay(1); 40 | } 41 | } 42 | 43 | 44 | static inline void bridge1(int state) 45 | { 46 | if (state==0) 47 | { 48 | PORT->Group[g_APinDescription[PIN_A4954_IN1].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN1].ulPin].bit.PMUXEN = 0; 49 | GPIO_OUTPUT(PIN_A4954_IN1);//pinMode(PIN_A4954_IN1,OUTPUT); 50 | GPIO_OUTPUT(PIN_A4954_IN2);//pinMode(PIN_A4954_IN2,OUTPUT); 51 | GPIO_HIGH(PIN_A4954_IN1);// digitalWrite(PIN_A4954_IN1, HIGH); 52 | GPIO_LOW(PIN_A4954_IN2);//digitalWrite(PIN_A4954_IN2, LOW); 53 | //pinPeripheral(PIN_A4954_IN2, PIO_TIMER_ALT); 54 | pinState=(pinState & 0x0C) | 0x1; 55 | } 56 | if (state==1) 57 | { 58 | PORT->Group[g_APinDescription[PIN_A4954_IN2].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN2].ulPin].bit.PMUXEN = 0; 59 | GPIO_OUTPUT(PIN_A4954_IN2);//pinMode(PIN_A4954_IN2,OUTPUT); 60 | GPIO_OUTPUT(PIN_A4954_IN1);pinMode(PIN_A4954_IN1,OUTPUT); 61 | GPIO_LOW(PIN_A4954_IN1);//digitalWrite(PIN_A4954_IN1, LOW); 62 | GPIO_HIGH(PIN_A4954_IN2);//digitalWrite(PIN_A4954_IN2, HIGH); 63 | //pinPeripheral(PIN_A4954_IN1, PIO_TIMER); 64 | pinState=(pinState & 0x0C) | 0x2; 65 | } 66 | if (state==3) 67 | { 68 | GPIO_LOW(PIN_A4954_IN1); 69 | GPIO_LOW(PIN_A4954_IN2); 70 | //digitalWrite(PIN_A4954_IN1, LOW); 71 | //digitalWrite(PIN_A4954_IN2, LOW); 72 | } 73 | } 74 | 75 | static inline void bridge2(int state) 76 | { 77 | if (state==0) 78 | { 79 | PORT->Group[g_APinDescription[PIN_A4954_IN3].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN3].ulPin].bit.PMUXEN = 0; 80 | GPIO_OUTPUT(PIN_A4954_IN3); //pinMode(PIN_A4954_IN3,OUTPUT); 81 | GPIO_OUTPUT(PIN_A4954_IN4);//pinMode(PIN_A4954_IN4,OUTPUT); 82 | GPIO_HIGH(PIN_A4954_IN3);//digitalWrite(PIN_A4954_IN3, HIGH); 83 | GPIO_LOW(PIN_A4954_IN4);//digitalWrite(PIN_A4954_IN4, LOW); 84 | //pinPeripheral(PIN_A4954_IN4, PIO_TIMER_ALT); 85 | pinState=(pinState & 0x03) | 0x4; 86 | } 87 | if (state==1) 88 | { 89 | PORT->Group[g_APinDescription[PIN_A4954_IN4].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN4].ulPin].bit.PMUXEN = 0; 90 | GPIO_OUTPUT(PIN_A4954_IN4);//pinMode(PIN_A4954_IN4,OUTPUT); 91 | GPIO_OUTPUT(PIN_A4954_IN3);//pinMode(PIN_A4954_IN3,OUTPUT); 92 | GPIO_LOW(PIN_A4954_IN3);//digitalWrite(PIN_A4954_IN3, LOW); 93 | GPIO_HIGH(PIN_A4954_IN4);//digitalWrite(PIN_A4954_IN4, HIGH); 94 | //pinPeripheral(PIN_A4954_IN3, PIO_TIMER_ALT); 95 | pinState=(pinState & 0x03) | 0x8; 96 | } 97 | if (state==3) 98 | { 99 | GPIO_LOW(PIN_A4954_IN3); 100 | GPIO_LOW(PIN_A4954_IN4); 101 | //digitalWrite(PIN_A4954_IN3, LOW); 102 | //digitalWrite(PIN_A4954_IN4, LOW); 103 | } 104 | } 105 | 106 | static void enableTCC0(uint8_t percent) 107 | { 108 | #ifdef MECHADUINO_HARDWARE 109 | return; 110 | #else 111 | Tcc* TCCx = TCC0 ; 112 | 113 | 114 | uint32_t ulValue=((uint32_t)(100-percent)*480)/100; 115 | //ERROR("Enable TCC0"); 116 | 117 | GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ; 118 | 119 | while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; 120 | 121 | //ERROR("Setting TCC %d %d",ulValue,ulPin); 122 | TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; 123 | syncTCC(TCCx); 124 | 125 | // Set TCx as normal PWM 126 | TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; 127 | syncTCC(TCCx); 128 | 129 | // Set TCx in waveform mode Normal PWM 130 | TCCx->CC[1].reg = (uint32_t)ulValue; //ch5 //IN3 131 | syncTCC(TCCx); 132 | 133 | TCCx->CC[2].reg = (uint32_t)ulValue; //ch6 //IN4 134 | syncTCC(TCCx); 135 | 136 | TCCx->CC[3].reg = (uint32_t)ulValue; //ch7 //IN2 137 | syncTCC(TCCx); 138 | 139 | TCCx->CC[1].reg = (uint32_t)ulValue; //ch1 == ch5 //IN1 140 | 141 | syncTCC(TCCx); 142 | 143 | // Set PER to maximum counter value (resolution : 0xFF) 144 | TCCx->PER.reg = DAC_MAX; 145 | syncTCC(TCCx); 146 | 147 | // Enable TCCx 148 | TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; 149 | syncTCC(TCCx); 150 | //ERROR("Enable TCC0 DONE"); 151 | #endif 152 | } 153 | 154 | static void setDAC(uint32_t DAC1, uint32_t DAC2) 155 | { 156 | TCC1->CC[1].reg = (uint32_t)DAC1; //D9 PA07 - VREF12 157 | syncTCC(TCC1); 158 | TCC1->CC[0].reg = (uint32_t)DAC2; //D4 - VREF34 159 | syncTCC(TCC1); 160 | 161 | 162 | } 163 | 164 | static void setupDAC(void) 165 | { 166 | Tcc* TCCx = TCC1 ; 167 | 168 | 169 | pinPeripheral(PIN_A4954_VREF34, PIO_TIMER_ALT); 170 | pinPeripheral(PIN_A4954_VREF12, PIO_TIMER); 171 | 172 | GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ; 173 | 174 | while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; 175 | 176 | //ERROR("Setting TCC %d %d",ulValue,ulPin); 177 | TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; 178 | syncTCC(TCCx); 179 | 180 | // Set TCx as normal PWM 181 | TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; 182 | syncTCC(TCCx); 183 | 184 | // Set TCx in waveform mode Normal PWM 185 | TCCx->CC[1].reg = (uint32_t)0; 186 | syncTCC(TCCx); 187 | 188 | TCCx->CC[0].reg = (uint32_t)0; 189 | syncTCC(TCCx); 190 | 191 | // Set PER to maximum counter value (resolution : 0xFFF = 12 bits) 192 | // =48e6/2^12=11kHz frequency 193 | TCCx->PER.reg = DAC_MAX; 194 | syncTCC(TCCx); 195 | 196 | // Enable TCCx 197 | TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; 198 | syncTCC(TCCx); 199 | 200 | } 201 | 202 | 203 | void A4954::begin() 204 | { 205 | //setup the A4954 pins 206 | digitalWrite(PIN_A4954_IN3,LOW); 207 | pinMode(PIN_A4954_IN3,OUTPUT); 208 | digitalWrite(PIN_A4954_IN4,LOW); 209 | pinMode(PIN_A4954_IN4,OUTPUT); 210 | digitalWrite(PIN_A4954_IN2,LOW); 211 | pinMode(PIN_A4954_IN2,OUTPUT); 212 | digitalWrite(PIN_A4954_IN1,LOW); 213 | pinMode(PIN_A4954_IN1,OUTPUT); 214 | 215 | //setup the PWM for current on the A4954, set for low current 216 | digitalWrite(PIN_A4954_VREF12,LOW); 217 | digitalWrite(PIN_A4954_VREF34,LOW); 218 | pinMode(PIN_A4954_VREF34, OUTPUT); 219 | pinMode(PIN_A4954_VREF12, OUTPUT); 220 | 221 | enabled=true; 222 | lastStepMicros=0; 223 | forwardRotation=true; 224 | 225 | enableTCC0(90); 226 | setupDAC(); 227 | // 228 | // int i=0; 229 | // bridge1(0); 230 | // bridge2(0); 231 | //while (1) 232 | // { 233 | // int32_t x; 234 | // WARNING("MA %d",i); 235 | // x=(int32_t)((int64_t)i*(DAC_MAX))/3300; 236 | // setDAC(x,x); 237 | // delay(1000); 238 | // i=i+10; 239 | // if (i>1000) 240 | // { 241 | // i=0; 242 | // } 243 | // 244 | // } 245 | 246 | // 247 | // WARNING("Setting DAC for 500mA output"); 248 | // setDAC((int32_t)((int64_t)1000*(DAC_MAX))/3300,(int32_t)((int64_t)1000*(DAC_MAX))/3300); 249 | // bridge1(0); 250 | // bridge2(0); 251 | // while(1) 252 | // { 253 | // 254 | // } 255 | return; 256 | } 257 | 258 | void A4954::limitCurrent(uint8_t percent) 259 | { 260 | #ifdef MECHADUINO_HARDWARE 261 | return; 262 | #else 263 | //WARNING("current limit %d",percent); 264 | enableTCC0(percent); 265 | if (pinState & 0x01) 266 | { 267 | pinPeripheral(PIN_A4954_IN2, PIO_TIMER_ALT); //TCC0 WO[7] 268 | } 269 | if (pinState & 0x02) 270 | { 271 | pinPeripheral(PIN_A4954_IN1, PIO_TIMER); //TCC0 WO[1] 272 | } 273 | if (pinState & 0x04) 274 | { 275 | pinPeripheral(PIN_A4954_IN4, PIO_TIMER_ALT); 276 | } 277 | if (pinState & 0x08) 278 | { 279 | pinPeripheral(PIN_A4954_IN3, PIO_TIMER_ALT); 280 | } 281 | #endif 282 | } 283 | 284 | 285 | void A4954::enable(bool enable) 286 | { 287 | enabled=enable; 288 | if (enabled == false) 289 | { 290 | WARNING("A4954 disabled"); 291 | setDAC(0,0); //turn current off 292 | bridge1(3); //tri state bridge outputs 293 | bridge2(3); //tri state bridge outputs 294 | } 295 | } 296 | 297 | 298 | 299 | //this is precise move and modulo of A4954_NUM_MICROSTEPS is a full step. 300 | // stepAngle is in A4954_NUM_MICROSTEPS units.. 301 | // The A4954 has no idea where the motor is, so the calling function has to 302 | // to tell the A4954 what phase to drive motor coils. 303 | // A4954_NUM_MICROSTEPS is 256 by default so stepAngle of 1024 is 360 degrees 304 | // Note you can only move up to +/-A4954_NUM_MICROSTEPS from where you 305 | // currently are. 306 | int32_t A4954::move(int32_t stepAngle, uint32_t mA) 307 | { 308 | uint16_t angle; 309 | int32_t cos,sin; 310 | int32_t dacSin,dacCos; 311 | //static int i=0; 312 | 313 | if (enabled == false) 314 | { 315 | WARNING("A4954 disabled"); 316 | setDAC(0,0); //turn current off 317 | bridge1(3); //tri state bridge outputs 318 | bridge2(3); //tri state bridge outputs 319 | } 320 | 321 | //WARNING("move %d %d",stepAngle,mA); 322 | //handle roll overs, could do with modulo operator 323 | stepAngle=stepAngle%SINE_STEPS; 324 | 325 | //figure out our sine Angle 326 | // note our SINE_STEPS is 4x of microsteps for a reason 327 | //angle=(stepAngle+(SINE_STEPS/8)) % SINE_STEPS; 328 | angle=(stepAngle); 329 | 330 | //calculate the sine and cosine of our angle 331 | sin=sine(angle); 332 | cos=cosine(angle); 333 | 334 | //if we are reverse swap the sign of one of the angels 335 | if (false == forwardRotation) 336 | { 337 | cos=-cos; 338 | } 339 | 340 | //scale sine result by current(mA) 341 | dacSin=((int32_t)mA*(int64_t)abs(sin))/SINE_MAX; 342 | 343 | //scale cosine result by current(mA) 344 | dacCos=((int32_t)mA*(int64_t)abs(cos))/SINE_MAX; 345 | 346 | // if (i==0) 347 | // { 348 | // WARNING("dacs are %d %d",dacSin,dacCos); 349 | // } 350 | 351 | //convert value into DAC scaled to 3300mA max 352 | dacCos=(int32_t)((int64_t)dacCos*(DAC_MAX))/3300; 353 | //convert value into DAC scaled to 3300mA max 354 | dacSin=(int32_t)((int64_t)dacSin*(DAC_MAX))/3300; 355 | 356 | //WARNING("dacs are %d %d ",dacSin,dacCos); 357 | 358 | setDAC(dacSin,dacCos); 359 | 360 | if (sin>0) 361 | { 362 | bridge1(1); 363 | }else 364 | { 365 | bridge1(0); 366 | } 367 | if (cos>0) 368 | { 369 | bridge2(1); 370 | }else 371 | { 372 | bridge2(0); 373 | } 374 | 375 | // if (i++>3000) 376 | // { 377 | // i=0; 378 | // } 379 | // YELLOW_LED(led); 380 | // led=(led+1) & 0x01; 381 | lastStepMicros=micros(); 382 | return stepAngle; 383 | } 384 | #pragma GCC pop_options 385 | 386 | -------------------------------------------------------------------------------- /firmware/stepServo/A4954.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #ifndef __A4954__H__ 13 | #define __A4954__H__ 14 | #include 15 | #include "board.h" 16 | #include "angle.h" 17 | #include "sine.h" 18 | 19 | #define A4954_NUM_MICROSTEPS (256) 20 | #define A4954_MIN_TIME_BETWEEN_STEPS_MICROS (1000) 21 | 22 | //prevent someone for making a mistake with the code 23 | #if ((A4954_NUM_MICROSTEPS*4) != SINE_STEPS) 24 | #error "SINE_STEPS must be 4x of Micro steps for the move function" 25 | #endif 26 | 27 | 28 | 29 | /* 30 | * When it comes to the stepper driver if we use angles 31 | * we will always have a rounding error. For example 32 | * a 0-65536(360) angle for 1.8 degree step is 327.68 so 33 | * if you increment 200 of these as 327 you have a 13.6 error 34 | * after one rotation. 35 | * If you use floating point the effect is the same but takes longer. 36 | * 37 | * The only error-less accumulation system is to use native units, ie full 38 | * steps and microsteps. 39 | * 40 | */ 41 | 42 | class A4954 43 | { 44 | private: 45 | uint32_t lastStepMicros; // time in microseconds that last step happened 46 | bool forwardRotation=true; 47 | volatile bool enabled=true; 48 | 49 | public: 50 | void begin(void); 51 | 52 | //moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step. 53 | int32_t move(int32_t stepAngle, uint32_t mA); 54 | 55 | uint32_t microsSinceStep(void) {return micros()-lastStepMicros;}; 56 | void setRotationDirection(bool forward) {forwardRotation=forward;}; 57 | 58 | void enable(bool enable); 59 | void limitCurrent(uint8_t percent); //higher more current 60 | }; 61 | 62 | 63 | 64 | #endif //__A4954__H__ 65 | -------------------------------------------------------------------------------- /firmware/stepServo/A5995.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * A5995.cpp 3 | * 4 | * Created on: Feb 2, 2017 5 | * Author: tstern 6 | */ 7 | 8 | 9 | #include "A5995.h" 10 | #include "wiring_private.h" 11 | #include "syslog.h" 12 | #include "angle.h" 13 | #include "Arduino.h" 14 | #include "sine.h" 15 | 16 | static uint8_t pinState=0; 17 | 18 | #pragma GCC push_options 19 | #pragma GCC optimize ("-Ofast") 20 | 21 | 22 | 23 | 24 | #define DAC_MAX (0x01FFL) 25 | // Wait for synchronization of registers between the clock domains 26 | static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused)); 27 | static void syncTCC(Tcc* TCCx) { 28 | //int32_t t0=1000; 29 | while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK) 30 | { 31 | // t0--; 32 | // if (t0==0) 33 | // { 34 | // break; 35 | // } 36 | // delay(1); 37 | } 38 | } 39 | 40 | 41 | 42 | static void setDAC(uint32_t DAC1, uint32_t DAC2) 43 | { 44 | TCC1->CC[1].reg = (uint32_t)DAC1; //D9 PA07 - VREF2 45 | syncTCC(TCC1); 46 | TCC1->CC[0].reg = (uint32_t)DAC2; //D4 - VREF1 47 | syncTCC(TCC1); 48 | 49 | } 50 | 51 | static void setupDAC(void) 52 | { 53 | Tcc* TCCx = TCC1 ; 54 | 55 | 56 | pinPeripheral(PIN_A5995_VREF1, PIO_TIMER_ALT); 57 | pinPeripheral(PIN_A5995_VREF2, PIO_TIMER); 58 | 59 | GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ; 60 | 61 | while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; 62 | 63 | //ERROR("Setting TCC %d %d",ulValue,ulPin); 64 | TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; 65 | syncTCC(TCCx); 66 | 67 | // Set TCx as normal PWM 68 | TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; 69 | syncTCC(TCCx); 70 | 71 | // Set TCx in waveform mode Normal PWM 72 | TCCx->CC[1].reg = (uint32_t)0; 73 | syncTCC(TCCx); 74 | 75 | TCCx->CC[0].reg = (uint32_t)0; 76 | syncTCC(TCCx); 77 | 78 | // Set PER to maximum counter value (resolution : 0xFFF = 12 bits) 79 | // =48e6/2^12=11kHz frequency 80 | TCCx->PER.reg = DAC_MAX; 81 | syncTCC(TCCx); 82 | 83 | // Enable TCCx 84 | TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; 85 | syncTCC(TCCx); 86 | 87 | } 88 | 89 | 90 | void A5995::begin() 91 | { 92 | //setup the A5995 pins 93 | digitalWrite(PIN_A5995_ENABLE1,LOW); 94 | pinMode(PIN_A5995_ENABLE1,OUTPUT); 95 | digitalWrite(PIN_A5995_ENABLE2,LOW); 96 | pinMode(PIN_A5995_ENABLE2,OUTPUT); 97 | digitalWrite(PIN_A5995_MODE1,LOW); 98 | pinMode(PIN_A5995_MODE1,OUTPUT); 99 | digitalWrite(PIN_A5995_MODE2,LOW); 100 | pinMode(PIN_A5995_MODE2,OUTPUT); 101 | digitalWrite(PIN_A5995_PHASE1,LOW); 102 | pinMode(PIN_A5995_PHASE1,OUTPUT); 103 | digitalWrite(PIN_A5995_PHASE2,LOW); 104 | pinMode(PIN_A5995_PHASE2,OUTPUT); 105 | 106 | digitalWrite(PIN_A5995_SLEEPn,HIGH); 107 | pinMode(PIN_A5995_SLEEPn,OUTPUT); 108 | 109 | 110 | 111 | //setup the PWM for current on the A4954, set for low current 112 | digitalWrite(PIN_A5995_VREF1,LOW); 113 | digitalWrite(PIN_A5995_VREF2,LOW); 114 | pinMode(PIN_A5995_VREF1, OUTPUT); 115 | pinMode(PIN_A5995_VREF2, OUTPUT); 116 | 117 | enabled=true; 118 | lastStepMicros=0; 119 | forwardRotation=true; 120 | 121 | setupDAC(); 122 | 123 | 124 | // 125 | // GPIO_HIGH(PIN_A5995_ENABLE1); 126 | // GPIO_HIGH(PIN_A5995_ENABLE2); 127 | // GPIO_LOW(PIN_A5995_MODE1); 128 | // GPIO_LOW(PIN_A5995_MODE2); 129 | // GPIO_HIGH(PIN_A5995_PHASE1); 130 | // GPIO_HIGH(PIN_A5995_PHASE2); 131 | // int i=0;; 132 | // while (1) 133 | // { 134 | // int32_t x; 135 | // WARNING("MA %d",i); 136 | // x=(int32_t)((int64_t)i*(DAC_MAX))/3300; 137 | // setDAC(x,x); 138 | // delay(1000); 139 | // i=i+10; 140 | // if (i>1000) 141 | // { 142 | // i=0; 143 | // } 144 | // 145 | // } 146 | 147 | 148 | return; 149 | } 150 | 151 | 152 | 153 | void A5995::enable(bool enable) 154 | { 155 | enabled=enable; 156 | if (enabled == false) 157 | { 158 | WARNING("A4954 disabled"); 159 | setDAC(0,0); //turn current off 160 | GPIO_LOW(PIN_A5995_ENABLE1); 161 | GPIO_LOW(PIN_A5995_ENABLE2); 162 | GPIO_LOW(PIN_A5995_MODE1); 163 | GPIO_LOW(PIN_A5995_MODE2); 164 | GPIO_LOW(PIN_A5995_PHASE1); 165 | GPIO_LOW(PIN_A5995_PHASE2); 166 | } 167 | } 168 | 169 | 170 | 171 | //this is precise move and modulo of A4954_NUM_MICROSTEPS is a full step. 172 | // stepAngle is in A4954_NUM_MICROSTEPS units.. 173 | // The A4954 has no idea where the motor is, so the calling function has to 174 | // to tell the A4954 what phase to drive motor coils. 175 | // A4954_NUM_MICROSTEPS is 256 by default so stepAngle of 1024 is 360 degrees 176 | // Note you can only move up to +/-A4954_NUM_MICROSTEPS from where you 177 | // currently are. 178 | int32_t A5995::move(int32_t stepAngle, uint32_t mA) 179 | { 180 | uint16_t angle; 181 | int32_t cos,sin; 182 | int32_t dacSin,dacCos; 183 | static int32_t lastSin=0,lastCos=0; 184 | static int i=1; 185 | 186 | if (enabled == false) 187 | { 188 | WARNING("A4954 disabled"); 189 | setDAC(0,0); //turn current off 190 | GPIO_LOW(PIN_A5995_ENABLE1); 191 | GPIO_LOW(PIN_A5995_ENABLE2); 192 | GPIO_LOW(PIN_A5995_MODE1); 193 | GPIO_LOW(PIN_A5995_MODE2); 194 | GPIO_LOW(PIN_A5995_PHASE1); 195 | GPIO_LOW(PIN_A5995_PHASE2); 196 | return stepAngle; 197 | } 198 | 199 | //WARNING("move %d %d",stepAngle,mA); 200 | 201 | stepAngle=(stepAngle) % SINE_STEPS; 202 | //figure out our sine Angle 203 | // note our SINE_STEPS is 4x of microsteps for a reason 204 | //angle=(stepAngle+(SINE_STEPS/8)) % SINE_STEPS; 205 | angle=stepAngle; 206 | 207 | if (i==0) 208 | { 209 | WARNING("angle %d ",angle); 210 | } 211 | //calculate the sine and cosine of our angle 212 | sin=sine(angle); 213 | cos=cosine(angle); 214 | 215 | //if we are reverse swap the sign of one of the angels 216 | if (false == forwardRotation) 217 | { 218 | cos=-cos; 219 | } 220 | 221 | //scale sine result by current(mA) 222 | dacSin=((int32_t)mA*(int64_t)(sin))/SINE_MAX; 223 | 224 | if (i==0) 225 | { 226 | WARNING("dacsine %d ",dacSin); 227 | } 228 | // if ((lastSin-dacSin)>100) //decreasing current 229 | // { 230 | // GPIO_LOW(PIN_A5995_MODE2); //fast decay 231 | // } else 232 | // { 233 | // GPIO_HIGH(PIN_A5995_MODE2); //slow decay 234 | // } 235 | lastSin=dacSin; 236 | 237 | //convert value into DAC scaled to 3300mA max 238 | dacSin=(int32_t)((int64_t)abs(dacSin)*(DAC_MAX))/3300; 239 | 240 | 241 | //scale cosine result by current(mA) 242 | dacCos=((int32_t)mA*(int64_t)(cos))/SINE_MAX; 243 | 244 | if (i==0) 245 | { 246 | WARNING("daccos %d ",dacCos); 247 | } 248 | // if ((lastCos-dacCos)>100) //decreasing current 249 | // { 250 | // GPIO_LOW(PIN_A5995_MODE1); //fast decay 251 | // } else 252 | // { 253 | // GPIO_HIGH(PIN_A5995_MODE1); //slow decay 254 | // } 255 | lastCos=dacCos; 256 | 257 | //convert value into DAC scaled to 3300mA max 258 | dacCos=(int32_t)((int64_t)abs(dacCos)*(DAC_MAX))/3300; 259 | 260 | 261 | if (i==0) 262 | { 263 | WARNING("dacs are %d %d",dacSin,dacCos); 264 | } 265 | setDAC(dacSin,dacCos); 266 | 267 | GPIO_HIGH(PIN_A5995_ENABLE1); 268 | GPIO_HIGH(PIN_A5995_ENABLE2); 269 | GPIO_LOW(PIN_A5995_MODE1); 270 | GPIO_LOW(PIN_A5995_MODE2); 271 | 272 | 273 | if (i==0) 274 | { 275 | WARNING("sins are %d %d",sin,cos); 276 | } 277 | 278 | if (sin>0) 279 | { 280 | GPIO_HIGH(PIN_A5995_PHASE2); 281 | }else 282 | { 283 | GPIO_LOW(PIN_A5995_PHASE2); 284 | 285 | } 286 | if (cos>0) 287 | { 288 | GPIO_HIGH(PIN_A5995_PHASE1); 289 | 290 | }else 291 | { 292 | GPIO_LOW(PIN_A5995_PHASE1); 293 | 294 | } 295 | 296 | // i++; 297 | // if (i>3000) i=0; 298 | // YELLOW_LED(led); 299 | // led=(led+1) & 0x01; 300 | lastStepMicros=micros(); 301 | return stepAngle; 302 | } 303 | #pragma GCC pop_options 304 | 305 | 306 | 307 | -------------------------------------------------------------------------------- /firmware/stepServo/A5995.h: -------------------------------------------------------------------------------- 1 | /* 2 | * A5995.h 3 | * 4 | * Created on: Feb 2, 2017 5 | * Author: tstern 6 | */ 7 | 8 | #ifndef A5995_H_ 9 | #define A5995_H_ 10 | 11 | #include 12 | #include "board.h" 13 | #include "angle.h" 14 | #include "sine.h" 15 | 16 | #define A5995_NUM_MICROSTEPS (256) 17 | 18 | 19 | //prevent someone for making a mistake with the code 20 | #if ((A5995_NUM_MICROSTEPS*4) != SINE_STEPS) 21 | #error "SINE_STEPS must be 4x of Micro steps for the move function" 22 | #endif 23 | 24 | 25 | 26 | /* 27 | * When it comes to the stepper driver if we use angles 28 | * we will always have a rounding error. For example 29 | * a 0-65536(360) angle for 1.8 degree step is 327.68 so 30 | * if you increment 200 of these as 327 you have a 13.6 error 31 | * after one rotation. 32 | * If you use floating point the effect is the same but takes longer. 33 | * 34 | * The only error-less accumulation system is to use native units, ie full 35 | * steps and microsteps. 36 | * 37 | */ 38 | 39 | class A5995 40 | { 41 | private: 42 | uint32_t lastStepMicros; // time in microseconds that last step happened 43 | bool forwardRotation=true; 44 | volatile bool enabled=true; 45 | 46 | public: 47 | void begin(void); 48 | 49 | //moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step. 50 | int32_t move(int32_t stepAngle, uint32_t mA); 51 | 52 | uint32_t microsSinceStep(void) {return micros()-lastStepMicros;}; 53 | void setRotationDirection(bool forward) {forwardRotation=forward;}; 54 | 55 | void enable(bool enable); 56 | void limitCurrent(uint8_t percent) {return;}; //Not used 57 | }; 58 | 59 | 60 | 61 | #endif /* A5995_H_ */ 62 | -------------------------------------------------------------------------------- /firmware/stepServo/Adafruit_GFX.h: -------------------------------------------------------------------------------- 1 | #ifndef _ADAFRUIT_GFX_H 2 | #define _ADAFRUIT_GFX_H 3 | 4 | #if ARDUINO >= 100 5 | #include "Arduino.h" 6 | #include "Print.h" 7 | #else 8 | #include "WProgram.h" 9 | #endif 10 | 11 | #include "gfxfont.h" 12 | 13 | class Adafruit_GFX : public Print { 14 | 15 | public: 16 | 17 | Adafruit_GFX(int16_t w, int16_t h); // Constructor 18 | 19 | // This MUST be defined by the subclass: 20 | virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; 21 | 22 | // These MAY be overridden by the subclass to provide device-specific 23 | // optimized code. Otherwise 'generic' versions are used. 24 | virtual void 25 | drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color), 26 | drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color), 27 | drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color), 28 | drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color), 29 | fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color), 30 | fillScreen(uint16_t color), 31 | invertDisplay(boolean i); 32 | 33 | // These exist only with Adafruit_GFX (no subclass overrides) 34 | void 35 | drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color), 36 | drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, 37 | uint16_t color), 38 | fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color), 39 | fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, 40 | int16_t delta, uint16_t color), 41 | drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, 42 | int16_t x2, int16_t y2, uint16_t color), 43 | fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, 44 | int16_t x2, int16_t y2, uint16_t color), 45 | drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, 46 | int16_t radius, uint16_t color), 47 | fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, 48 | int16_t radius, uint16_t color), 49 | drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, 50 | int16_t w, int16_t h, uint16_t color), 51 | drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, 52 | int16_t w, int16_t h, uint16_t color, uint16_t bg), 53 | drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, 54 | int16_t w, int16_t h, uint16_t color), 55 | drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, 56 | int16_t w, int16_t h, uint16_t color, uint16_t bg), 57 | drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, 58 | int16_t w, int16_t h, uint16_t color), 59 | drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, 60 | uint16_t bg, uint8_t size), 61 | setCursor(int16_t x, int16_t y), 62 | setTextColor(uint16_t c), 63 | setTextColor(uint16_t c, uint16_t bg), 64 | setTextSize(uint8_t s), 65 | setTextWrap(boolean w), 66 | setRotation(uint8_t r), 67 | cp437(boolean x=true), 68 | setFont(const GFXfont *f = NULL), 69 | getTextBounds(char *string, int16_t x, int16_t y, 70 | int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h), 71 | getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, 72 | int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h); 73 | 74 | #if ARDUINO >= 100 75 | virtual size_t write(uint8_t); 76 | #else 77 | virtual void write(uint8_t); 78 | #endif 79 | 80 | int16_t height(void) const; 81 | int16_t width(void) const; 82 | 83 | uint8_t getRotation(void) const; 84 | 85 | // get current cursor position (get rotation safe maximum values, using: width() for x, height() for y) 86 | int16_t getCursorX(void) const; 87 | int16_t getCursorY(void) const; 88 | 89 | protected: 90 | const int16_t 91 | WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes 92 | int16_t 93 | _width, _height, // Display w/h as modified by current rotation 94 | cursor_x, cursor_y; 95 | uint16_t 96 | textcolor, textbgcolor; 97 | uint8_t 98 | textsize, 99 | rotation; 100 | boolean 101 | wrap, // If set, 'wrap' text at right edge of display 102 | _cp437; // If set, use correct CP437 charset (default is off) 103 | GFXfont 104 | *gfxFont; 105 | }; 106 | 107 | class Adafruit_GFX_Button { 108 | 109 | public: 110 | Adafruit_GFX_Button(void); 111 | void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y, 112 | uint8_t w, uint8_t h, uint16_t outline, uint16_t fill, 113 | uint16_t textcolor, char *label, uint8_t textsize); 114 | void drawButton(boolean inverted = false); 115 | boolean contains(int16_t x, int16_t y); 116 | 117 | void press(boolean p); 118 | boolean isPressed(); 119 | boolean justPressed(); 120 | boolean justReleased(); 121 | 122 | private: 123 | Adafruit_GFX *_gfx; 124 | int16_t _x, _y; 125 | uint16_t _w, _h; 126 | uint8_t _textsize; 127 | uint16_t _outlinecolor, _fillcolor, _textcolor; 128 | char _label[10]; 129 | 130 | boolean currstate, laststate; 131 | }; 132 | 133 | class GFXcanvas1 : public Adafruit_GFX { 134 | 135 | public: 136 | GFXcanvas1(uint16_t w, uint16_t h); 137 | ~GFXcanvas1(void); 138 | void drawPixel(int16_t x, int16_t y, uint16_t color), 139 | fillScreen(uint16_t color); 140 | uint8_t *getBuffer(void); 141 | private: 142 | uint8_t *buffer; 143 | }; 144 | 145 | class GFXcanvas16 : public Adafruit_GFX { 146 | GFXcanvas16(uint16_t w, uint16_t h); 147 | ~GFXcanvas16(void); 148 | void drawPixel(int16_t x, int16_t y, uint16_t color), 149 | fillScreen(uint16_t color); 150 | uint16_t *getBuffer(void); 151 | private: 152 | uint16_t *buffer; 153 | }; 154 | 155 | #endif // _ADAFRUIT_GFX_H 156 | -------------------------------------------------------------------------------- /firmware/stepServo/Adafruit_SSD1306.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | This is a library for our Monochrome OLEDs based on SSD1306 drivers 3 | 4 | Pick one up today in the adafruit shop! 5 | ------> http://www.adafruit.com/category/63_98 6 | 7 | These displays use SPI to communicate, 4 or 5 pins are required to 8 | interface 9 | 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit and open-source hardware by purchasing 12 | products from Adafruit! 13 | 14 | Written by Limor Fried/Ladyada for Adafruit Industries. 15 | BSD license, check license.txt for more information 16 | All text above, and the splash screen must be included in any redistribution 17 | *********************************************************************/ 18 | #ifndef _Adafruit_SSD1306_H_ 19 | #define _Adafruit_SSD1306_H_ 20 | 21 | #if ARDUINO >= 100 22 | #include "Arduino.h" 23 | #define WIRE_WRITE Wire.write 24 | #else 25 | #include "WProgram.h" 26 | #define WIRE_WRITE Wire.send 27 | #endif 28 | 29 | #if defined(__SAM3X8E__) 30 | typedef volatile RwReg PortReg; 31 | typedef uint32_t PortMask; 32 | #define HAVE_PORTREG 33 | #elif defined(ARDUINO_ARCH_SAMD) 34 | // not supported 35 | #elif defined(ESP8266) || defined(ARDUINO_STM32_FEATHER) 36 | typedef volatile uint32_t PortReg; 37 | typedef uint32_t PortMask; 38 | #else 39 | typedef volatile uint8_t PortReg; 40 | typedef uint8_t PortMask; 41 | #define HAVE_PORTREG 42 | #endif 43 | 44 | #include 45 | #include "Adafruit_GFX.h" 46 | 47 | #define BLACK 0 48 | #define WHITE 1 49 | #define INVERSE 2 50 | 51 | #define SSD1306_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D 52 | // Address for 128x32 is 0x3C 53 | // Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded) 54 | 55 | /*========================================================================= 56 | SSD1306 Displays 57 | ----------------------------------------------------------------------- 58 | The driver is used in multiple displays (128x64, 128x32, etc.). 59 | Select the appropriate display below to create an appropriately 60 | sized framebuffer, etc. 61 | 62 | SSD1306_128_64 128x64 pixel display 63 | 64 | SSD1306_128_32 128x32 pixel display 65 | 66 | SSD1306_96_16 67 | 68 | -----------------------------------------------------------------------*/ 69 | #define SSD1306_128_64 70 | // #define SSD1306_128_32 71 | // #define SSD1306_96_16 72 | /*=========================================================================*/ 73 | 74 | #if defined SSD1306_128_64 && defined SSD1306_128_32 75 | #error "Only one SSD1306 display can be specified at once in SSD1306.h" 76 | #endif 77 | #if !defined SSD1306_128_64 && !defined SSD1306_128_32 && !defined SSD1306_96_16 78 | #error "At least one SSD1306 display must be specified in SSD1306.h" 79 | #endif 80 | 81 | #if defined SSD1306_128_64 82 | #define SSD1306_LCDWIDTH 128 83 | #define SSD1306_LCDHEIGHT 64 84 | #endif 85 | #if defined SSD1306_128_32 86 | #define SSD1306_LCDWIDTH 128 87 | #define SSD1306_LCDHEIGHT 32 88 | #endif 89 | #if defined SSD1306_96_16 90 | #define SSD1306_LCDWIDTH 96 91 | #define SSD1306_LCDHEIGHT 16 92 | #endif 93 | 94 | #define SSD1306_SETCONTRAST 0x81 95 | #define SSD1306_DISPLAYALLON_RESUME 0xA4 96 | #define SSD1306_DISPLAYALLON 0xA5 97 | #define SSD1306_NORMALDISPLAY 0xA6 98 | #define SSD1306_INVERTDISPLAY 0xA7 99 | #define SSD1306_DISPLAYOFF 0xAE 100 | #define SSD1306_DISPLAYON 0xAF 101 | 102 | #define SSD1306_SETDISPLAYOFFSET 0xD3 103 | #define SSD1306_SETCOMPINS 0xDA 104 | 105 | #define SSD1306_SETVCOMDETECT 0xDB 106 | 107 | #define SSD1306_SETDISPLAYCLOCKDIV 0xD5 108 | #define SSD1306_SETPRECHARGE 0xD9 109 | 110 | #define SSD1306_SETMULTIPLEX 0xA8 111 | 112 | #define SSD1306_SETLOWCOLUMN 0x00 113 | #define SSD1306_SETHIGHCOLUMN 0x10 114 | 115 | #define SSD1306_SETSTARTLINE 0x40 116 | 117 | #define SSD1306_MEMORYMODE 0x20 118 | #define SSD1306_COLUMNADDR 0x21 119 | #define SSD1306_PAGEADDR 0x22 120 | 121 | #define SSD1306_COMSCANINC 0xC0 122 | #define SSD1306_COMSCANDEC 0xC8 123 | 124 | #define SSD1306_SEGREMAP 0xA0 125 | 126 | #define SSD1306_CHARGEPUMP 0x8D 127 | 128 | #define SSD1306_EXTERNALVCC 0x1 129 | #define SSD1306_SWITCHCAPVCC 0x2 130 | 131 | // Scrolling #defines 132 | #define SSD1306_ACTIVATE_SCROLL 0x2F 133 | #define SSD1306_DEACTIVATE_SCROLL 0x2E 134 | #define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3 135 | #define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26 136 | #define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27 137 | #define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29 138 | #define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A 139 | 140 | class Adafruit_SSD1306 : public Adafruit_GFX { 141 | public: 142 | Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS); 143 | Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS); 144 | Adafruit_SSD1306(int8_t RST = -1); 145 | 146 | bool begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS, bool reset=true); 147 | uint8_t ssd1306_command(uint8_t c); 148 | 149 | void clearDisplay(void); 150 | void invertDisplay(uint8_t i); 151 | void display(); 152 | 153 | void startscrollright(uint8_t start, uint8_t stop); 154 | void startscrollleft(uint8_t start, uint8_t stop); 155 | 156 | void startscrolldiagright(uint8_t start, uint8_t stop); 157 | void startscrolldiagleft(uint8_t start, uint8_t stop); 158 | void stopscroll(void); 159 | 160 | void dim(boolean dim); 161 | 162 | void drawPixel(int16_t x, int16_t y, uint16_t color); 163 | 164 | virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); 165 | virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); 166 | 167 | private: 168 | int8_t _i2caddr, _vccstate, sid, sclk, dc, rst, cs; 169 | void fastSPIwrite(uint8_t c); 170 | 171 | boolean hwSPI; 172 | #ifdef HAVE_PORTREG 173 | PortReg *mosiport, *clkport, *csport, *dcport; 174 | PortMask mosipinmask, clkpinmask, cspinmask, dcpinmask; 175 | #endif 176 | 177 | inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline)); 178 | inline void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline)); 179 | 180 | }; 181 | 182 | #endif /* _Adafruit_SSD1306_H_ */ 183 | -------------------------------------------------------------------------------- /firmware/stepServo/Flash.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #include "Flash.h" 13 | #include "syslog.h" 14 | 15 | bool flashInit(void){ 16 | if (NVMCTRL->PARAM.bit.PSZ != 3) 17 | { 18 | ERROR("FLASH PAGE SIZE is not 64 bytes"); 19 | return false; 20 | } 21 | return true; 22 | } 23 | 24 | 25 | static void erase(const volatile void *flash_ptr) 26 | { 27 | NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2; 28 | NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER; 29 | while (!NVMCTRL->INTFLAG.bit.READY) { } 30 | } 31 | 32 | bool flashErase(const volatile void *flash_ptr, uint32_t size) 33 | { 34 | const uint8_t *ptr = (const uint8_t *)flash_ptr; 35 | while (size > FLASH_ROW_SIZE) { 36 | erase(ptr); 37 | ptr += FLASH_ROW_SIZE; 38 | size -= FLASH_ROW_SIZE; 39 | } 40 | if (size>0) 41 | { 42 | erase(ptr); 43 | } 44 | return true; //TODO should verify the erase 45 | } 46 | 47 | static inline uint32_t read_unaligned_uint32(const void *data) 48 | { 49 | union { 50 | uint32_t u32; 51 | uint8_t u8[4]; 52 | } res; 53 | const uint8_t *d = (const uint8_t *)data; 54 | res.u8[0] = d[0]; 55 | res.u8[1] = d[1]; 56 | res.u8[2] = d[2]; 57 | res.u8[3] = d[3]; 58 | return res.u32; 59 | } 60 | 61 | 62 | void flashWrite(const volatile void *flash_ptr,const void *data, uint32_t size) 63 | { 64 | uint32_t *ptrPage; 65 | uint8_t *destPtr; 66 | uint8_t *srcPtr; 67 | uint32_t bytesInBlock; 68 | __attribute__((__aligned__(4))) uint8_t buffer[FLASH_ROW_SIZE]; 69 | uint32_t offset; 70 | 71 | destPtr=(uint8_t *)flash_ptr; 72 | srcPtr=(uint8_t *)data; 73 | 74 | //LOG("flash write called"); 75 | while(size>0) 76 | { 77 | uint32_t i,j; 78 | 79 | //calculate the maximum number of bytes we can write in page 80 | offset=((uint32_t)destPtr)%(FLASH_ROW_SIZE); //offset into page 81 | bytesInBlock=FLASH_ROW_SIZE-offset; //this is how many bytes we need to overwrite in this page 82 | 83 | //LOG("offset %d, bytesInBlock %d size %d", offset, bytesInBlock,size); 84 | //get pointer to start of page 85 | ptrPage=(uint32_t *) ((((uint32_t)destPtr)/(FLASH_ROW_SIZE)) * FLASH_ROW_SIZE); 86 | 87 | //LOG("pointer to page %d(0x%08x) %d",(uint32_t)ptrPage,(uint32_t)ptrPage,destPtr); 88 | 89 | //fill page buffer with data from flash 90 | memcpy(buffer,ptrPage,FLASH_ROW_SIZE); 91 | 92 | //now fill buffer with new data that needs changing 93 | i=bytesInBlock; 94 | if (sizeCTRLB.bit.MANW = 1; 142 | 143 | // Do writes in pages 144 | while (size) 145 | { 146 | // Execute "PBC" Page Buffer Clear 147 | NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC; 148 | while (NVMCTRL->INTFLAG.bit.READY == 0) { } 149 | 150 | // Fill page buffer 151 | uint32_t i; 152 | for (i=0; i<(FLASH_PAGE_SIZE/4) && size; i++) //we write 4 bytes at a time 153 | { 154 | *dst_addr = read_unaligned_uint32(src_addr); 155 | src_addr += 4; 156 | dst_addr++; 157 | size--; //size is set to number of 32bit words in first line above 158 | } 159 | 160 | // Execute "WP" Write Page 161 | NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP; 162 | while (NVMCTRL->INTFLAG.bit.READY == 0) { } 163 | } 164 | 165 | 166 | } 167 | -------------------------------------------------------------------------------- /firmware/stepServo/Flash.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #ifndef __FLASH__H__ 13 | #define __FLASH__H__ 14 | 15 | #include 16 | #include "syslog.h" 17 | 18 | 19 | #define FLASH_PAGE_SIZE_NZS (64) //bytes 20 | #define FLASH_ROW_SIZE (FLASH_PAGE_SIZE_NZS*4) //defined in the datasheet as 4x page size 21 | #define FLASH_ERASE_VALUE (0xFF) //value of flash after an erase 22 | 23 | #define FLASH_ALLOCATE(name, size) \ 24 | __attribute__((__aligned__(FLASH_ROW_SIZE))) \ 25 | const uint8_t name[(size+(FLASH_ROW_SIZE-1))/FLASH_ROW_SIZE*FLASH_ROW_SIZE] = { }; 26 | 27 | bool flashInit(void); //this checks that our assumptions are true 28 | 29 | bool flashErase(const volatile void *flash_ptr, uint32_t size); 30 | void flashWrite(const volatile void *flash_ptr,const void *data,uint32_t size); 31 | void flashWritePage(const volatile void *flash_ptr, const void *data, uint32_t size); 32 | 33 | //you can read by dereferencing pointer but we will add a read 34 | static inline int32_t flashRead(const volatile void *flash_ptr, void *data, uint32_t size) 35 | { 36 | memcpy(data, (const void *)flash_ptr, size); 37 | } 38 | 39 | 40 | 41 | 42 | #endif //__FLASH__H__ 43 | -------------------------------------------------------------------------------- /firmware/stepServo/angle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * angle.h 3 | * 4 | * Created on: Sep 1, 2016 5 | * Author: TStern 6 | * 7 | * Misfit Tech invests time and resources providing this open source code, 8 | * please support Misfit Tech and open-source hardware by purchasing 9 | * products from Misfit Tech, www.misifittech.net! 10 | * 11 | * Written by Trampas Stern for Misfit Tech. 12 | * BSD license, check license.txt for more information 13 | * All text above, must be included in any redistribution 14 | *********************************************************************/ 15 | 16 | #ifndef ANGLE_H_ 17 | #define ANGLE_H_ 18 | #include 19 | #include 20 | #include 21 | 22 | #define ANGLE_STEPS (0x010000UL) 23 | #define ANGLE_MAX ((uint16_t)0x0FFFF) 24 | 25 | #define ANGLE_FROM_DEGREES(x) ((int32_t) ( ((float)ANGLE_STEPS*(float)(x)+180.0)/360.0 ) ) 26 | #define ANGLE_T0_DEGREES(x) ( (float) ((float(x)*360.0 + (float)(ANGLE_STEPS/2))/((float)ANGLE_STEPS) )) 27 | class Angle 28 | { 29 | private: 30 | uint16_t angle; 31 | public: 32 | Angle(void) {angle=0;} 33 | Angle(int32_t x) {angle=(uint16_t)x;} 34 | Angle(const Angle &x) {angle=x.angle;} 35 | 36 | int16_t operator-( const Angle &a2) 37 | { 38 | int32_t x,y,dx; 39 | x=(int32_t)angle; 40 | y=(int32_t)a2.angle; 41 | dx=x-y; 42 | if (abs(x-y)>ANGLE_STEPS/2) 43 | { 44 | //we have a wrap condition 45 | if (x>y) 46 | { 47 | dx=x-(y+ANGLE_STEPS); 48 | }else if (xANGLE_MAX) 61 | // { 62 | // y=y-ANGLE_STEPS; 63 | // } 64 | // while(y<-ANGLE_MAX) 65 | // { 66 | // y=y+ANGLE_STEPS; 67 | // } 68 | // 69 | // dx=x-y; 70 | // if (abs(x-y)>ANGLE_STEPS/2) 71 | // { 72 | // //we have a wrap condition 73 | // if (x>y) 74 | // { 75 | // dx=x-(y+ANGLE_STEPS); 76 | // }else if (x=ANGLE_STEPS) 95 | { 96 | a=a-ANGLE_STEPS; 97 | } 98 | while (a<0) 99 | { 100 | a=a+ANGLE_STEPS; 101 | } 102 | return Angle((uint16_t)a); 103 | } 104 | Angle operator+(const unsigned long int x) 105 | { 106 | uint32_t a; 107 | a=(uint32_t)angle+ x; 108 | while (a>=ANGLE_STEPS) 109 | { 110 | a=a-ANGLE_STEPS; 111 | } 112 | return Angle((uint16_t)a); 113 | } 114 | 115 | operator uint16_t() const {return angle;} 116 | operator uint32_t() const {return (uint32_t)angle;} 117 | operator int32_t() const {return (int32_t)angle;} 118 | 119 | 120 | 121 | }; 122 | 123 | 124 | #endif /* ANGLE_H_ */ 125 | -------------------------------------------------------------------------------- /firmware/stepServo/as5047d.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #include 13 | #include "syslog.h" 14 | #include "as5047d.h" 15 | #include "SPI.h" 16 | #include 17 | #include "board.h" 18 | 19 | #define AS5047D_CMD_NOP (0x0000) 20 | #define AS5047D_CMD_ERRFL (0x0001) 21 | #define AS5047D_CMD_PROG (0x0003) 22 | #define AS5047D_CMD_DIAAGC (0x3FFC) 23 | #define AS5047D_CMD_MAG (0x3FFD) 24 | #define AS5047D_CMD_ANGLEUNC (0x3FFE) 25 | #define AS5047D_CMD_ANGLECOM (0x3FFF) 26 | 27 | #pragma GCC push_options 28 | #pragma GCC optimize ("-Ofast") 29 | 30 | static int getBit(int16_t data, int bit) 31 | { 32 | return (data>>bit) & 0x01; 33 | } 34 | 35 | static int getParity(uint16_t data) 36 | { 37 | int i,bits; 38 | data=data & 0x7FFF; //mask out upper bit 39 | 40 | //count number of bits, brute force 41 | bits=0; 42 | for(i=0; i<16; i++) 43 | { 44 | if (0 != (data & ((0x0001)<>15 != getParity(data)) 147 | { 148 | //parity did not match 149 | ERROR("read command parity error 0x%04X ",addr); 150 | error=true; 151 | return -2; 152 | } 153 | 154 | data=data & 0x3FFF; //mask off the error and parity bits 155 | 156 | return data; 157 | } 158 | 159 | //read the encoders 160 | int16_t AS5047D::readEncoderAngle(void) 161 | { 162 | return readAddress(AS5047D_CMD_ANGLECOM); 163 | } 164 | 165 | //pipelined read of the encoder angle used for high speed reads, but value is always one read behind 166 | int16_t AS5047D::readEncoderAnglePipeLineRead(void) 167 | { 168 | int16_t data; 169 | int error, t0=10; 170 | GPIO_LOW(chipSelectPin);//(chipSelectPin, LOW); 171 | //delayMicroseconds(1); 172 | do { 173 | 174 | // doing two 8 bit transfers is faster than one 16 bit 175 | data =(uint16_t)SPI.transfer(0xFF)<<8 | ((uint16_t)SPI.transfer(0xFF) & 0x0FF); 176 | t0--; 177 | if (t0<=0) 178 | { 179 | ERROR("AS5047D problem"); 180 | break; 181 | } 182 | //data=SPI.transfer16(0xFFFF); //to speed things up we know the parity and address for the read 183 | }while(data & (1<<14)); //while error bit is set 184 | 185 | data=data & 0x3FFF; //mask off the error and parity bits 186 | GPIO_HIGH(chipSelectPin); 187 | //digitalWrite(chipSelectPin, HIGH); 188 | //TODO we really should check for errors and return a negative result or something 189 | return data; 190 | } 191 | 192 | 193 | void AS5047D::diagnostics(char *ptrStr) 194 | { 195 | int16_t data; 196 | int m,d; 197 | 198 | data=readAddress(AS5047D_CMD_DIAAGC); 199 | 200 | if (NULL == ptrStr) 201 | { 202 | LOG("DIAAGC: 0x%04X", data); 203 | LOG("MAGL: %d", getBit(data,11)); 204 | LOG("MAGH: %d", getBit(data,10)); 205 | LOG("COF: %d", getBit(data,9)); 206 | LOG("LFGL: %d", getBit(data,8)); 207 | LOG("AGC: %d", data & 0x0FF); 208 | 209 | data=readAddress(AS5047D_CMD_MAG); 210 | LOG("CMAG: 0x%04X(%d)",data,data); 211 | 212 | data=readAddress(AS5047D_CMD_ANGLEUNC); 213 | m=(int)((float)data*AS5047D_DEGREES_PER_BIT); 214 | d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100); 215 | LOG("CORDICANG: 0x%04X(%d) %d.%02d deg(est)",data,data,m,d); 216 | 217 | data=readAddress(AS5047D_CMD_ANGLECOM); 218 | m=(int)((float)data*AS5047D_DEGREES_PER_BIT); 219 | d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100); 220 | LOG("DAECANG: 0x%04X(%d) %d.%02d deg(est)",data,data,m,d); 221 | }else 222 | { 223 | sprintf(ptrStr,"DIAAGC: 0x%04X\n\r", data); 224 | sprintf(ptrStr,"%sMAGL: %d\n\r", ptrStr,getBit(data,11)); 225 | sprintf(ptrStr,"%sMAGH: %d\n\r", ptrStr,getBit(data,10)); 226 | sprintf(ptrStr,"%sCOF: %d\n\r", ptrStr, getBit(data,9)); 227 | sprintf(ptrStr,"%sLFGL: %d\n\r", ptrStr, getBit(data,8)); 228 | sprintf(ptrStr,"%sAGC: %d\n\r", ptrStr,data & 0x0FF); 229 | 230 | data=readAddress(AS5047D_CMD_MAG); 231 | sprintf(ptrStr,"%sCMAG: 0x%04X(%d)\n\r", ptrStr,data,data); 232 | 233 | data=readAddress(AS5047D_CMD_ANGLEUNC); 234 | m=(int)((float)data*AS5047D_DEGREES_PER_BIT); 235 | d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100); 236 | sprintf(ptrStr,"%sCORDICANG: 0x%04X(%d) %d.%02d deg(est)\n\r", ptrStr,data,data,m,d); 237 | 238 | data=readAddress(AS5047D_CMD_ANGLECOM); 239 | m=(int)((float)data*AS5047D_DEGREES_PER_BIT); 240 | d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100); 241 | sprintf(ptrStr,"%sDAECANG: 0x%04X(%d) %d.%02d deg(est)\n\r", ptrStr,data,data,m,d); 242 | 243 | } 244 | } 245 | 246 | #pragma GCC pop_options 247 | 248 | -------------------------------------------------------------------------------- /firmware/stepServo/as5047d.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #ifndef __AS5047D_H__ 13 | #define __AS5047D_H__ 14 | 15 | #include 16 | #define AS5047D_DEGREES_PER_BIT (360.0/(float)(0x3FFF)) 17 | 18 | class AS5047D { 19 | private: 20 | int chipSelectPin; 21 | int16_t readAddress(uint16_t addr); 22 | bool error=false; 23 | public: 24 | boolean begin(int csPin); 25 | int16_t readEncoderAngle(void); 26 | void diagnostics(char *ptrStr); 27 | int16_t readEncoderAnglePipeLineRead(void); 28 | bool getError(void) {return error;}; 29 | }; 30 | 31 | #endif //__AS5047D_H__ 32 | -------------------------------------------------------------------------------- /firmware/stepServo/calibration.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #ifndef __CALIBRAITON_H__ 13 | #define __CALIBRAITON_H__ 14 | 15 | #include 16 | #include "syslog.h" 17 | #include "angle.h" 18 | 19 | 20 | //this file implements a table that is linearly interpolated circular calibration table 21 | // it is assumed the data wraps around, ie you interpolated 65536==0 22 | //we want this to be "whole" steps, for 1.8 degree motors this should be 200. 23 | // 200 will work for 0.9 degree too, but could be 400. However 400 is not good for 1.8 degree motors 24 | #define CALIBRATION_TABLE_SIZE (200) 25 | 26 | #define CALIBRATION_STEPS ((uint32_t)ANGLE_STEPS) // this is one rotation ie 0-65535 aka 65536 steps is 0-360 degrees 27 | 28 | #define CALIBRATION_ERROR_NOT_SET (-1) //indicated that the calibration value is not set. 29 | 30 | #define CALIBRATION_UPDATE_RATE (32) //number of samples to keep 1 pole running average 31 | #define CALIBRATION_MIN_ERROR (4) //the minimal expected error on our calibration 4 ~=+/0.2 degrees 32 | 33 | 34 | typedef struct { 35 | uint16_t table[CALIBRATION_TABLE_SIZE]; 36 | bool status; 37 | } FlashCalData_t; 38 | 39 | 40 | 41 | 42 | 43 | typedef struct { 44 | Angle value; //cal value 45 | int16_t error; //error assuming it is constantly updated 46 | } CalData_t; 47 | 48 | class CalibrationTable 49 | { 50 | private: 51 | CalData_t table[CALIBRATION_TABLE_SIZE]; 52 | 53 | bool fastCalVaild=false; 54 | void loadFromFlash(void); 55 | bool flashGood(void); //returns true if the flash copy of calibration is valid 56 | 57 | void updateFastCal(void); 58 | void createFastCal(void); 59 | 60 | public: 61 | void init(void); 62 | void saveToFlash(void); //saves the calibration to flash 63 | bool updateTableValue(int32_t index, int32_t value); 64 | void updateTable(Angle actualAngle, Angle encoderValue); 65 | int getValue(Angle actualAngle, CalData_t *ptrData); 66 | Angle getCal(Angle actualAngle); 67 | bool calValid(void); 68 | Angle reverseLookup(Angle encoderAngle); //this turns encoder angle into real angle 69 | void printCalTable(void); 70 | void smoothTable(void); 71 | 72 | Angle fastReverseLookup(Angle encoderAngle); 73 | }; 74 | 75 | 76 | 77 | 78 | #endif //__CALIBRAITON_H__ 79 | -------------------------------------------------------------------------------- /firmware/stepServo/command.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) Trampas Stern name of author 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 2 7 | of the License. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "command.h" 20 | #include 21 | 22 | 23 | #define ASCII_BACKSPACE 0x08 24 | #define ASCII_ESC 0x1B 25 | #define ASCII_UP_ARROW 0x9b 26 | //const char CMD_ANSI_UP[]= {ASCII_ESC,'[','A',0}; 27 | 28 | int strcicmp(char const *a, char const *b) 29 | { 30 | for (;; a++, b++) { 31 | int d = tolower(*a) - tolower(*b); 32 | if (d != 0 || !*a) 33 | return d; 34 | } 35 | } 36 | 37 | int CommandInit(sCmdUart *ptrUart, uint8_t (*kbhit)(void), uint8_t (*getch)(void),uint8_t (*putch)(char data),uint8_t (*puts)(uint8_t *buffer, uint8_t size) ) 38 | { 39 | ptrUart->kbhit=kbhit; 40 | ptrUart->getch=getch; 41 | ptrUart->putch=putch; 42 | ptrUart->puts=puts; 43 | ptrUart->histIndex=0; 44 | ptrUart->buffIndex=0; 45 | return 0; 46 | } 47 | 48 | #ifdef PGM_P //check and see if the PGM_P is defined for the AVR 49 | 50 | int CommandPrintf(sCmdUart *ptrUart, const char *fmt, ...) 51 | { 52 | int ret=0; 53 | char vastr[MAX_STRING]={0}; 54 | //char str[MAX_STRING]={0}; 55 | char *ptr; 56 | va_list ap; 57 | 58 | //LOG("Command printf"); 59 | memset(vastr,0,MAX_STRING); 60 | va_start(ap,fmt); 61 | ret=vsprintf(vastr,(const char *)fmt,ap); 62 | //ret=sprintf(vastr,"%s\r\n",str); 63 | //LOG("%s",vastr); 64 | if (ptrUart->puts!=NULL) 65 | { 66 | return ptrUart->puts((uint8_t *)vastr, (uint8_t)ret); 67 | } 68 | 69 | if (ptrUart->putch!=NULL) 70 | { 71 | ptr=vastr; 72 | while(*ptr) 73 | { 74 | ptrUart->putch(*ptr++); 75 | } 76 | 77 | return ret; 78 | } 79 | return 0; 80 | } 81 | 82 | 83 | #else 84 | int CommandPrintf(sCmdUart *ptrUart, char *fmt, ...) 85 | { 86 | int ret=0; 87 | char vastr[MAX_STRING]={0}; 88 | char *ptr; 89 | va_list ap; 90 | 91 | 92 | memset(vastr,0,MAX_STRING); 93 | va_start(ap,fmt); 94 | ret=vsprintf(vastr,(char *)fmt,ap); 95 | if (ptrUart->puts!=NULL) 96 | { 97 | return ptrUart->puts((uint8_t *)vastr, (uint8_t)ret); 98 | } 99 | 100 | if (ptrUart->putch!=NULL) 101 | { 102 | ptr=vastr; 103 | while(*ptr) 104 | { 105 | ptrUart->putch(*ptr++); 106 | } 107 | 108 | return ret; 109 | } 110 | return 0; 111 | } 112 | #endif 113 | 114 | 115 | // the delimiter is command/parameter delimiter 116 | // by default a ' '0x20 is used but for the TDR with GUI a ':' was preferred, not sure why 117 | // set to ' '/0x20 if you want normal command parsing, like DOS 118 | unsigned int CommandParse(sCmdUart *ptrUart,sCommand *ptrCmds, char *str, char delimitor ) 119 | { 120 | char *ptr; 121 | char *ptr2; 122 | unsigned int i; 123 | //char cmd[MAX_STRING]; 124 | char buff[MAX_CMD_LENGTH]; 125 | char argv[MAX_ARGS][MAX_ARG_LENGTH]; 126 | char *ptrArgv[MAX_ARGS]; 127 | unsigned int numArgs; 128 | int emptyArg=0; 129 | 130 | sCommand cmd_list; 131 | 132 | 133 | while (*str==0x20 || *str=='\n' || *str=='\r' || *str=='\t') str++; 134 | //first we need find command and arguments 135 | ptr=strchr(str,delimitor); //find first char 136 | 137 | //LOG("2parsing %s",str); 138 | 139 | 140 | if (ptr==0) 141 | { 142 | //we have two options, frist whole thing is command 143 | //second bad command 144 | if(strlen(str)>0) 145 | ptr=str+strlen(str); 146 | else 147 | return 0; //bad command 148 | } 149 | 150 | //copy string to command buffer. 151 | i=0; 152 | ptr2=str; 153 | while(ptr!=0 && ptr!=ptr2 && i<(MAX_CMD_LENGTH-1)) 154 | { 155 | //if (*ptr2!='\n' && *ptr2!='\r') //do not include newlines 156 | { 157 | buff[i++]=*ptr2; 158 | } 159 | ptr2++; 160 | } 161 | buff[i]=0; 162 | 163 | //now buff contains the command let's get the args 164 | numArgs=0; 165 | while(*ptr!=0 && (*ptr==' ' || *ptr==delimitor)) 166 | ptr++; //increment pointer past ' ' 167 | if (*ptr!=0) 168 | { 169 | if (*ptr==34) // " char 170 | { 171 | ptr++; 172 | ptr2=strchr(ptr,34); //find match 173 | } else if (*ptr==39) // 'char 174 | { 175 | ptr++; 176 | ptr2=strchr(ptr,39); //find match 177 | } else 178 | { 179 | ptr2=strchr(ptr,delimitor); 180 | } 181 | if (ptr2==0) 182 | { 183 | //we have two options, frist whole thing is command 184 | //second bad command 185 | //LOG("strlen ptr is %d",strlen(ptr)); 186 | if(strlen(ptr)>0) 187 | ptr2=ptr+strlen(ptr); 188 | } 189 | emptyArg=0; 190 | while((ptr2!=0 && numArgs0) 230 | ptr2=ptr+strlen(ptr); 231 | } 232 | } 233 | } 234 | } 235 | 236 | for(i=0; ikbhit()) 283 | { 284 | ptrUart->data=ptrUart->getch(); 285 | 286 | //echo the data 287 | ptrUart->putch(ptrUart->data); 288 | 289 | //if the data is the CR we need to process buffer 290 | if (ptrUart->data==0x0D) 291 | { 292 | ptrUart->putch(0x0A); 293 | if (strlen(ptrUart->buffer)>0) 294 | { 295 | if (ptrUart->lastChar!=ASCII_UP_ARROW) 296 | { 297 | strcpy(ptrUart->bufferHist[ptrUart->histIndex],ptrUart->buffer); 298 | ptrUart->histIndex=(ptrUart->histIndex+1) % CMD_HISTORY; 299 | } 300 | CommandParse(ptrUart,ptrCmds,ptrUart->buffer,delimitor); 301 | } 302 | 303 | CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt); 304 | ptrUart->buffIndex=0; 305 | ptrUart->buffer[ptrUart->buffIndex]=0; 306 | } 307 | 308 | if (ptrUart->data==ASCII_BACKSPACE) //backspace 309 | { 310 | if (ptrUart->buffIndex>0) 311 | { 312 | ptrUart->buffIndex--; 313 | ptrUart->buffer[ptrUart->buffIndex]='\0'; 314 | //Echo the backspace 315 | ptrUart->putch(' '); 316 | ptrUart->putch(ASCII_BACKSPACE); 317 | } 318 | }else if (ptrUart->data != 0x0A && ptrUart->data !=0x0D && ptrUart->data<127) 319 | { 320 | ptrUart->buffer[ptrUart->buffIndex++]=ptrUart->data; 321 | ptrUart->buffer[ptrUart->buffIndex]=0; 322 | } 323 | if (ptrUart->buffIndex>=(MAX_CMD_LENGTH-1)) 324 | { 325 | CommandPrintf(ptrUart,PSTR("\n\rERROR: Command buffer overflow\n\r"));\ 326 | ERROR("Command buffer overflow"); 327 | ptrUart->buffIndex=0; 328 | ptrUart->buffer[0]=0; 329 | CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt); 330 | } 331 | } 332 | 333 | 334 | if (strstr(ptrUart->buffer,ANSI_UP)) //up arrow 335 | { 336 | uint8_t i; 337 | 338 | CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt); 339 | i=CMD_HISTORY-1; 340 | if (ptrUart->histIndex>0) 341 | { 342 | i=ptrUart->histIndex-1; 343 | } 344 | if (strlen(ptrUart->bufferHist[i])>0) 345 | { 346 | strcpy(ptrUart->buffer,ptrUart->bufferHist[i]); 347 | ptrUart->buffIndex=strlen(ptrUart->buffer); 348 | CommandPrintf(ptrUart,PSTR("%s"),ptrUart->buffer); 349 | }else 350 | { 351 | ptrUart->buffIndex=0; 352 | ptrUart->buffer[0]=0; 353 | } 354 | ptrUart->data=ASCII_UP_ARROW; 355 | } 356 | 357 | 358 | ptrUart->lastChar=ptrUart->data; 359 | return 0; 360 | } 361 | 362 | -------------------------------------------------------------------------------- /firmware/stepServo/command.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __COMMAND_H 3 | #define __COMMAND_H 4 | 5 | #include 6 | #include 7 | #include "syslog.h" 8 | /* 9 | * Usage: 10 | * 11 | #include 12 | #include "uart_e0.h" 13 | 14 | sCmdUart KeyfobCmdUart; // UART used for the keyfob command line interface 15 | 16 | CMD_STR(help,"Displays this message"); 17 | 18 | //List of supported commands 19 | sCommand KeyfobCmds[] = 20 | { 21 | COMMAND(help), 22 | {"",0,""}, //End of list signal 23 | }; 24 | 25 | // print out the help strings for the commands 26 | static int help_cmd(sCmdUart *ptrUart,int argc, char * argv[]) 27 | { 28 | sCommand cmd_list; 29 | int i; 30 | 31 | //now let's parse the command 32 | i=0; 33 | memcpy(&cmd_list, &KeyfobCmds[i], sizeof(sCommand)); 34 | while(cmd_list.function!=0) 35 | { 36 | 37 | CommandPrintf(ptrUart,(cmd_list.name)); 38 | CommandPrintf(ptrUart,PSTR(" - ")); 39 | CommandPrintf(ptrUart,(cmd_list.help)); 40 | CommandPrintf(ptrUart,PSTR("\n\r")); 41 | i=i+1; 42 | memcpy(&cmd_list, &KeyfobCmds[i], sizeof(sCommand)); 43 | } 44 | return 0; 45 | } 46 | 47 | uint8_t KeyfobCmdGetChar(void) 48 | { 49 | uint8_t c; 50 | if (UARTE0_getc(&c)!=0) 51 | { 52 | ERROR("Uart getchar failed"); 53 | return 0; 54 | } 55 | return c; 56 | } 57 | int KeyfobCmdInit(PIN tx_pin, PIN rx_pin, uint32_t baud) 58 | { 59 | LOG("UARTE0 init"); 60 | UARTE0_Init(tx_pin, rx_pin, baud); 61 | CommandInit(&KeyfobCmdUart, UARTE0_kbhit, KeyfobCmdGetChar, UARTE0_putc,NULL); //set up the UART structure 62 | return 0; 63 | } 64 | 65 | int KeyfobCmdProcess(void) 66 | { 67 | return CommandProcess(&KeyfobCmdUart,KeyfobCmds,' ',KEYFOB_CMD_PROMPT); 68 | } 69 | 70 | Advantages: 71 | 1. You can actually have more than one UART/device connected to same command line interface. 72 | 2. works with harvard machines to save SRAM space using the PSTR functionality 73 | 3. You can swap out commands "on the fly" 74 | 75 | 76 | */ 77 | #define MAX_CMD_LENGTH 60 78 | #define MAX_ARGS 10 79 | #define MAX_ARG_LENGTH 40 80 | #define CMD_HISTORY 3 //number of commands in history buffer 81 | #define ASCII_BACKSPACE 0x08 82 | #define ASCII_ESC 0x1B 83 | #define ASCII_UP_ARROW 0x9b 84 | #define ANSI_UP "\x1B[A\0" 85 | 86 | #define MAX_STRING 255 87 | //const char ANSI_UP[]= {ASCII_ESC,'[','A',0}; 88 | 89 | typedef struct { 90 | uint8_t (*kbhit)(void); 91 | uint8_t (*getch)(void); 92 | uint8_t (*putch)(char data); 93 | uint8_t (*puts)(uint8_t *buffer, uint8_t size); 94 | uint8_t data; 95 | char buffer[MAX_CMD_LENGTH]; 96 | 97 | char bufferHist[CMD_HISTORY][MAX_CMD_LENGTH]; 98 | uint8_t histIndex; 99 | uint8_t buffIndex; 100 | uint8_t lastChar; 101 | }sCmdUart; 102 | 103 | 104 | #define COMMAND(NAME) { NAME ## _str, NAME ## _cmd, NAME ## _help} 105 | 106 | 107 | #ifdef PGM_P //check and see if the PGM_P is defined for the AVR 108 | 109 | //If so then we use the strings in flash not SRAM 110 | #define CMD_STR(NAME,STR) static const char NAME ## _help[] PROGMEM = STR; static const char NAME ## _str[] PROGMEM = #NAME; static int NAME ##_cmd(sCmdUart *ptrUart,int, char **); 111 | //Command structure 112 | typedef struct 113 | { 114 | PGM_P name; 115 | int (*function) (sCmdUart *ptrUart,int, char **); 116 | PGM_P help; 117 | } sCommand; 118 | int CommandPrintf(sCmdUart *ptrUart, const char *fmt, ...); 119 | 120 | #else 121 | 122 | #define CMD_STR(NAME,STR) static char NAME ## _help[] = STR; static char NAME ## _str[] = #NAME; static int NAME ##_cmd(sCmdUart *ptrUart,int, char **); 123 | 124 | //Command structure 125 | typedef struct 126 | { 127 | char *name; 128 | int (*function) (sCmdUart *ptrUart,int, char **); 129 | char *help; 130 | } sCommand; 131 | 132 | int CommandPrintf(sCmdUart *ptrUart, char *fmt, ...); 133 | #endif 134 | 135 | 136 | int CommandInit(sCmdUart *ptrUart, uint8_t (*kbhit)(void), uint8_t (*getch)(void),uint8_t (*putch)(char data),uint8_t (*puts)(uint8_t *buffer, uint8_t size)); 137 | unsigned int CommandParse(sCmdUart *ptrUart,sCommand *ptrCmds, char *str, char delimitor); 138 | int CommandProcess(sCmdUart *ptrUart,sCommand *ptrCmds, char delimitor, char *cmdPrompt); 139 | 140 | 141 | 142 | #endif 143 | 144 | -------------------------------------------------------------------------------- /firmware/stepServo/commands.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMANDS_H__ 2 | #define __COMMANDS_H__ 3 | #include 4 | #include "stepper_controller.h" 5 | #include "nzs.h" 6 | 7 | extern StepperCtrl stepperCtrl; 8 | extern eepromData_t PowerupEEPROM; 9 | 10 | void commandsInit(void); 11 | int commandsProcess(void); 12 | 13 | #endif //__COMMANDS_H__ 14 | -------------------------------------------------------------------------------- /firmware/stepServo/eeprom.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * eeprom.cpp 3 | * 4 | * Created on: May 30, 2017 5 | * Author: tstern 6 | */ 7 | #include "eeprom.h" 8 | #include "calibration.h" 9 | #include "Flash.h" 10 | #include "board.h" //for divide with rounding macro 11 | #include 12 | #include "syslog.h" 13 | 14 | //since we will write the following structure into each page, we need to find our latest page 15 | // to do this we will use the header to contain a checksum and write counter. 16 | #define EEPROM_SIZE (FLASH_ROW_SIZE*2) 17 | 18 | typedef struct { 19 | uint16_t checksum; 20 | uint16_t count; 21 | }eepromHeader_t; 22 | 23 | #define EEPROM_DATA_SIZE (FLASH_PAGE_SIZE_NZS-sizeof(eepromHeader_t)) 24 | typedef struct { 25 | eepromHeader_t header; 26 | uint8_t data[EEPROM_DATA_SIZE]; 27 | } eepromData_t; 28 | 29 | 30 | 31 | static eepromData_t EEPROMCache; 32 | 33 | static int32_t NextPageWrite=-1; 34 | 35 | //we need to reserve two pages for EEPROM 36 | __attribute__((__aligned__(FLASH_ROW_SIZE))) const uint8_t NVM_eeprom[EEPROM_SIZE]={0xFFF}; 37 | 38 | 39 | static uint16_t checksum(uint8_t *ptrData, uint32_t nBytes) 40 | { 41 | uint16_t sum=0; 42 | uint32_t i; 43 | i=0; 44 | //LOG("running checksum %d",nBytes); 45 | while(idata, EEPROM_DATA_SIZE); 61 | //LOG("checksum is %d %d",cs,ptrData->header.checksum); 62 | 63 | if (cs==ptrData->header.checksum) 64 | { 65 | //LOG("Page good %d",page); 66 | return true; 67 | } 68 | //LOG("page bad %d",page); 69 | return false; 70 | } 71 | 72 | static void printEEPROM(uint32_t page) 73 | { 74 | eepromData_t *ptrData; 75 | int i; 76 | ptrData=(eepromData_t *)&NVM_eeprom[page]; 77 | LOG("count %d", ptrData->header.count); 78 | LOG("checksum %d", ptrData->header.checksum); 79 | for (i=0; i<10; i++) 80 | { 81 | LOG("Data[%d]=%02X",i,ptrData->data[i]); 82 | } 83 | } 84 | 85 | static uint32_t findLastGoodPage(void) 86 | { 87 | uint32_t lastGoodPage=0; 88 | uint32_t page; 89 | uint16_t lastCnt=0; 90 | eepromData_t *ptrData; 91 | 92 | page=0; 93 | while(page < (EEPROM_SIZE)) 94 | { 95 | //LOG("checking page %d",page); 96 | if (isPageGood(page)) 97 | { 98 | ptrData=(eepromData_t *)&NVM_eeprom[page]; 99 | 100 | //check for roll over which is OK 101 | if (lastCnt==16534 && ptrData->header.count==1) 102 | { 103 | lastCnt=ptrData->header.count; 104 | lastGoodPage=page; 105 | } 106 | if (ptrData->header.count>lastCnt) 107 | { 108 | //make sure we have not rolled over. 109 | if ((ptrData->header.count-lastCnt)<(16534/2)) 110 | { 111 | lastCnt=ptrData->header.count; 112 | lastGoodPage=page; 113 | } 114 | } 115 | } 116 | page=page + FLASH_PAGE_SIZE_NZS; 117 | } 118 | //LOG("last good page %d",lastGoodPage); 119 | return lastGoodPage; 120 | } 121 | 122 | //find the next page to write 123 | static uint32_t eepromGetNextWritPage(void) 124 | { 125 | eepromHeader_t *ptrHeader; 126 | uint32_t page; 127 | uint32_t row; 128 | int blockCount; 129 | int done=0; 130 | 131 | //start at first address: 132 | page=0; 133 | 134 | while(page < (EEPROM_SIZE)) 135 | { 136 | //LOG("checking page %d",page); 137 | ptrHeader=(eepromHeader_t *) &NVM_eeprom[page]; 138 | if (ptrHeader->count == 0xFFFF) 139 | { 140 | uint32_t i; 141 | uint8_t *ptrData; 142 | //uint8_t erasedByte=(uint8_t)ptrHeader->count; 143 | bool erased=true; 144 | 145 | //verify page is erased 146 | ptrData= (uint8_t *)&NVM_eeprom[page]; 147 | 148 | for (i=0; i=EEPROM_SIZE) 175 | { 176 | row=0; 177 | //TODO we should make sure this not where good data is 178 | // however if it is what should we do? 179 | } 180 | 181 | //now we need to erase that row 182 | //WARNING("Erasing page %d",row*FLASH_ROW_SIZE); 183 | flashErase(&NVM_eeprom[row*FLASH_ROW_SIZE],FLASH_ROW_SIZE); 184 | page=row*FLASH_ROW_SIZE; 185 | //LOG("Next free page is %d",page); 186 | return page; 187 | } 188 | 189 | 190 | eepromError_t eepromInit(void) 191 | { 192 | uint32_t page; 193 | 194 | 195 | //find the last good page offset in flash 196 | page=findLastGoodPage(); 197 | LOG("EEPROM Init found page %d",page); 198 | if (isPageGood(page)) 199 | { 200 | LOG("EEPROM page good %d",page); 201 | memcpy(&EEPROMCache, &NVM_eeprom[page], sizeof(EEPROMCache)); 202 | 203 | NextPageWrite=eepromGetNextWritPage(); 204 | return EEPROM_OK; 205 | } 206 | //ERROR("page is bad"); 207 | memset(&EEPROMCache, 0, sizeof(EEPROMCache)); 208 | NextPageWrite=eepromGetNextWritPage(); 209 | return EEPROM_CORRUPT; 210 | } 211 | 212 | 213 | int eepromWriteCache(uint8_t *ptrData, uint32_t size) 214 | { 215 | //LOG("Cache write %d",size); 216 | if (NextPageWrite==-1) //some one did not init the module 217 | { 218 | //lets handle gracefully and do it ourselves 219 | eepromInit(); 220 | } 221 | if (size>EEPROM_DATA_SIZE) 222 | { 223 | size =EEPROM_DATA_SIZE; 224 | } 225 | memcpy(EEPROMCache.data, ptrData, size); 226 | EEPROMCache.header.checksum=checksum(EEPROMCache.data,EEPROM_DATA_SIZE); 227 | 228 | 229 | return size; 230 | } 231 | 232 | int eepromRead(uint8_t *ptrData, uint32_t size) //returns number of bytes actually read, whcih could be less than size requested 233 | { 234 | if (NextPageWrite==-1) //some one did not init the module 235 | { 236 | //lets handle gracefully and do it ourselves 237 | eepromInit(); 238 | } 239 | if (size>EEPROM_DATA_SIZE) 240 | { 241 | size =EEPROM_DATA_SIZE; 242 | } 243 | if (EEPROMCache.header.count == 0) 244 | { 245 | return 0; //cache is new/corrupt 246 | } 247 | memcpy(ptrData, EEPROMCache.data, size); 248 | return size; 249 | } 250 | 251 | eepromError_t eepromFlush(void) //flush the cache to flash memory 252 | { 253 | if (NextPageWrite==-1) 254 | { 255 | ERROR("EEPROM WRITE FAILED"); 256 | return EEPROM_FAILED; //most likely no one has written to cache 257 | } 258 | EEPROMCache.header.count++; 259 | if (EEPROMCache.header.count>=16535) 260 | { 261 | EEPROMCache.header.count=1; 262 | } 263 | //WARNING("Writting to Page %d",NextPageWrite); 264 | flashWrite(&NVM_eeprom[NextPageWrite], &EEPROMCache, sizeof(EEPROMCache)); 265 | 266 | // printEEPROM(NextPageWrite); 267 | 268 | if (!SYSCTRL->PCLKSR.bit.BOD33DET) //if not in brown out condition find next write location 269 | { 270 | //LOG("getting next page to write"); 271 | NextPageWrite=eepromGetNextWritPage(); //find next write location and erase if needed 272 | } else 273 | { 274 | //LOG("BOD active"); 275 | NextPageWrite=-1; //else we will just clear NextPageWrite location just in case we recover from brown out 276 | } 277 | return EEPROM_OK; 278 | } 279 | 280 | 281 | 282 | -------------------------------------------------------------------------------- /firmware/stepServo/eeprom.h: -------------------------------------------------------------------------------- 1 | /* 2 | * eeprom.h 3 | * 4 | * Created on: May 30, 2017 5 | * Author: tstern 6 | */ 7 | 8 | #ifndef EEPROM_H_ 9 | #define EEPROM_H_ 10 | #include "Flash.h" 11 | #include "calibration.h" 12 | #include "board.h" 13 | 14 | /* 15 | * This EEPROM implementation provides 60bytes of "eeprom space" (we reserve 4 bytes for overhead) 16 | * The EEPROM uses two rows of flash (256 bytes per row), which 17 | * for the SAMD21G18A this allows a minimual 200k writes, but typically 1200k 18 | */ 19 | 20 | typedef enum { 21 | EEPROM_OK =0, 22 | EEPROM_FAILED=1, 23 | EEPROM_CORRUPT=2, 24 | } eepromError_t; 25 | 26 | 27 | eepromError_t eepromInit(void); 28 | int eepromWriteCache(uint8_t *ptrData, uint32_t size); //returns number bytes written to cache 29 | eepromError_t eepromFlush(void); //flush the cache to flash memory 30 | int eepromRead(uint8_t *ptrData, uint32_t size); //returns number of bytes actually read, whcih could be less than size requested 31 | 32 | #endif /* EEPROM_H_ */ 33 | -------------------------------------------------------------------------------- /firmware/stepServo/fet_driver.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fet_driver.h 3 | * 4 | * Created on: Dec 24, 2016 5 | * Author: tstern 6 | * 7 | * This file supports using discrete FETs as drivers for stepper motor 8 | * 9 | * Misfit Tech invests time and resources providing this open source code, 10 | * please support Misfit Tech and open-source hardware by purchasing 11 | * products from Misfit Tech, www.misifittech.net! 12 | * 13 | * Written by Trampas Stern for Misfit Tech. 14 | * BSD license, check license.txt for more information 15 | * All text above, must be included in any redistribution 16 | *********************************************************************/ 17 | 18 | #ifndef FET_DRIVER_H_ 19 | #define FET_DRIVER_H_ 20 | 21 | 22 | 23 | #include 24 | #include "board.h" 25 | #include "angle.h" 26 | #include "sine.h" 27 | 28 | #ifdef NEMA_23_10A_HW 29 | #define FET_DRIVER_NUM_MICROSTEPS (SINE_STEPS/4) //number of steps to use for microstepping, default is 256 30 | #define FET_DRIVER_NUM_ZERO_AVG (100) 31 | 32 | 33 | #define FET_ADC_TO_MA(x) (((x)*2537)/1000) 34 | #define FET_MA_TO_ADC(x) (((x)*1000)/2537) 35 | //prvent someone for making a mistake with the code 36 | #if ((FET_DRIVER_NUM_MICROSTEPS*4) != SINE_STEPS) 37 | #error "SINE_STEPS must be 4x of Micro steps for the move function" 38 | #endif 39 | 40 | /* 41 | * When it comes to the stepper driver if we use angles 42 | * we will always have a rounding error. For example 43 | * a 0-65536(360) angle for 1.8 degree step is 327.68 so 44 | * if you increment 200 of these as 327 you have a 13.6 error 45 | * after one rotation. 46 | * If you use floating point the effect is the same but takes longer. 47 | * 48 | * The only error-less accumulation system is to use native units, ie full 49 | * steps and microsteps. 50 | * 51 | */ 52 | 53 | class FetDriver 54 | { 55 | static FetDriver *ptrInstance; 56 | private: 57 | uint32_t lastStepMicros; // time in microseconds that last step happened 58 | 59 | int32_t PWM_Table_B[512]; 60 | int32_t PWM_Table_A[512]; 61 | 62 | bool forwardRotation=true; 63 | volatile bool enabled=true; 64 | 65 | volatile int32_t adc; 66 | 67 | 68 | volatile int32_t coilB_value=0; 69 | volatile int32_t coilB_Zero=-1; 70 | volatile int32_t coilB_SetPoint=100; 71 | volatile int32_t coilB_error=0; 72 | 73 | volatile int32_t coilA_value=0; 74 | volatile int32_t coilA_Zero=-1; 75 | volatile int32_t coilA_SetPoint=200; 76 | volatile int32_t coilA_error=0; 77 | void ctrl_update(uint16_t channel, uint16_t value); 78 | void measureCoilB_zero(void); 79 | void measureCoilA_zero(void); 80 | void CalTableB(int32_t maxMA); 81 | void CalTableA(int32_t maxMA); 82 | int coilA_PWM(int32_t value); 83 | void coilB_PWM(int32_t value); 84 | int32_t getCoilB_mA(void); 85 | int32_t getCoilA_mA(void); 86 | public: 87 | 88 | static void ADC_Callback(uint16_t channel, uint16_t value); 89 | void begin(void); 90 | 91 | //moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step. 92 | int32_t move(int32_t stepAngle, uint32_t mA); 93 | 94 | uint32_t microsSinceStep(void) {return micros()-lastStepMicros;}; 95 | void setRotationDirection(bool forward) {forwardRotation=forward;}; 96 | 97 | void enable(bool enable) {enabled=enable;}; 98 | void limitCurrent(uint8_t x) {return;}; 99 | }; 100 | 101 | 102 | #endif //#ifdef NEMA_23_10A_HW 103 | #endif /* FET_DRIVER_H_ */ 104 | -------------------------------------------------------------------------------- /firmware/stepServo/ftoa.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "board.h" 3 | #include "ftoa.h" 4 | /******************************************************************* 5 | * FUNCTION: ftoa 6 | * AUTHOR = TRAMPAS STERN 7 | * FILE = strio.c 8 | * DATE = 2/6/2003 4:27:14 PM 9 | * 10 | * PARAMETERS: long,*str, int count 11 | * 12 | * DESCRIPTION: Convets an float to string 13 | * format 'f', 'E', or 'e' 14 | * 15 | * 16 | * RETURNS: 17 | * 18 | * NOTE this code was found on the web and modified to actually work 19 | *******************************************************************/ 20 | int ftoa (float x, char *str, char prec, char format) 21 | { 22 | 23 | int ie, i, k, ndig, fstyle; 24 | double y; 25 | char *start; 26 | 27 | start=str; 28 | 29 | //based on percission set number digits 30 | ndig=prec+1; 31 | if (prec<0) 32 | ndig=7; 33 | if (prec>22) 34 | ndig=23; 35 | 36 | fstyle = 0; //exponent 'e' 37 | if (format == 'f' || format == 'F') 38 | fstyle = 1; //normal 'f' 39 | if (format=='g' || format=='G') 40 | fstyle=2; 41 | 42 | ie = 0; 43 | /* if x negative, write minus and reverse */ 44 | if ( x < 0) 45 | { 46 | *str++ = '-'; 47 | x = -x; 48 | } 49 | 50 | //if (x<0.0) then increment by 10 till betwen 1.0 and 10.0 51 | if (x!=0.0) 52 | { 53 | while (x < 1.0) 54 | { 55 | x =x* 10.0; 56 | ie--; 57 | } 58 | } 59 | 60 | //if x>10 then let's shift it down 61 | while (x >= 10.0) 62 | { 63 | x = x*(1.0/10.0); 64 | ie++; 65 | } 66 | 67 | if (ABS(ie)>MAX_MANTISA) 68 | { 69 | if (fstyle==1) 70 | { 71 | fstyle=0; 72 | format='e'; 73 | //ie=2; 74 | } 75 | } 76 | 77 | 78 | /* in f format, number of digits is related to size */ 79 | if (fstyle) 80 | ndig =ndig + ie; 81 | 82 | if(prec==0 && ie>ndig && fstyle) 83 | { 84 | ndig=ie; 85 | } 86 | 87 | /* round. x is between 1 and 10 and ndig will be printed to 88 | right of decimal point so rounding is ... */ 89 | y=1; 90 | for (i = 1; i < ndig; i++) //find lest significant digit 91 | y = y *(1.0/10.0); //multiply by 1/10 is faster than divides 92 | 93 | x = x+ y *(1.0/2.0); //add rounding 94 | 95 | /* repair rounding disasters */ 96 | if (x >= 10.0) 97 | { 98 | x = 1.0; 99 | ie++; 100 | ndig++; 101 | } 102 | 103 | //check and see if the number is less than 1.0 104 | if (fstyle && ie<0) 105 | { 106 | *str++ = '0'; 107 | if (prec!=0) 108 | *str++ = '.'; 109 | if (ndig < 0) 110 | ie = ie-ndig; /* limit zeros if underflow */ 111 | for (i = -1; i > ie; i--) 112 | *str++ = '0'; 113 | } 114 | 115 | //for each digit 116 | for (i=0; i < ndig; i++) 117 | { 118 | float b; 119 | k = x; //k = most significant digit 120 | *str++ = k + '0'; //output the char representation 121 | if (((!fstyle && i==0) || (fstyle && i==ie)) && prec!=0) 122 | *str++ = '.'; //output a decimal point 123 | b=(float)k; 124 | //multiply by 10 before subtraction to remove 125 | //errors from limited number of bits in float. 126 | b=b*10.0; 127 | x=x*10.0; 128 | x =x - b; //subtract k from x 129 | //b=x+b; 130 | //x =x* 10.0; //get next digit 131 | } 132 | 133 | /* now, in estyle, put out exponent if not zero */ 134 | if (!fstyle && ie != 0) 135 | { 136 | *str++ = format; 137 | if (ie < 0) //if number has negative exponent 138 | { 139 | ie = -ie; 140 | *str++ = '-'; 141 | } 142 | 143 | //now we need to convert the exponent to string 144 | for (k=1000; k>ie; k=k/10); //find the decade of exponent 145 | 146 | for (; k > 0; k=k/10) 147 | { 148 | char t; 149 | t=DIV(ie,k); 150 | *str++ = t + '0'; 151 | ie = ie -(t*k); 152 | } 153 | 154 | } 155 | *str++ = '\0'; 156 | return (str-start); //return string length 157 | } 158 | -------------------------------------------------------------------------------- /firmware/stepServo/ftoa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ftoa.h 3 | * 4 | * Created on: Jan 6, 2017 5 | * Author: tstern 6 | */ 7 | 8 | #ifndef FTOA_H_ 9 | #define FTOA_H_ 10 | 11 | #define MAX_MANTISA (1000) 12 | 13 | int ftoa (float x, char *str, char prec, char format); 14 | 15 | 16 | 17 | #endif /* FTOA_H_ */ 18 | -------------------------------------------------------------------------------- /firmware/stepServo/gfxfont.h: -------------------------------------------------------------------------------- 1 | // Font structures for newer Adafruit_GFX (1.1 and later). 2 | // Example fonts are included in 'Fonts' directory. 3 | // To use a font in your Arduino sketch, #include the corresponding .h 4 | // file and pass address of GFXfont struct to setFont(). Pass NULL to 5 | // revert to 'classic' fixed-space bitmap font. 6 | 7 | #ifndef _GFXFONT_H_ 8 | #define _GFXFONT_H_ 9 | 10 | typedef struct { // Data stored PER GLYPH 11 | uint16_t bitmapOffset; // Pointer into GFXfont->bitmap 12 | uint8_t width, height; // Bitmap dimensions in pixels 13 | uint8_t xAdvance; // Distance to advance cursor (x axis) 14 | int8_t xOffset, yOffset; // Dist from cursor pos to UL corner 15 | } GFXglyph; 16 | 17 | typedef struct { // Data stored for FONT AS A WHOLE: 18 | uint8_t *bitmap; // Glyph bitmaps, concatenated 19 | GFXglyph *glyph; // Glyph array 20 | uint8_t first, last; // ASCII extents 21 | uint8_t yAdvance; // Newline distance (y axis) 22 | } GFXfont; 23 | 24 | #endif // _GFXFONT_H_ 25 | -------------------------------------------------------------------------------- /firmware/stepServo/glcdfont.c: -------------------------------------------------------------------------------- 1 | // This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0. 2 | // See gfxfont.h for newer custom bitmap font info. 3 | 4 | #ifndef FONT5X7_H 5 | #define FONT5X7_H 6 | 7 | #ifdef __AVR__ 8 | #include 9 | #include 10 | #elif defined(ESP8266) 11 | #include 12 | #else 13 | #define PROGMEM 14 | #endif 15 | 16 | // Standard ASCII 5x7 font 17 | 18 | static const unsigned char font[] PROGMEM = { 19 | 0x00, 0x00, 0x00, 0x00, 0x00, 20 | 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 21 | 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 22 | 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 23 | 0x18, 0x3C, 0x7E, 0x3C, 0x18, 24 | 0x1C, 0x57, 0x7D, 0x57, 0x1C, 25 | 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 26 | 0x00, 0x18, 0x3C, 0x18, 0x00, 27 | 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 28 | 0x00, 0x18, 0x24, 0x18, 0x00, 29 | 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 30 | 0x30, 0x48, 0x3A, 0x06, 0x0E, 31 | 0x26, 0x29, 0x79, 0x29, 0x26, 32 | 0x40, 0x7F, 0x05, 0x05, 0x07, 33 | 0x40, 0x7F, 0x05, 0x25, 0x3F, 34 | 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 35 | 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 36 | 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 37 | 0x14, 0x22, 0x7F, 0x22, 0x14, 38 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 39 | 0x06, 0x09, 0x7F, 0x01, 0x7F, 40 | 0x00, 0x66, 0x89, 0x95, 0x6A, 41 | 0x60, 0x60, 0x60, 0x60, 0x60, 42 | 0x94, 0xA2, 0xFF, 0xA2, 0x94, 43 | 0x08, 0x04, 0x7E, 0x04, 0x08, 44 | 0x10, 0x20, 0x7E, 0x20, 0x10, 45 | 0x08, 0x08, 0x2A, 0x1C, 0x08, 46 | 0x08, 0x1C, 0x2A, 0x08, 0x08, 47 | 0x1E, 0x10, 0x10, 0x10, 0x10, 48 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 49 | 0x30, 0x38, 0x3E, 0x38, 0x30, 50 | 0x06, 0x0E, 0x3E, 0x0E, 0x06, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x5F, 0x00, 0x00, 53 | 0x00, 0x07, 0x00, 0x07, 0x00, 54 | 0x14, 0x7F, 0x14, 0x7F, 0x14, 55 | 0x24, 0x2A, 0x7F, 0x2A, 0x12, 56 | 0x23, 0x13, 0x08, 0x64, 0x62, 57 | 0x36, 0x49, 0x56, 0x20, 0x50, 58 | 0x00, 0x08, 0x07, 0x03, 0x00, 59 | 0x00, 0x1C, 0x22, 0x41, 0x00, 60 | 0x00, 0x41, 0x22, 0x1C, 0x00, 61 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 62 | 0x08, 0x08, 0x3E, 0x08, 0x08, 63 | 0x00, 0x80, 0x70, 0x30, 0x00, 64 | 0x08, 0x08, 0x08, 0x08, 0x08, 65 | 0x00, 0x00, 0x60, 0x60, 0x00, 66 | 0x20, 0x10, 0x08, 0x04, 0x02, 67 | 0x3E, 0x51, 0x49, 0x45, 0x3E, 68 | 0x00, 0x42, 0x7F, 0x40, 0x00, 69 | 0x72, 0x49, 0x49, 0x49, 0x46, 70 | 0x21, 0x41, 0x49, 0x4D, 0x33, 71 | 0x18, 0x14, 0x12, 0x7F, 0x10, 72 | 0x27, 0x45, 0x45, 0x45, 0x39, 73 | 0x3C, 0x4A, 0x49, 0x49, 0x31, 74 | 0x41, 0x21, 0x11, 0x09, 0x07, 75 | 0x36, 0x49, 0x49, 0x49, 0x36, 76 | 0x46, 0x49, 0x49, 0x29, 0x1E, 77 | 0x00, 0x00, 0x14, 0x00, 0x00, 78 | 0x00, 0x40, 0x34, 0x00, 0x00, 79 | 0x00, 0x08, 0x14, 0x22, 0x41, 80 | 0x14, 0x14, 0x14, 0x14, 0x14, 81 | 0x00, 0x41, 0x22, 0x14, 0x08, 82 | 0x02, 0x01, 0x59, 0x09, 0x06, 83 | 0x3E, 0x41, 0x5D, 0x59, 0x4E, 84 | 0x7C, 0x12, 0x11, 0x12, 0x7C, 85 | 0x7F, 0x49, 0x49, 0x49, 0x36, 86 | 0x3E, 0x41, 0x41, 0x41, 0x22, 87 | 0x7F, 0x41, 0x41, 0x41, 0x3E, 88 | 0x7F, 0x49, 0x49, 0x49, 0x41, 89 | 0x7F, 0x09, 0x09, 0x09, 0x01, 90 | 0x3E, 0x41, 0x41, 0x51, 0x73, 91 | 0x7F, 0x08, 0x08, 0x08, 0x7F, 92 | 0x00, 0x41, 0x7F, 0x41, 0x00, 93 | 0x20, 0x40, 0x41, 0x3F, 0x01, 94 | 0x7F, 0x08, 0x14, 0x22, 0x41, 95 | 0x7F, 0x40, 0x40, 0x40, 0x40, 96 | 0x7F, 0x02, 0x1C, 0x02, 0x7F, 97 | 0x7F, 0x04, 0x08, 0x10, 0x7F, 98 | 0x3E, 0x41, 0x41, 0x41, 0x3E, 99 | 0x7F, 0x09, 0x09, 0x09, 0x06, 100 | 0x3E, 0x41, 0x51, 0x21, 0x5E, 101 | 0x7F, 0x09, 0x19, 0x29, 0x46, 102 | 0x26, 0x49, 0x49, 0x49, 0x32, 103 | 0x03, 0x01, 0x7F, 0x01, 0x03, 104 | 0x3F, 0x40, 0x40, 0x40, 0x3F, 105 | 0x1F, 0x20, 0x40, 0x20, 0x1F, 106 | 0x3F, 0x40, 0x38, 0x40, 0x3F, 107 | 0x63, 0x14, 0x08, 0x14, 0x63, 108 | 0x03, 0x04, 0x78, 0x04, 0x03, 109 | 0x61, 0x59, 0x49, 0x4D, 0x43, 110 | 0x00, 0x7F, 0x41, 0x41, 0x41, 111 | 0x02, 0x04, 0x08, 0x10, 0x20, 112 | 0x00, 0x41, 0x41, 0x41, 0x7F, 113 | 0x04, 0x02, 0x01, 0x02, 0x04, 114 | 0x40, 0x40, 0x40, 0x40, 0x40, 115 | 0x00, 0x03, 0x07, 0x08, 0x00, 116 | 0x20, 0x54, 0x54, 0x78, 0x40, 117 | 0x7F, 0x28, 0x44, 0x44, 0x38, 118 | 0x38, 0x44, 0x44, 0x44, 0x28, 119 | 0x38, 0x44, 0x44, 0x28, 0x7F, 120 | 0x38, 0x54, 0x54, 0x54, 0x18, 121 | 0x00, 0x08, 0x7E, 0x09, 0x02, 122 | 0x18, 0xA4, 0xA4, 0x9C, 0x78, 123 | 0x7F, 0x08, 0x04, 0x04, 0x78, 124 | 0x00, 0x44, 0x7D, 0x40, 0x00, 125 | 0x20, 0x40, 0x40, 0x3D, 0x00, 126 | 0x7F, 0x10, 0x28, 0x44, 0x00, 127 | 0x00, 0x41, 0x7F, 0x40, 0x00, 128 | 0x7C, 0x04, 0x78, 0x04, 0x78, 129 | 0x7C, 0x08, 0x04, 0x04, 0x78, 130 | 0x38, 0x44, 0x44, 0x44, 0x38, 131 | 0xFC, 0x18, 0x24, 0x24, 0x18, 132 | 0x18, 0x24, 0x24, 0x18, 0xFC, 133 | 0x7C, 0x08, 0x04, 0x04, 0x08, 134 | 0x48, 0x54, 0x54, 0x54, 0x24, 135 | 0x04, 0x04, 0x3F, 0x44, 0x24, 136 | 0x3C, 0x40, 0x40, 0x20, 0x7C, 137 | 0x1C, 0x20, 0x40, 0x20, 0x1C, 138 | 0x3C, 0x40, 0x30, 0x40, 0x3C, 139 | 0x44, 0x28, 0x10, 0x28, 0x44, 140 | 0x4C, 0x90, 0x90, 0x90, 0x7C, 141 | 0x44, 0x64, 0x54, 0x4C, 0x44, 142 | 0x00, 0x08, 0x36, 0x41, 0x00, 143 | 0x00, 0x00, 0x77, 0x00, 0x00, 144 | 0x00, 0x41, 0x36, 0x08, 0x00, 145 | 0x02, 0x01, 0x02, 0x04, 0x02, 146 | 0x3C, 0x26, 0x23, 0x26, 0x3C, 147 | 0x1E, 0xA1, 0xA1, 0x61, 0x12, 148 | 0x3A, 0x40, 0x40, 0x20, 0x7A, 149 | 0x38, 0x54, 0x54, 0x55, 0x59, 150 | 0x21, 0x55, 0x55, 0x79, 0x41, 151 | 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut 152 | 0x21, 0x55, 0x54, 0x78, 0x40, 153 | 0x20, 0x54, 0x55, 0x79, 0x40, 154 | 0x0C, 0x1E, 0x52, 0x72, 0x12, 155 | 0x39, 0x55, 0x55, 0x55, 0x59, 156 | 0x39, 0x54, 0x54, 0x54, 0x59, 157 | 0x39, 0x55, 0x54, 0x54, 0x58, 158 | 0x00, 0x00, 0x45, 0x7C, 0x41, 159 | 0x00, 0x02, 0x45, 0x7D, 0x42, 160 | 0x00, 0x01, 0x45, 0x7C, 0x40, 161 | 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut 162 | 0xF0, 0x28, 0x25, 0x28, 0xF0, 163 | 0x7C, 0x54, 0x55, 0x45, 0x00, 164 | 0x20, 0x54, 0x54, 0x7C, 0x54, 165 | 0x7C, 0x0A, 0x09, 0x7F, 0x49, 166 | 0x32, 0x49, 0x49, 0x49, 0x32, 167 | 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut 168 | 0x32, 0x4A, 0x48, 0x48, 0x30, 169 | 0x3A, 0x41, 0x41, 0x21, 0x7A, 170 | 0x3A, 0x42, 0x40, 0x20, 0x78, 171 | 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 172 | 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut 173 | 0x3D, 0x40, 0x40, 0x40, 0x3D, 174 | 0x3C, 0x24, 0xFF, 0x24, 0x24, 175 | 0x48, 0x7E, 0x49, 0x43, 0x66, 176 | 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 177 | 0xFF, 0x09, 0x29, 0xF6, 0x20, 178 | 0xC0, 0x88, 0x7E, 0x09, 0x03, 179 | 0x20, 0x54, 0x54, 0x79, 0x41, 180 | 0x00, 0x00, 0x44, 0x7D, 0x41, 181 | 0x30, 0x48, 0x48, 0x4A, 0x32, 182 | 0x38, 0x40, 0x40, 0x22, 0x7A, 183 | 0x00, 0x7A, 0x0A, 0x0A, 0x72, 184 | 0x7D, 0x0D, 0x19, 0x31, 0x7D, 185 | 0x26, 0x29, 0x29, 0x2F, 0x28, 186 | 0x26, 0x29, 0x29, 0x29, 0x26, 187 | 0x30, 0x48, 0x4D, 0x40, 0x20, 188 | 0x38, 0x08, 0x08, 0x08, 0x08, 189 | 0x08, 0x08, 0x08, 0x08, 0x38, 190 | 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 191 | 0x2F, 0x10, 0x28, 0x34, 0xFA, 192 | 0x00, 0x00, 0x7B, 0x00, 0x00, 193 | 0x08, 0x14, 0x2A, 0x14, 0x22, 194 | 0x22, 0x14, 0x2A, 0x14, 0x08, 195 | 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code 196 | 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block 197 | 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block 198 | 0x00, 0x00, 0x00, 0xFF, 0x00, 199 | 0x10, 0x10, 0x10, 0xFF, 0x00, 200 | 0x14, 0x14, 0x14, 0xFF, 0x00, 201 | 0x10, 0x10, 0xFF, 0x00, 0xFF, 202 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 203 | 0x14, 0x14, 0x14, 0xFC, 0x00, 204 | 0x14, 0x14, 0xF7, 0x00, 0xFF, 205 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 206 | 0x14, 0x14, 0xF4, 0x04, 0xFC, 207 | 0x14, 0x14, 0x17, 0x10, 0x1F, 208 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 209 | 0x14, 0x14, 0x14, 0x1F, 0x00, 210 | 0x10, 0x10, 0x10, 0xF0, 0x00, 211 | 0x00, 0x00, 0x00, 0x1F, 0x10, 212 | 0x10, 0x10, 0x10, 0x1F, 0x10, 213 | 0x10, 0x10, 0x10, 0xF0, 0x10, 214 | 0x00, 0x00, 0x00, 0xFF, 0x10, 215 | 0x10, 0x10, 0x10, 0x10, 0x10, 216 | 0x10, 0x10, 0x10, 0xFF, 0x10, 217 | 0x00, 0x00, 0x00, 0xFF, 0x14, 218 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 219 | 0x00, 0x00, 0x1F, 0x10, 0x17, 220 | 0x00, 0x00, 0xFC, 0x04, 0xF4, 221 | 0x14, 0x14, 0x17, 0x10, 0x17, 222 | 0x14, 0x14, 0xF4, 0x04, 0xF4, 223 | 0x00, 0x00, 0xFF, 0x00, 0xF7, 224 | 0x14, 0x14, 0x14, 0x14, 0x14, 225 | 0x14, 0x14, 0xF7, 0x00, 0xF7, 226 | 0x14, 0x14, 0x14, 0x17, 0x14, 227 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 228 | 0x14, 0x14, 0x14, 0xF4, 0x14, 229 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 230 | 0x00, 0x00, 0x1F, 0x10, 0x1F, 231 | 0x00, 0x00, 0x00, 0x1F, 0x14, 232 | 0x00, 0x00, 0x00, 0xFC, 0x14, 233 | 0x00, 0x00, 0xF0, 0x10, 0xF0, 234 | 0x10, 0x10, 0xFF, 0x10, 0xFF, 235 | 0x14, 0x14, 0x14, 0xFF, 0x14, 236 | 0x10, 0x10, 0x10, 0x1F, 0x00, 237 | 0x00, 0x00, 0x00, 0xF0, 0x10, 238 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 239 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 240 | 0xFF, 0xFF, 0xFF, 0x00, 0x00, 241 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 242 | 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 243 | 0x38, 0x44, 0x44, 0x38, 0x44, 244 | 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta 245 | 0x7E, 0x02, 0x02, 0x06, 0x06, 246 | 0x02, 0x7E, 0x02, 0x7E, 0x02, 247 | 0x63, 0x55, 0x49, 0x41, 0x63, 248 | 0x38, 0x44, 0x44, 0x3C, 0x04, 249 | 0x40, 0x7E, 0x20, 0x1E, 0x20, 250 | 0x06, 0x02, 0x7E, 0x02, 0x02, 251 | 0x99, 0xA5, 0xE7, 0xA5, 0x99, 252 | 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 253 | 0x4C, 0x72, 0x01, 0x72, 0x4C, 254 | 0x30, 0x4A, 0x4D, 0x4D, 0x30, 255 | 0x30, 0x48, 0x78, 0x48, 0x30, 256 | 0xBC, 0x62, 0x5A, 0x46, 0x3D, 257 | 0x3E, 0x49, 0x49, 0x49, 0x00, 258 | 0x7E, 0x01, 0x01, 0x01, 0x7E, 259 | 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 260 | 0x44, 0x44, 0x5F, 0x44, 0x44, 261 | 0x40, 0x51, 0x4A, 0x44, 0x40, 262 | 0x40, 0x44, 0x4A, 0x51, 0x40, 263 | 0x00, 0x00, 0xFF, 0x01, 0x03, 264 | 0xE0, 0x80, 0xFF, 0x00, 0x00, 265 | 0x08, 0x08, 0x6B, 0x6B, 0x08, 266 | 0x36, 0x12, 0x36, 0x24, 0x36, 267 | 0x06, 0x0F, 0x09, 0x0F, 0x06, 268 | 0x00, 0x00, 0x18, 0x18, 0x00, 269 | 0x00, 0x00, 0x10, 0x10, 0x00, 270 | 0x30, 0x40, 0xFF, 0x01, 0x01, 271 | 0x00, 0x1F, 0x01, 0x01, 0x1E, 272 | 0x00, 0x19, 0x1D, 0x17, 0x12, 273 | 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 274 | 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP 275 | }; 276 | #endif // FONT5X7_H 277 | -------------------------------------------------------------------------------- /firmware/stepServo/nonvolatile.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #include "nonvolatile.h" 13 | #include "Flash.h" //thanks to Kent Larsen for pointing out the lower case error 14 | #include 15 | 16 | 17 | 18 | 19 | //we use this so we can hard code calibration table 20 | // be sure to set the last word as status flag 21 | // this save time calibrating each time we do a code build 22 | #ifdef NZS_FAST_CAL 23 | __attribute__((__aligned__(FLASH_ROW_SIZE))) const uint16_t NVM_flash[16640]={ //allocates 33280 bytes 24 | #else 25 | __attribute__((__aligned__(FLASH_ROW_SIZE))) const uint16_t NVM_flash[256]={ //allocates 512 bytes 26 | #endif 27 | //insert the getcal command calibration data here 28 | 0xFFFF 29 | }; 30 | 31 | 32 | 33 | static_assert (sizeof(nvm_t)CalibrationTable,ptrData,size); 45 | return true; 46 | } 47 | 48 | bool nvmWrite_sPID(float Kp, float Ki, float Kd) 49 | { 50 | PIDparams_t pid; 51 | 52 | pid.Kp=Kp; 53 | pid.Ki=Ki; 54 | pid.Kd=Kd; 55 | pid.parametersVaild=true; 56 | 57 | flashWrite((void *)&NVM->sPID,&pid,sizeof(pid)); 58 | return true; 59 | } 60 | 61 | bool nvmWrite_vPID(float Kp, float Ki, float Kd) 62 | { 63 | PIDparams_t pid; 64 | 65 | pid.Kp=Kp; 66 | pid.Ki=Ki; 67 | pid.Kd=Kd; 68 | pid.parametersVaild=true; 69 | 70 | flashWrite((void *)&NVM->vPID,&pid,sizeof(pid)); 71 | return true; 72 | } 73 | 74 | bool nvmWrite_pPID(float Kp, float Ki, float Kd) 75 | { 76 | PIDparams_t pid; 77 | 78 | pid.Kp=Kp; 79 | pid.Ki=Ki; 80 | pid.Kd=Kd; 81 | pid.parametersVaild=true; 82 | 83 | flashWrite((void *)&NVM->pPID,&pid,sizeof(pid)); 84 | return true; 85 | } 86 | 87 | bool nvmWriteSystemParms(SystemParams_t &systemParams) 88 | { 89 | systemParams.parametersVaild=true; 90 | 91 | flashWrite((void *)&NVM->SystemParams,&systemParams,sizeof(systemParams)); 92 | return true; 93 | } 94 | 95 | bool nvmWriteMotorParms(MotorParams_t &motorParams) 96 | { 97 | motorParams.parametersVaild=true; 98 | 99 | flashWrite((void *)&NVM->motorParams,&motorParams,sizeof(motorParams)); 100 | return true; 101 | } 102 | 103 | bool nvmErase(void) 104 | { 105 | bool data=false; 106 | uint16_t cs=0; 107 | 108 | flashWrite((void *)&NVM->CalibrationTable.status,&data,sizeof(data)); 109 | flashWrite((void *)&NVM->sPID.parametersVaild ,&data,sizeof(data)); 110 | flashWrite((void *)&NVM->vPID.parametersVaild ,&data,sizeof(data)); 111 | flashWrite((void *)&NVM->pPID.parametersVaild ,&data,sizeof(data)); 112 | flashWrite((void *)&NVM->motorParams.parametersVaild ,&data,sizeof(data)); 113 | flashWrite((void *)&NVM->SystemParams.parametersVaild ,&data,sizeof(data)); 114 | #ifdef NZS_FAST_CAL 115 | flashWrite((void *)&NVM->FastCal.checkSum,&cs,sizeof(cs)); 116 | #endif 117 | } 118 | 119 | -------------------------------------------------------------------------------- /firmware/stepServo/nonvolatile.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #ifndef __NONVOLATILE__H__ 13 | #define __NONVOLATILE__H__ 14 | 15 | #include "calibration.h" 16 | #include "board.h" 17 | 18 | 19 | typedef struct { 20 | float Kp; 21 | float Ki; 22 | float Kd; 23 | bool parametersVaild; 24 | } PIDparams_t; 25 | 26 | typedef struct { 27 | int32_t currentMa; //maximum current for the motor 28 | int32_t currentHoldMa; //hold current for the motor 29 | bool motorWiring; //forward wiring of motor or reverse 30 | int32_t fullStepsPerRotation; //how many full steps per rotation is the motor 31 | bool parametersVaild; 32 | } MotorParams_t; 33 | 34 | typedef struct { 35 | int32_t microsteps; //number of microsteps on the dir/step pin interface from host 36 | RotationDir_t dirPinRotation; //is the direction pin high for clockwise or counterClockWise 37 | int32_t errorLimit; //error limit before error pin asserts 65536==360degrees 38 | ErrorPinMode_t errorPinMode; //is error pin used for enable, error, or bidirectional 39 | feedbackCtrl_t controllerMode; //feedback mode for the controller 40 | bool parametersVaild; 41 | } SystemParams_t; 42 | 43 | #ifdef NZS_FAST_CAL 44 | typedef struct { 45 | uint16_t angle[16384]; 46 | uint16_t checkSum; 47 | }FastCal_t; 48 | #endif 49 | 50 | typedef struct { 51 | FlashCalData_t CalibrationTable; 52 | __attribute__((__aligned__(8))) PIDparams_t sPID; //simple PID parameters 53 | __attribute__((__aligned__(8))) PIDparams_t pPID; //position PID parameters 54 | __attribute__((__aligned__(8))) PIDparams_t vPID; //velocity PID parameters 55 | __attribute__((__aligned__(8))) SystemParams_t SystemParams; 56 | __attribute__((__aligned__(8))) MotorParams_t motorParams; 57 | #ifdef NZS_FAST_CAL 58 | __attribute__((__aligned__(8))) FastCal_t FastCal; 59 | #endif 60 | } nvm_t; 61 | 62 | #ifdef NZS_FAST_CAL 63 | extern const uint16_t NVM_flash[16640]; 64 | #else 65 | extern const uint16_t NVM_flash[256]; 66 | #endif 67 | #define NVM ((const nvm_t *)NVM_flash) 68 | 69 | bool nvmWriteCalTable(void *ptrData, uint32_t size); 70 | bool nvmWrite_sPID(float Kp, float Ki, float Kd); 71 | bool nvmWrite_pPID(float Kp, float Ki, float Kd); 72 | bool nvmWrite_vPID(float Kp, float Ki, float Kd); 73 | bool nvmWriteSystemParms(SystemParams_t &systemParams); 74 | bool nvmWriteMotorParms(MotorParams_t &motorParams); 75 | bool nvmErase(void); 76 | 77 | #endif // __NONVOLATILE__H__ 78 | -------------------------------------------------------------------------------- /firmware/stepServo/nzs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * nzs.h 3 | * 4 | * Created on: Dec 8, 2016 5 | * Author: trampas 6 | * 7 | * Misfit Tech invests time and resources providing this open source code, 8 | * please support Misfit Tech and open-source hardware by purchasing 9 | * products from Misfit Tech, www.misifittech.net! 10 | * 11 | * Written by Trampas Stern for Misfit Tech. 12 | * BSD license, check license.txt for more information 13 | * All text above, must be included in any redistribution 14 | *********************************************************************/ 15 | 16 | #ifndef NZS_H_ 17 | #define NZS_H_ 18 | 19 | #include "board.h" 20 | #include "nzs_lcd.h" 21 | #include "stepper_controller.h" 22 | #include "planner.h" 23 | 24 | typedef struct 25 | { 26 | int64_t angle; 27 | uint16_t encoderAngle; 28 | uint8_t valid; 29 | }eepromData_t; 30 | 31 | class NZS //nano Zero Stepper 32 | { 33 | 34 | public: 35 | void begin(void); 36 | void loop(void); 37 | 38 | }; 39 | 40 | 41 | #endif /* NZS_H_ */ 42 | -------------------------------------------------------------------------------- /firmware/stepServo/nzs_lcd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * nzs_lcd.h 3 | * 4 | * Created on: Dec 8, 2016 5 | * Author: trampas 6 | * 7 | * 8 | * Misfit Tech invests time and resources providing this open source code, 9 | * please support Misfit Tech and open-source hardware by purchasing 10 | * products from Misfit Tech, www.misifittech.net! 11 | * 12 | * Written by Trampas Stern for Misfit Tech. 13 | * BSD license, check license.txt for more information 14 | * All text above, must be included in any redistribution 15 | *********************************************************************/ 16 | 17 | #ifndef NZS_LCD_H_ 18 | #define NZS_LCD_H_ 19 | 20 | #include "Arduino.h" 21 | #include "syslog.h" 22 | #include "board.h" 23 | #include "stepper_controller.h" 24 | 25 | #include "Adafruit_GFX.h" 26 | #include "Adafruit_SSD1306.h" 27 | #include "gfxfont.h" 28 | 29 | 30 | typedef struct { 31 | char str[15]; 32 | } options_t; 33 | 34 | typedef struct { 35 | char str[15]; 36 | 37 | //only one of the following should be not null 38 | int (*func)(int argc, char *argv[]); 39 | options_t *ptrOptions; 40 | 41 | } menuItem_t; 42 | 43 | 44 | 45 | 46 | 47 | class NZS_LCD 48 | { 49 | private: 50 | bool displayEnabled; 51 | Adafruit_SSD1306 display; 52 | StepperCtrl *ptrStepperCtrl; 53 | menuItem_t *ptrMenu; 54 | int32_t menuIndex; 55 | bool menuActive; 56 | 57 | options_t *ptrOptions; 58 | int32_t optionIndex; 59 | 60 | int32_t buttonState; 61 | 62 | void updateLCD(void); 63 | void showMenu(void); 64 | void updateMenu(void); 65 | void showOptions(void); 66 | public: 67 | void forceMenuActive(void); 68 | void setMenu(menuItem_t *pMenu); 69 | void begin(StepperCtrl *ptrStepperCtrl); //sets up the LCD 70 | void process(void); //processes the LCD and updates as needed 71 | void showSplash(void); 72 | void lcdShow(const char *line1, const char *line2,const char *line3); 73 | 74 | 75 | }; 76 | 77 | 78 | #endif /* NZS_LCD_H_ */ 79 | -------------------------------------------------------------------------------- /firmware/stepServo/planner.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #include "planner.h" 13 | 14 | #include "board.h" 15 | #include "wiring_private.h" 16 | #include "syslog.h" 17 | #include "angle.h" 18 | #include "Arduino.h" 19 | 20 | #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY); 21 | 22 | //define the planner class as being global 23 | Planner SmartPlanner; 24 | 25 | static bool enterTC3CriticalSection() 26 | { 27 | bool state=NVIC_IS_IRQ_ENABLED(TC3_IRQn); 28 | NVIC_DisableIRQ(TC3_IRQn); 29 | return state; 30 | } 31 | 32 | static void exitTC3CriticalSection(bool prevState) 33 | { 34 | if (prevState) 35 | { 36 | NVIC_EnableIRQ(TC3_IRQn); 37 | } //else do nothing 38 | } 39 | 40 | 41 | 42 | 43 | void TC3_Init(void) 44 | { 45 | // Enable GCLK for TC3 46 | GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 )) ; 47 | while (GCLK->STATUS.bit.SYNCBUSY); 48 | 49 | TC3->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; // Disable TCx 50 | WAIT_TC16_REGS_SYNC(TC3) // wait for sync 51 | 52 | TC3->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16; // Set Timer counter Mode to 16 bits 53 | WAIT_TC16_REGS_SYNC(TC3) 54 | 55 | TC3->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ; // Set TC as normal Normal Frq 56 | WAIT_TC16_REGS_SYNC(TC3) 57 | 58 | TC3->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV2; // Set perscaler 59 | WAIT_TC16_REGS_SYNC(TC3) 60 | 61 | 62 | TC3->COUNT16.CC[0].reg = F_CPU/PLANNER_UPDATE_RATE_HZ/2; //divide by two because of prescaler 63 | 64 | WAIT_TC16_REGS_SYNC(TC3) 65 | 66 | 67 | TC3->COUNT16.INTENSET.reg = 0; // disable all interrupts 68 | TC3->COUNT16.INTENSET.bit.OVF = 1; // enable overfollow 69 | 70 | 71 | 72 | NVIC_SetPriority(TC3_IRQn, 3); 73 | 74 | 75 | // Enable InterruptVector 76 | NVIC_EnableIRQ(TC3_IRQn); 77 | 78 | 79 | // Enable TC 80 | TC3->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; 81 | WAIT_TC16_REGS_SYNC(TC3); 82 | } 83 | 84 | 85 | void TC3_Handler(void) 86 | { 87 | //do the planner tick 88 | SmartPlanner.tick(); 89 | //SerialUSB.println('x'); 90 | TC3->COUNT16.INTFLAG.bit.OVF = 1; //clear interrupt by writing 1 to flag 91 | } 92 | 93 | void Planner::begin(StepperCtrl *ptrStepper) 94 | { 95 | 96 | ptrStepperCtrl=ptrStepper; 97 | currentMode=PLANNER_NONE; 98 | //setup the timer and interrupt as the last thing 99 | TC3_Init(); 100 | } 101 | 102 | void Planner::tick(void) 103 | { 104 | if (currentMode == PLANNER_NONE) 105 | { 106 | return; //do nothing 107 | } 108 | 109 | if (PLANNER_CV == currentMode) 110 | { 111 | // SerialUSB.println(currentSetAngle); 112 | // SerialUSB.println(endAngle); 113 | // SerialUSB.println(tickIncrement); 114 | // SerialUSB.println(fabs(currentSetAngle-endAngle)); 115 | // SerialUSB.println(fabs(tickIncrement*2)); 116 | // SerialUSB.println(); 117 | int32_t x; 118 | if (fabs(currentSetAngle-endAngle) >= fabs(tickIncrement)) 119 | { 120 | currentSetAngle+=tickIncrement; 121 | x=ANGLE_FROM_DEGREES(currentSetAngle); 122 | ptrStepperCtrl->moveToAbsAngle(x); 123 | }else 124 | { 125 | //we are done, make sure we end at the right point 126 | //SerialUSB.println("done"); 127 | x=ANGLE_FROM_DEGREES(endAngle); 128 | ptrStepperCtrl->moveToAbsAngle(x); 129 | currentMode=PLANNER_NONE; 130 | } 131 | } 132 | 133 | 134 | } 135 | 136 | void Planner::stop(void) 137 | { 138 | bool state; 139 | state = enterTC3CriticalSection(); 140 | currentMode=PLANNER_NONE; 141 | exitTC3CriticalSection(state); 142 | } 143 | 144 | bool Planner::moveConstantVelocity(float finalAngle, float rpm) 145 | { 146 | bool state; 147 | state = enterTC3CriticalSection(); 148 | 149 | //first determine if operation is in progress 150 | if (PLANNER_NONE != currentMode) 151 | { 152 | //we are in operation return false 153 | SerialUSB.println("planner operational"); 154 | exitTC3CriticalSection(state); 155 | return false; 156 | } 157 | 158 | //get current posistion 159 | startAngle = ANGLE_T0_DEGREES(ptrStepperCtrl->getCurrentAngle()); 160 | 161 | //deterime the tick increment 162 | tickIncrement=360.0*fabs(rpm)/60/PLANNER_UPDATE_RATE_HZ; 163 | 164 | 165 | 166 | //set the desired end angle 167 | endAngle=finalAngle; 168 | 169 | 170 | //set the current angle 171 | currentSetAngle=startAngle; 172 | 173 | if (startAngle>endAngle) 174 | { 175 | SerialUSB.println("reverse"); 176 | tickIncrement=-tickIncrement; 177 | } 178 | 179 | // SerialUSB.println(currentSetAngle); 180 | // SerialUSB.println(endAngle); 181 | // SerialUSB.println(tickIncrement); 182 | // SerialUSB.println(); 183 | 184 | currentMode=PLANNER_CV; 185 | 186 | exitTC3CriticalSection(state); 187 | return true; 188 | } 189 | -------------------------------------------------------------------------------- /firmware/stepServo/planner.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | 13 | /* 14 | * This file implements a trajectory planner for use with serial 15 | * interface. It allows the smart stepper to move at constant velocity. 16 | * Additionally you can move to some location at constant velocity or 17 | * with a trajectory curve 18 | */ 19 | 20 | #ifndef PLANNER_H_ 21 | #define PLANNER_H_ 22 | #include "board.h" 23 | #include "stepper_controller.h" 24 | 25 | #define PLANNER_UPDATE_RATE_HZ (3000UL) //how often planner updates PID 26 | 27 | typedef enum { 28 | PLANNER_NONE =0, 29 | PLANNER_CV =1, //constant velocity 30 | //PLANNER_CA =2, //constant accleration 31 | //PLANNER_S_CURVE =3, //s-curve move 32 | } PlannerMode; 33 | class Planner 34 | { 35 | private: 36 | StepperCtrl *ptrStepperCtrl; 37 | volatile PlannerMode currentMode=PLANNER_NONE; 38 | //todo we should not use floating point, rather use "Angle" 39 | volatile float endAngle; 40 | volatile float startAngle; 41 | volatile float currentSetAngle; 42 | volatile float tickIncrement; 43 | 44 | public: 45 | void begin(StepperCtrl *ptrStepper); 46 | bool moveConstantVelocity(float finalAngle, float rpm); //moves to the final location at a constant RPM 47 | void tick(void); //this is called on regulat tick interval 48 | void stop(void); 49 | bool done(void) {return currentMode==PLANNER_NONE;} 50 | }; 51 | 52 | 53 | extern Planner SmartPlanner; 54 | 55 | 56 | #endif /* PLANNER_H_ */ 57 | -------------------------------------------------------------------------------- /firmware/stepServo/sine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * since.cpp 3 | * 4 | * Created on: Dec 24, 2016 5 | * Author: tstern 6 | * 7 | * Misfit Tech invests time and resources providing this open source code, 8 | * please support Misfit Tech and open-source hardware by purchasing 9 | * products from Misfit Tech, www.misifittech.net! 10 | * 11 | * Written by Trampas Stern for Misfit Tech. 12 | * BSD license, check license.txt for more information 13 | * All text above, must be included in any redistribution 14 | *********************************************************************/ 15 | 16 | #include "sine.h" 17 | 18 | #pragma GCC push_options 19 | #pragma GCC optimize ("-Ofast") 20 | 21 | #ifdef NZS_FAST_SINE 22 | static const int16_t sineTable[1280]={ 23 | 0,201,402,603,804,1005,1206,1407,1608,1808,2009,2210,2410,2611,2811,3011, 24 | 3212,3412,3611,3811,4011,4210,4410,4609,4808,5007,5205,5404,5602,5800,5998,6195, 25 | 6392,6589,6786,6983,7179,7375,7571,7766,7962,8156,8351,8545,8739,8933,9126,9319, 26 | 9512,9704,9896,10087,10278,10469,10659,10849,11039,11228,11417,11605,11793,11980,12167,12353, 27 | 12539,12725,12910,13094,13278,13462,13645,13828,14010,14191,14372,14553,14732,14912,15090,15269, 28 | 15446,15623,15800,15976,16151,16325,16499,16673,16846,17018,17189,17360,17530,17700,17869,18037, 29 | 18204,18371,18537,18703,18868,19032,19195,19357,19519,19680,19841,20000,20159,20317,20475,20631, 30 | 20787,20942,21097,21250,21403,21554,21705,21856,22005,22154,22301,22448,22594,22739,22884,23027, 31 | 23170,23312,23452,23592,23732,23870,24007,24143,24279,24413,24547,24680,24812,24942,25072,25201, 32 | 25329,25456,25583,25708,25832,25955,26077,26199,26319,26438,26556,26674,26790,26905,27019,27133, 33 | 27245,27356,27466,27575,27683,27791,27897,28001,28105,28208,28310,28411,28510,28609,28706,28803, 34 | 28898,28992,29085,29178,29268,29358,29447,29535,29621,29707,29791,29874,29956,30037,30117,30195, 35 | 30273,30349,30425,30499,30572,30643,30714,30783,30852,30919,30985,31050,31113,31176,31237,31297, 36 | 31356,31414,31471,31526,31580,31633,31685,31736,31785,31834,31881,31926,31971,32015,32057,32098, 37 | 32138,32176,32214,32250,32285,32319,32351,32382,32413,32441,32469,32496,32521,32545,32568,32589, 38 | 32609,32629,32646,32663,32678,32693,32706,32717,32728,32737,32745,32752,32757,32762,32765,32767, 39 | 32767,32767,32765,32762,32757,32752,32745,32737,32728,32717,32706,32693,32678,32663,32646,32629, 40 | 32609,32589,32568,32545,32521,32496,32469,32441,32413,32382,32351,32319,32285,32250,32214,32176, 41 | 32138,32098,32057,32015,31971,31926,31881,31834,31785,31736,31685,31633,31580,31526,31471,31414, 42 | 31356,31297,31237,31176,31113,31050,30985,30919,30852,30783,30714,30643,30572,30499,30425,30349, 43 | 30273,30195,30117,30037,29956,29874,29791,29707,29621,29535,29447,29358,29268,29178,29085,28992, 44 | 28898,28803,28706,28609,28510,28411,28310,28208,28105,28001,27897,27791,27683,27575,27466,27356, 45 | 27245,27133,27019,26905,26790,26674,26556,26438,26319,26199,26077,25955,25832,25708,25583,25456, 46 | 25329,25201,25072,24942,24812,24680,24547,24413,24279,24143,24007,23870,23732,23592,23452,23312, 47 | 23170,23027,22884,22739,22594,22448,22301,22154,22005,21856,21705,21554,21403,21250,21097,20942, 48 | 20787,20631,20475,20317,20159,20000,19841,19680,19519,19357,19195,19032,18868,18703,18537,18371, 49 | 18204,18037,17869,17700,17530,17360,17189,17018,16846,16673,16499,16325,16151,15976,15800,15623, 50 | 15446,15269,15090,14912,14732,14553,14372,14191,14010,13828,13645,13462,13278,13094,12910,12725, 51 | 12539,12353,12167,11980,11793,11605,11417,11228,11039,10849,10659,10469,10278,10087,9896,9704, 52 | 9512,9319,9126,8933,8739,8545,8351,8156,7962,7766,7571,7375,7179,6983,6786,6589, 53 | 6392,6195,5998,5800,5602,5404,5205,5007,4808,4609,4410,4210,4011,3811,3611,3412, 54 | 3212,3011,2811,2611,2410,2210,2009,1808,1608,1407,1206,1005,804,603,402,201, 55 | 0,-201,-402,-603,-804,-1005,-1206,-1407,-1608,-1809,-2010,-2210,-2411,-2611,-2812,-3012, 56 | -3212,-3412,-3612,-3812,-4011,-4211,-4410,-4609,-4808,-5007,-5206,-5404,-5602,-5800,-5998,-6196, 57 | -6393,-6590,-6787,-6983,-7180,-7376,-7571,-7767,-7962,-8157,-8352,-8546,-8740,-8933,-9127,-9320, 58 | -9512,-9704,-9896,-10088,-10279,-10470,-10660,-10850,-11039,-11228,-11417,-11605,-11793,-11980,-12167,-12354, 59 | -12540,-12725,-12910,-13095,-13279,-13463,-13646,-13828,-14010,-14192,-14373,-14553,-14733,-14912,-15091,-15269, 60 | -15447,-15624,-15800,-15976,-16151,-16326,-16500,-16673,-16846,-17018,-17190,-17361,-17531,-17700,-17869,-18037, 61 | -18205,-18372,-18538,-18703,-18868,-19032,-19195,-19358,-19520,-19681,-19841,-20001,-20160,-20318,-20475,-20632, 62 | -20788,-20943,-21097,-21250,-21403,-21555,-21706,-21856,-22006,-22154,-22302,-22449,-22595,-22740,-22884,-23028, 63 | -23170,-23312,-23453,-23593,-23732,-23870,-24007,-24144,-24279,-24414,-24548,-24680,-24812,-24943,-25073,-25202, 64 | -25330,-25457,-25583,-25708,-25832,-25956,-26078,-26199,-26319,-26439,-26557,-26674,-26790,-26906,-27020,-27133, 65 | -27245,-27357,-27467,-27576,-27684,-27791,-27897,-28002,-28106,-28209,-28310,-28411,-28511,-28609,-28707,-28803, 66 | -28899,-28993,-29086,-29178,-29269,-29359,-29448,-29535,-29622,-29707,-29791,-29875,-29957,-30038,-30117,-30196, 67 | -30273,-30350,-30425,-30499,-30572,-30644,-30715,-30784,-30852,-30919,-30985,-31050,-31114,-31176,-31238,-31298, 68 | -31357,-31415,-31471,-31527,-31581,-31634,-31686,-31736,-31786,-31834,-31881,-31927,-31972,-32015,-32057,-32098, 69 | -32138,-32177,-32214,-32250,-32285,-32319,-32352,-32383,-32413,-32442,-32470,-32496,-32521,-32545,-32568,-32590, 70 | -32610,-32629,-32647,-32664,-32679,-32693,-32706,-32718,-32728,-32738,-32746,-32752,-32758,-32762,-32765,-32767, 71 | -32768,-32767,-32765,-32762,-32758,-32752,-32746,-32738,-32728,-32718,-32706,-32693,-32679,-32664,-32647,-32629, 72 | -32610,-32590,-32568,-32545,-32521,-32496,-32470,-32442,-32413,-32383,-32352,-32319,-32285,-32250,-32214,-32177, 73 | -32138,-32098,-32057,-32015,-31972,-31927,-31881,-31834,-31786,-31736,-31686,-31634,-31581,-31527,-31471,-31415, 74 | -31357,-31298,-31238,-31176,-31114,-31050,-30985,-30919,-30852,-30784,-30715,-30644,-30572,-30499,-30425,-30350, 75 | -30273,-30196,-30117,-30038,-29957,-29875,-29791,-29707,-29622,-29535,-29448,-29359,-29269,-29178,-29086,-28993, 76 | -28899,-28803,-28707,-28609,-28511,-28411,-28310,-28209,-28106,-28002,-27897,-27791,-27684,-27576,-27467,-27357, 77 | -27245,-27133,-27020,-26906,-26790,-26674,-26557,-26439,-26319,-26199,-26078,-25956,-25832,-25708,-25583,-25457, 78 | -25330,-25202,-25073,-24943,-24812,-24680,-24548,-24414,-24279,-24144,-24007,-23870,-23732,-23593,-23453,-23312, 79 | -23170,-23028,-22884,-22740,-22595,-22449,-22302,-22154,-22006,-21856,-21706,-21555,-21403,-21250,-21097,-20943, 80 | -20788,-20632,-20475,-20318,-20160,-20001,-19841,-19681,-19520,-19358,-19195,-19032,-18868,-18703,-18538,-18372, 81 | -18205,-18037,-17869,-17700,-17531,-17361,-17190,-17018,-16846,-16673,-16500,-16326,-16151,-15976,-15800,-15624, 82 | -15447,-15269,-15091,-14912,-14733,-14553,-14373,-14192,-14010,-13828,-13646,-13463,-13279,-13095,-12910,-12725, 83 | -12540,-12354,-12167,-11980,-11793,-11605,-11417,-11228,-11039,-10850,-10660,-10470,-10279,-10088,-9896,-9704, 84 | -9512,-9320,-9127,-8933,-8740,-8546,-8352,-8157,-7962,-7767,-7571,-7376,-7180,-6983,-6787,-6590, 85 | -6393,-6196,-5998,-5800,-5602,-5404,-5206,-5007,-4808,-4609,-4410,-4211,-4011,-3812,-3612,-3412, 86 | -3212,-3012,-2812,-2611,-2411,-2210,-2010,-1809,-1608,-1407,-1206,-1005,-804,-603,-402,-201, 87 | 0,201,402,603,804,1005,1206,1407,1608,1808,2009,2210,2410,2611,2811,3011, 88 | 3212,3412,3611,3811,4011,4210,4410,4609,4808,5007,5205,5404,5602,5800,5998,6195, 89 | 6392,6589,6786,6983,7179,7375,7571,7766,7962,8156,8351,8545,8739,8933,9126,9319, 90 | 9512,9704,9896,10087,10278,10469,10659,10849,11039,11228,11417,11605,11793,11980,12167,12353, 91 | 12539,12725,12910,13094,13278,13462,13645,13828,14010,14191,14372,14553,14732,14912,15090,15269, 92 | 15446,15623,15800,15976,16151,16325,16499,16673,16846,17018,17189,17360,17530,17700,17869,18037, 93 | 18204,18371,18537,18703,18868,19032,19195,19357,19519,19680,19841,20000,20159,20317,20475,20631, 94 | 20787,20942,21097,21250,21403,21554,21705,21856,22005,22154,22301,22448,22594,22739,22884,23027, 95 | 23170,23312,23452,23592,23732,23870,24007,24143,24279,24413,24547,24680,24812,24942,25072,25201, 96 | 25329,25456,25583,25708,25832,25955,26077,26199,26319,26438,26556,26674,26790,26905,27019,27133, 97 | 27245,27356,27466,27575,27683,27791,27897,28001,28105,28208,28310,28411,28510,28609,28706,28803, 98 | 28898,28992,29085,29178,29268,29358,29447,29535,29621,29707,29791,29874,29956,30037,30117,30195, 99 | 30273,30349,30425,30499,30572,30643,30714,30783,30852,30919,30985,31050,31113,31176,31237,31297, 100 | 31356,31414,31471,31526,31580,31633,31685,31736,31785,31834,31881,31926,31971,32015,32057,32098, 101 | 32138,32176,32214,32250,32285,32319,32351,32382,32413,32441,32469,32496,32521,32545,32568,32589, 102 | 32609,32629,32646,32663,32678,32693,32706,32717,32728,32737,32745,32752,32757,32762,32765,32767 103 | }; 104 | #else 105 | static const uint16_t sineTable[257]={ 106 | 0,402,804,1206,1608,2010,2412,2814,3216,3617,4019,4420,4821,5222,5623,6023, 107 | 6424,6824,7223,7623,8022,8421,8820,9218,9616,10014,10411,10808,11204,11600,11996,12391, 108 | 12785,13179,13573,13966,14359,14751,15142,15533,15924,16313,16703,17091,17479,17866,18253,18639, 109 | 19024,19408,19792,20175,20557,20939,21319,21699,22078,22456,22834,23210,23586,23960,24334,24707, 110 | 25079,25450,25820,26189,26557,26925,27291,27656,28020,28383,28745,29106,29465,29824,30181,30538, 111 | 30893,31247,31600,31952,32302,32651,32999,33346,33692,34036,34379,34721,35061,35400,35738,36074, 112 | 36409,36743,37075,37406,37736,38064,38390,38715,39039,39361,39682,40001,40319,40635,40950,41263, 113 | 41575,41885,42194,42500,42806,43109,43411,43712,44011,44308,44603,44897,45189,45479,45768,46055, 114 | 46340,46624,46905,47185,47464,47740,48014,48287,48558,48827,49095,49360,49624,49885,50145,50403, 115 | 50659,50913,51166,51416,51664,51911,52155,52398,52638,52877,53113,53348,53580,53811,54039,54266, 116 | 54490,54713,54933,55151,55367,55582,55794,56003,56211,56417,56620,56822,57021,57218,57413,57606, 117 | 57797,57985,58171,58356,58537,58717,58895,59070,59243,59414,59582,59749,59913,60075,60234,60391, 118 | 60546,60699,60850,60998,61144,61287,61429,61567,61704,61838,61970,62100,62227,62352,62475,62595, 119 | 62713,62829,62942,63053,63161,63267,63371,63472,63571,63668,63762,63853,63943,64030,64114,64196, 120 | 64276,64353,64428,64500,64570,64638,64703,64765,64826,64883,64939,64992,65042,65090,65136,65179, 121 | 65219,65258,65293,65327,65357,65386,65412,65435,65456,65475,65491,65504,65515,65524,65530,65534, 122 | 65535, 123 | }; 124 | #endif 125 | 126 | 127 | 128 | 129 | int16_t sine(uint16_t angle) 130 | { 131 | #ifdef NZS_FAST_SINE 132 | return sineTable[angle]; 133 | #else 134 | int sign=1; 135 | int16_t ret; 136 | //our sine table has 1024 points per rotation so convert angle to closest step 137 | 138 | if (angle>=(SINE_STEPS/2)) 139 | { 140 | sign=-1; 141 | } 142 | 143 | angle=angle % (SINE_STEPS/2); //limit to 0-180 as sign takes care of 180-360 144 | 145 | if (angle>(SINE_STEPS/4-1)) //if we are greater than 90 we need to look up table backwards 146 | { 147 | angle=(SINE_STEPS/2)-angle; 148 | } 149 | 150 | ret=(int16_t)(sineTable[angle]/2)*sign; 151 | return ret; 152 | #endif 153 | } 154 | 155 | int16_t cosine(uint16_t angle) 156 | { 157 | #ifdef NZS_FAST_SINE 158 | angle=angle+(SINE_STEPS/4); 159 | return sineTable[angle]; 160 | #else 161 | 162 | int sign=1; 163 | int16_t ret; 164 | //our sine table has 1024 points per rotation so convert angle to closest step 165 | 166 | if (angle>=(SINE_STEPS/4) and angle<(3*(SINE_STEPS/4))) 167 | { 168 | sign=-1; 169 | } 170 | 171 | angle=angle % (SINE_STEPS/2); //limit to 0-180 as sign takes care of 180-360 172 | 173 | if (angle>(SINE_STEPS/4-1)) //if we are greater than 90 we need to look up table backwards 174 | { 175 | angle=(SINE_STEPS/2)-angle; 176 | } 177 | 178 | //for cosine we need 90 degree phase shift 179 | angle=(SINE_STEPS/4)-angle; 180 | 181 | ret=(int16_t)(sineTable[angle]/2)*sign; 182 | return ret; 183 | #endif 184 | } 185 | 186 | #pragma GCC pop_options 187 | -------------------------------------------------------------------------------- /firmware/stepServo/sine.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * sine.h 3 | * 4 | * Created on: Dec 24, 2016 5 | * Author: tstern 6 | * 7 | * Misfit Tech invests time and resources providing this open source code, 8 | * please support Misfit Tech and open-source hardware by purchasing 9 | * products from Misfit Tech, www.misifittech.net! 10 | * 11 | * Written by Trampas Stern for Misfit Tech. 12 | * BSD license, check license.txt for more information 13 | * All text above, must be included in any redistribution 14 | *********************************************************************/ 15 | 16 | 17 | #ifndef SINE_H_ 18 | #define SINE_H_ 19 | 20 | #include "board.h" 21 | 22 | #define SINE_STEPS (1024L) 23 | 24 | #define SINE_MAX ((int32_t)(32768L)) 25 | 26 | 27 | int16_t sine(uint16_t angle); 28 | int16_t cosine(uint16_t angle); 29 | 30 | 31 | #endif /* SINE_H_ */ 32 | -------------------------------------------------------------------------------- /firmware/stepServo/stepper_controller.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | #ifndef __STEPPER_CONTROLLER_H__ 13 | #define __STEPPER_CONTROLLER_H__ 14 | 15 | #include "syslog.h" 16 | #include "board.h" 17 | #include "as5047d.h" 18 | #include "calibration.h" 19 | #include "A4954.h" 20 | #include "A5995.h" 21 | #include "nonvolatile.h" 22 | #include "fet_driver.h" //for the NEMA23 10A 23 | 24 | 25 | #define N_DATA (1024) 26 | 27 | 28 | typedef enum { 29 | STEPCTRL_NO_ERROR=0, 30 | STEPCTRL_NO_POWER=1, //no power to motor 31 | STEPCTRL_NO_CAL=2, //calibration not set 32 | STEPCTRL_NO_ENCODER=3, //encoder not working 33 | } stepCtrlError_t; 34 | 35 | 36 | typedef struct { 37 | int32_t Kp; 38 | int32_t Ki; 39 | int32_t Kd; 40 | } PID_t; 41 | 42 | 43 | typedef __attribute__((packed, aligned(4))) struct { 44 | int32_t microSecs; 45 | int32_t desiredLoc; 46 | int32_t actualLoc; 47 | int32_t angle; 48 | int32_t ma; 49 | } Location_t; 50 | 51 | 52 | typedef struct { 53 | int32_t angle; 54 | int32_t ma; 55 | }Control_t; 56 | 57 | #define MAX_NUM_LOCATIONS (64) //maximum number of locations to buffer 58 | 59 | 60 | //this scales the PID parameters from Flash to floating point 61 | // to fixed point int32_t values 62 | #define CTRL_PID_SCALING (1024) 63 | 64 | class StepperCtrl 65 | { 66 | private: 67 | volatile bool enableFeedback; //true if we are using PID control algorithm 68 | AS5047D encoder; 69 | #ifdef NEMA_23_10A_HW 70 | FetDriver stepperDriver; 71 | #else 72 | #ifdef A5995_DRIVER 73 | A5995 stepperDriver; 74 | #else 75 | A4954 stepperDriver; 76 | #endif 77 | #endif 78 | uint16_t startUpEncoder; 79 | volatile int32_t ticks=0; 80 | volatile Location_t locs[MAX_NUM_LOCATIONS]; 81 | volatile int32_t locReadIndx=0; 82 | volatile int32_t locWriteIndx=0; 83 | 84 | volatile MotorParams_t motorParams; 85 | volatile SystemParams_t systemParams; 86 | volatile bool enabled; 87 | 88 | 89 | 90 | volatile int32_t loopTimeus; //time to run loop in microseconds 91 | 92 | volatile PID_t sPID; //simple control loop PID parameters 93 | volatile PID_t pPID; //positional current based PID control parameters 94 | volatile PID_t vPID; //velocity PID control parameters 95 | 96 | volatile int64_t numSteps; //this is the number of steps we have taken from our start angle 97 | 98 | volatile int32_t loopError; 99 | 100 | volatile int64_t currentLocation; //estimate of the current location from encoder feedback 101 | // the current location lower 16 bits is angle (0-360 degrees in 65536 steps) while upper 102 | // bits is the number of full rotations. 103 | 104 | //this is used for the velocity PID feedback 105 | // units are in Angles/sec where 1 Angle=360deg/65536 106 | volatile int64_t velocity; 107 | 108 | int64_t zeroAngleOffset=0; 109 | 110 | 111 | //volatile int16_t data[N_DATA]; 112 | 113 | //does linear interpolation of the encoder calibration table 114 | int32_t getAngleCalibration(int32_t encoderAngle); 115 | 116 | //updates the currentMeasuredAngle with our best guess where we are 117 | Angle sampleAngle(void); 118 | Angle sampleMeanEncoder(int32_t numSamples); 119 | 120 | float measureStepSize(void); //steps motor and estimates step size 121 | uint32_t measureMaxCalibrationError(void); 122 | void setLocationFromEncoder(void); 123 | 124 | void motorReset(void); 125 | void updateStep(int dir, uint16_t steps); 126 | 127 | 128 | bool pidFeedback(int64_t desiredLoc, int64_t currentLoc, Control_t *ptrCtrl); 129 | bool simpleFeedback(int64_t desiredLoc, int64_t currentLoc,Control_t *ptrCtrl); 130 | bool vpidFeedback(int64_t desiredLoc, int64_t currentLoc,Control_t *ptrCtrl); 131 | int64_t getCurrentLocation(void); 132 | int64_t getDesiredLocation(void); 133 | void updateLocTable(int64_t desiredLoc, int64_t currentLoc,Control_t *ptrCtrl); 134 | 135 | int64_t calculatePhasePrediction(int64_t currentLoc); 136 | 137 | public: 138 | uint16_t getStartupEncoder(void) {return startUpEncoder;} 139 | int32_t getLocation(Location_t *ptrLoc); 140 | 141 | Angle getEncoderAngle(void); 142 | 143 | void setAngle(int64_t loc); 144 | 145 | int64_t getZeroAngleOffset(void); 146 | void PrintData(void); 147 | void setVelocity(int64_t vel); //set velocity for vPID mode 148 | int64_t getVelocity(void); 149 | int32_t getLoopError(void) {return loopError;}; //assume atomic read 150 | 151 | bool calibrationValid(void) { return calTable.calValid();} //returns true if calbiration is good 152 | 153 | void updateParamsFromNVM(void); //updates the parameters from NVM 154 | CalibrationTable calTable; 155 | //void printData(void); 156 | 157 | bool calibrateEncoder(void); //do manual calibration of the encoder 158 | Angle maxCalibrationError(void); //measures the maximum calibration error as an angle 159 | 160 | void moveToAbsAngle(int32_t a); 161 | void moveToAngle(int32_t a, uint32_t ma); 162 | 163 | stepCtrlError_t begin(void); //returns false if we can not use motor 164 | 165 | bool processFeedback(void); // does the feedback loop 166 | 167 | feedbackCtrl_t getControlMode(void) { return systemParams.controllerMode;}; 168 | 169 | void requestStep(int dir, uint16_t steps); //requests a step, if feedback controller is off motor does not move 170 | 171 | void feedback(bool enable); 172 | bool getFeedback(void) {return enableFeedback;} 173 | 174 | void encoderDiagnostics(char *ptrStr); 175 | int32_t measureError(void); 176 | 177 | //these two functions are compenstated by the zero offset 178 | int64_t getCurrentAngle(void); 179 | int64_t getDesiredAngle(void); 180 | 181 | void move(int dir, uint16_t steps); //forces motor to move even if feedback controller is turned off. 182 | void enable(bool enable); 183 | bool getEnable(void) {return enabled;} 184 | 185 | int32_t getLoopTime(void) { return loopTimeus;} 186 | 187 | void PID_Autotune(void); 188 | void setZero(void); 189 | }; 190 | 191 | #endif //__STEPPER_CONTROLLER_H__ 192 | 193 | -------------------------------------------------------------------------------- /firmware/stepServo/stepper_nano_zero.ino: -------------------------------------------------------------------------------- 1 | #include "nzs.h" 2 | 3 | NZS nzs; 4 | 5 | 6 | void setup() { 7 | nzs.begin(); 8 | } 9 | 10 | 11 | void loop() { 12 | nzs.loop(); 13 | } 14 | -------------------------------------------------------------------------------- /firmware/stepServo/syslog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * syslog.c 3 | * 4 | * Created on: Sep 14, 2011 5 | * Author: trampas.stern 6 | * 7 | * Misfit Tech invests time and resources providing this open source code, 8 | * please support Misfit Tech and open-source hardware by purchasing 9 | * products from Misfit Tech, www.misifittech.net! 10 | * 11 | * Written by Trampas Stern for Misfit Tech. 12 | * BSD license, check license.txt for more information 13 | * All text above, must be included in any redistribution 14 | *********************************************************************/ 15 | #include "syslog.h" 16 | #include 17 | 18 | 19 | #define ANSI_WHITE "\033[37m" 20 | #define ANSI_NORMAL "\033[0m" 21 | #define ANSI_BLINK "\033[5m" 22 | #define ANSI_BLUE "\033[34m" 23 | #define ANSI_MAGENTA "\033[35m" 24 | #define ANSI_CYAN "\033[36m" 25 | #define ANSI_WHITE "\033[37m" 26 | #define ANSI_RED "\033[31m" 27 | #define ANSI_GREEN "\033[32m" 28 | #define ANSI_PINK "\033[35m\033[1m" 29 | #define ANSI_BROWN "\033[33m" 30 | #define ANSI_YELLOW "\033[33m\033[1m" 31 | #define ANSI_BLACK "\033[30m" 32 | #define ANSI_BELL_AND_RED "\a\033[31m" 33 | 34 | #define NEW_LINE "\n\r" 35 | 36 | Uart *ptrSerial=NULL; 37 | eLogLevel SyslogLevelToWrite; 38 | 39 | static char buffer[SYSLOG_BUFFER_SIZE]; 40 | static unsigned int BufIndex=0; 41 | 42 | static int SysLog_Enabled=1; 43 | 44 | int SysLogDisable(void) 45 | { 46 | SysLog_Enabled=0; 47 | return 0; 48 | } 49 | 50 | int SysLogEnable(void) 51 | { 52 | SysLog_Enabled=1; 53 | return 0; 54 | } 55 | 56 | int SysLogIsEnabled(void) 57 | { 58 | return SysLog_Enabled; 59 | } 60 | 61 | void SysLogPuts(const char *ptrStr) 62 | { 63 | if (!SysLog_Enabled) 64 | return; 65 | 66 | if (NULL == ptrSerial) 67 | { 68 | while(*ptrStr) 69 | { 70 | 71 | SYSLOG_PUTC(*ptrStr); 72 | ptrStr++; 73 | } 74 | } else 75 | { 76 | ptrSerial->write(ptrStr); 77 | } 78 | } 79 | 80 | int SysLogInitDone=0; 81 | void SysLogInit(Uart *ptrSerialObj, eLogLevel LevelToWrite) 82 | { 83 | ptrSerial=ptrSerialObj; 84 | SyslogLevelToWrite=LevelToWrite; 85 | 86 | SysLogInitDone=1; 87 | BufIndex=0; 88 | memset(buffer,0,SYSLOG_BUFFER_SIZE); 89 | } 90 | 91 | 92 | int SysLogProcessing=0; // this is used such that syslog can be reentrent 93 | int SysLogMissed=0; 94 | 95 | 96 | void SysLog(eLogLevel priorty, const char *fmt, ...) 97 | { 98 | //UINT32 ret; 99 | int previousState=SysLog_Enabled; 100 | char vastr[MAX_SYSLOG_STRING]={0}; 101 | //char outstr[MAX_SYSLOG_STRING]={0}; 102 | 103 | 104 | va_list ap; 105 | 106 | if (SysLogProcessing) 107 | { 108 | //we have a syslog from a syslog call thus return as not much we can do... 109 | //memset(buffer,0,SYSLOG_BUFFER_SIZE); 110 | va_start(ap,fmt); 111 | vsnprintf(&buffer[BufIndex],SYSLOG_BUFFER_SIZE-BufIndex,(char *)fmt,ap); 112 | BufIndex=strlen(buffer); 113 | snprintf(&buffer[BufIndex],SYSLOG_BUFFER_SIZE-BufIndex,NEW_LINE); 114 | BufIndex=strlen(buffer); 115 | SysLogMissed++; //set flag that we missed a call 116 | return; 117 | } 118 | 119 | SysLogProcessing=1; 120 | 121 | //stop the watch dog will doing a SysLog print 122 | Sys_WDogHoldOn(); 123 | 124 | if(!SysLogInitDone) 125 | { 126 | SysLogInit(NULL, LOG_WARNING); //not sure who is reseting serial port but before we print set it up 127 | WARNING("You should init SysLog"); 128 | //SysLogInitDone=0; 129 | } 130 | 131 | //Send out a * that we missed a SysLog Message before this current message 132 | if (SysLogMissed) 133 | { 134 | //SysLogPuts(ANSI_RED); 135 | SysLogPuts("*** Reentrant Log call possible loss of message(s):"); 136 | SysLogPuts(NEW_LINE); 137 | if (BufIndex>0) 138 | { 139 | SysLogPuts(buffer); 140 | memset(buffer,0,SYSLOG_BUFFER_SIZE); 141 | BufIndex=0; 142 | } 143 | //SysLogPuts(ANSI_RED); 144 | SysLogPuts("***********"); 145 | SysLogPuts(NEW_LINE); 146 | SysLogMissed=0; 147 | } 148 | memset(vastr,0,MAX_SYSLOG_STRING); 149 | va_start(ap,fmt); 150 | //#ifndef PGM_P 151 | #if 1 152 | vsnprintf(vastr,MAX_SYSLOG_STRING,(char *)fmt,ap); 153 | #else 154 | vsprintf_P(vastr,(const char *)fmt,ap); 155 | #endif 156 | //get time and store in datetimestr if desired 157 | //sprintf(outstr, "[%s] %s\r\n", datetimestr, vastr); 158 | 159 | 160 | 161 | if (priorty<=LOG_ERROR) 162 | { 163 | SysLog_Enabled=1; 164 | SysLogPuts(ANSI_RED); 165 | 166 | }else if (priorty==LOG_DEBUG) 167 | { 168 | SysLogPuts(ANSI_WHITE); 169 | }else if (priorty==LOG_WARNING) 170 | { 171 | SysLogPuts(ANSI_BLUE); 172 | } 173 | 174 | #ifdef RTC_H_ 175 | #ifdef TIME_H_ 176 | { 177 | struct tm tp; 178 | RTC_Time_s tm; 179 | time_t secs; 180 | char datetimestr[MAX_SYSLOG_STRING]={0}; 181 | 182 | RTC_ReadTime(&tm); 183 | secs=tm.seconds; 184 | convertFlexNetTime((time_t *)&secs, &tp); 185 | time_str(datetimestr,&tp); 186 | SysLogPuts(datetimestr); 187 | 188 | if (priorty<=SyslogLevelToWrite && SysLogWriteFunc!=NULL) 189 | { 190 | SysLogWriteFunc(datetimestr,strlen(datetimestr)); 191 | } 192 | } 193 | #endif 194 | #endif 195 | 196 | SysLogPuts(vastr); 197 | // 198 | // if (priorty<=SyslogLevelToWrite && SysLogWriteFunc!=NULL) 199 | // { 200 | // SysLogWriteFunc(vastr,strlen(vastr)); 201 | // SysLogWriteFunc(NEW_LINE,strlen(NEW_LINE)); 202 | // } 203 | 204 | 205 | SysLogPuts(ANSI_NORMAL); 206 | SysLogPuts(NEW_LINE); 207 | 208 | 209 | 210 | if (priorty == LOG_EMERG) { 211 | //you can reboot processor here 212 | } 213 | 214 | //start the watch dog where left off.. 215 | Sys_WDogHoldOff(); 216 | SysLogProcessing=0; 217 | SysLog_Enabled=previousState; 218 | return; 219 | } 220 | 221 | -------------------------------------------------------------------------------- /firmware/stepServo/syslog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * syslog.h 3 | * 4 | * Created on: Sep 14, 2011 5 | * Author: trampas.stern 6 | * 7 | * Misfit Tech invests time and resources providing this open source code, 8 | * please support Misfit Tech and open-source hardware by purchasing 9 | * products from Misfit Tech, www.misifittech.net! 10 | * 11 | * Written by Trampas Stern for Misfit Tech. 12 | * BSD license, check license.txt for more information 13 | * All text above, must be included in any redistribution 14 | *********************************************************************/ 15 | 16 | #ifndef SYSLOG_H_ 17 | #define SYSLOG_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include "Arduino.h" 23 | #include "variant.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" 27 | { 28 | #endif // __cplusplus 29 | 30 | #define SYSLOG_BUFFER_SIZE (250) 31 | 32 | #define MAX_SYSLOG_STRING (250) 33 | #define __FILENAME1__ (__builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__) 34 | #define __FILENAME__ (__builtin_strrchr(__FILENAME1__, '/') ? __builtin_strrchr(__FILENAME1__, '/') + 1 : __FILENAME1__) 35 | 36 | #define SYSLOG_WRITE(buffer,nBytes) 37 | 38 | #ifdef CMD_SERIAL_PORT 39 | #define SYSLOG_PUTC(x) 40 | #else 41 | #define SYSLOG_PUTC(x) //SerialUSB.write(x) 42 | #endif 43 | 44 | #define Sys_WDogHoldOn() 45 | #define Sys_WDogHoldOff() 46 | /* 47 | * priorities/facilities are encoded into a single 32-bit quantity, where the 48 | * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility 49 | * (0-big number). Both the priorities and the facilities map roughly 50 | * one-to-one to strings in the syslogd(8) source code. This mapping is 51 | * included in this file. 52 | * 53 | * priorities (these are ordered) 54 | */ 55 | 56 | typedef enum _eLogLevel { 57 | LOG_EMERG = 0, // system is unusable 58 | LOG_ALERT = 1, // action must be taken immediately 59 | LOG_CRIT = 2, // critical conditions 60 | LOG_ERROR = 3, // error conditions 61 | LOG_WARNING = 4, // warning conditions 62 | LOG_NOTICE = 5, // normal but significant condition 63 | LOG_INFO = 6, // informational 64 | LOG_DEBUG = 7, // debug-level messages 65 | LOG_DISABLED = 8 // disabled messages 66 | } eLogLevel; 67 | 68 | #if 0 69 | #define CONCAT(x, y) CONCAT_(x, y) 70 | #define CONCAT_(x, y) x##y 71 | 72 | #define ID(...) __VA_ARGS__ 73 | 74 | #define IFMULTIARG(if,then,else) \ 75 | CONCAT(IFMULTIARG_, IFMULTIARG_(if, \ 76 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 77 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 78 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 79 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 80 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 81 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 82 | 1, 1, 0, ))(then,else) 83 | #define IFMULTIARG_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, \ 84 | _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \ 85 | _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \ 86 | _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \ 87 | _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \ 88 | _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \ 89 | _60, _61, _62, _63, ...) _63 90 | #define IFMULTIARG_0(then, else) else 91 | #define IFMULTIARG_1(then, else) then 92 | 93 | #define PROVIDE_SECOND_ARGUMENT(x, ...) CONCAT( IFMULTIARG(ID(__VA_ARGS__), INSERT_, ADD_), SECOND_ARGUMENT ) (x, __VA_ARGS__) 94 | #define PROVIDE_SECOND_ARGUMENT2(x, y, ...) CONCAT( IFMULTIARG(ID(__VA_ARGS__), INSERT_, ADD_), SECOND_ARGUMENT2 ) (x, y, __VA_ARGS__) 95 | 96 | #define ADD_SECOND_ARGUMENT(x, y) y, x 97 | #define INSERT_SECOND_ARGUMENT(x, y, ...) y, x, __VA_ARGS__ 98 | 99 | #define ADD_SECOND_ARGUMENT2(x, z, y) y, x, z 100 | #define INSERT_SECOND_ARGUMENT2(x, z, y, ...) y, x, z, __VA_ARGS__ 101 | 102 | #endif 103 | //#define DEBUG1(...) printf( "DEBUG %s %s: " 104 | //PROVIDE_SECOND_ARGUMENT2(__FILE__, __LINE__, __VA_ARGS__)) 105 | 106 | 107 | //TXT(x) macro is used for system which can store strings in flash, like AVR processors 108 | #ifndef TXT 109 | #define TXT(x) x 110 | #endif 111 | 112 | void SysLog(eLogLevel priorty, const char *fmt, ...); 113 | 114 | 115 | 116 | static inline const char * __file__( const char *filename ) { 117 | char const *p = strrchr( filename, '/' ); 118 | if ( p ) 119 | return p+1; 120 | else 121 | return filename; 122 | } // __file__ 123 | 124 | 125 | //These macros abstract the logging and append the file and line number to errors. 126 | #ifndef SYSLOG_DISABLE 127 | //#ifndef PGM_P 128 | #if 1 129 | //EMERG means system is unstable thus will force a reboot! 130 | #define EMERG(fmt, ...) SysLog( LOG_EMERG, "EMERG: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) 131 | #define ALERT(fmt, ...) SysLog( LOG_ALERT, "ALERT: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) 132 | #define CRITICAL(fmt, ...) SysLog( LOG_CRIT, "CRITICAL: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) 133 | #define ERROR(fmt, ...) SysLog( LOG_ERROR, "ERROR: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) 134 | #define WARNING(fmt, ...) SysLog( LOG_WARNING, "WARNING: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) 135 | #define NOTICE(fmt, ...) SysLog( LOG_NOTICE, "NOTICE: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) 136 | #define INFO(fmt, ...) SysLog( LOG_INFO, "INFO: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) 137 | #define LOG(fmt, ...) SysLog( LOG_DEBUG, "%s %4d: " fmt, __FILENAME__ , __LINE__, ## __VA_ARGS__ ) 138 | // 139 | //#define EMERG(...) SysLog( LOG_EMERG, "EMERG: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) 140 | //#define ALERT(...) SysLog( LOG_ALERT, "ALERT: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) 141 | //#define CRITICAL(...) SysLog( LOG_CRIT, "CRITICAL: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) 142 | //#define ERROR(...) SysLog( LOG_ERROR, "ERROR: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) 143 | //#define WARNING(...) SysLog( LOG_WARNING, "WARNING: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) 144 | //#define NOTICE(...) SysLog( LOG_NOTICE, "NOTICE: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) 145 | //#define INFO(...) SysLog( LOG_INFO, "INFO: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) 146 | //#define LOG(...) SysLog( LOG_DEBUG, "%s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) 147 | #else 148 | //EMERG means system is unstable thus will force a reboot! 149 | #define EMERG(fmt, ...) SysLog( LOG_EMERG, PSTR("EMERG: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) 150 | #define ALERT(fmt, ...) SysLog( LOG_ALERT, PSTR("ALERT: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) 151 | #define CRITICAL(fmt, ...) SysLog( LOG_CRIT, PSTR("CRITICAL: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) 152 | #define ERROR(fmt, ...) SysLog( LOG_ERROR, PSTR("ERROR: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) 153 | #define WARNING(fmt, ...) SysLog( LOG_WARNING, PSTR("WARNING: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) 154 | #define NOTICE(fmt, ...) SysLog( LOG_NOTICE, PSTR("NOTICE: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) 155 | #define INFO(fmt, ...) SysLog( LOG_INFO, PSTR("INFO: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) 156 | #define LOG(fmt, ...) SysLog( LOG_DEBUG, PSTR("%15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) 157 | 158 | #endif 159 | #else 160 | #define EMERG(fmt, ...) 161 | #define ALERT(fmt, ...) 162 | #define CRITICAL(fmt, ...) 163 | #define ERROR(fmt, ...) 164 | #define WARNING(fmt, ...) 165 | #define NOTICE(fmt, ...) 166 | #define INFO(fmt, ...) 167 | #define LOG(fmt, ...) 168 | 169 | #endif //SYSLOG_DIABLE 170 | 171 | //Note that if you are running debug code with JTAG the assert will stop 172 | // However you might want to run release code with syslog enabled for testing 173 | // where you want error logging, but asserts are not enabled. 174 | // Thus this macro does error logging and an assert. 175 | //This macro assumed to take a constant string as argument 176 | 177 | 178 | //this can be enabled to log asserts to the history file, if you have code space to do it. 179 | #ifdef ASSERT_HISTORY 180 | #define ASSERT(x) {if(!(x)){ERROR(#x); HISTORY_ASSERT();} assert(x);} 181 | #define ASSERT_ERROR(x) {HISTORY_ASSERT(); ERROR(x); ASSERT_FAIL(x);} 182 | #else 183 | #define ASSERT(x) {if(!(x)){ERROR(#x);} assert(x);} 184 | #define ASSERT_ERROR(x) {ERROR(x); ASSERT_FAIL(x);} 185 | #endif 186 | 187 | 188 | void SysLogInit(Uart *ptrSerialObj, eLogLevel LevelToWrite); 189 | int SysLogDisable(void); 190 | int SysLogEnable(void); 191 | int SysLogIsEnabled(void); 192 | 193 | #ifdef __cplusplus 194 | } 195 | #endif // __cplusplus 196 | 197 | #endif /* SYSLOG_H_ */ 198 | -------------------------------------------------------------------------------- /firmware/stepServo/utils.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | 13 | #include "utils.h" 14 | #include "syslog.h" 15 | 16 | double CubicInterpolate( 17 | double y0,double y1, 18 | double y2,double y3, 19 | double mu) 20 | { 21 | double a0,a1,a2,a3,mu2; 22 | 23 | mu2 = mu*mu; 24 | a0 = y3 - y2 - y0 + y1; 25 | a1 = y0 - y1 - a0; 26 | a2 = y2 - y0; 27 | a3 = y1; 28 | 29 | return(a0*mu*mu2+a1*mu2+a2*mu+a3); 30 | } 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /firmware/stepServo/utils.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Author: tstern 3 | * 4 | * Misfit Tech invests time and resources providing this open source code, 5 | * please support Misfit Tech and open-source hardware by purchasing 6 | * products from Misfit Tech, www.misifittech.net! 7 | * 8 | * Written by Trampas Stern for Misfit Tech. 9 | * BSD license, check license.txt for more information 10 | * All text above, must be included in any redistribution 11 | *********************************************************************/ 12 | 13 | /* this file contains generic utilities and functions */ 14 | 15 | #ifndef UTILS_H_ 16 | #define UTILS_H_ 17 | 18 | 19 | double CubicInterpolate( 20 | double y0,double y1, 21 | double y2,double y3, 22 | double mu); 23 | 24 | 25 | 26 | 27 | #endif /* UTILS_H_ */ 28 | -------------------------------------------------------------------------------- /hardware/NZS_A4954_R2.0.PrjPcb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/hardware/NZS_A4954_R2.0.PrjPcb -------------------------------------------------------------------------------- /hardware/NZS_A4954_R2_0.PcbDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/hardware/NZS_A4954_R2_0.PcbDoc -------------------------------------------------------------------------------- /hardware/Nano_stepper.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/hardware/Nano_stepper.SchDoc -------------------------------------------------------------------------------- /hardware/Nano_zero_stepper_Schematics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/hardware/Nano_zero_stepper_Schematics.pdf -------------------------------------------------------------------------------- /hardware/Status Report.Txt: -------------------------------------------------------------------------------- 1 | Source PCB Design panel.PcbDoc contains embedded board array. It is recomended to generate individual BOM for each embedded board PCB design. 2 | 3 | Output: NC Drill Files 4 | Type : NC Drill 5 | From : Project [Free Documents] 6 | Generated File[panel-RoundHoles.TXT] 7 | Generated File[panel-SlotHoles.TXT] 8 | Generated File[panel.LDP] 9 | Generated File[panel.DRR] 10 | 11 | 12 | Files Generated : 4 13 | Documents Printed : 0 14 | 15 | Finished Output Generation At 7:25:51 AM On 10/11/2016 16 | -------------------------------------------------------------------------------- /hardware/panel-SlotHoles.TXT: -------------------------------------------------------------------------------- 1 | M48 2 | ;Layer_Color=9474304 3 | ;FILE_FORMAT=2:5 4 | INCH,LZ 5 | ;TYPE=PLATED 6 | T3F00S00C0.01968 7 | T4F00S00C0.02165 8 | ;TYPE=NON_PLATED 9 | % 10 | G90 11 | G05 12 | T03 13 | G00X0311728Y0181964 14 | M15 15 | G01X0314287 16 | M16 17 | G00X0311728Y0209524 18 | M15 19 | G01X0314287 20 | M16 21 | G00X0131728Y0209524 22 | M15 23 | G01X0134287 24 | M16 25 | G00X0131728Y0181964 26 | M15 27 | G01X0134287 28 | M16 29 | G00X0131728Y0361964 30 | M15 31 | G01X0134287 32 | M16 33 | G00X0131728Y0389524 34 | M15 35 | G01X0134287 36 | M16 37 | G00X0311728Y0389524 38 | M15 39 | G01X0314287 40 | M16 41 | G00X0311728Y0361964 42 | M15 43 | G01X0314287 44 | M16 45 | T04 46 | G00X0324031Y0186492 47 | M15 48 | G01Y0185311 49 | M16 50 | G00X0324031Y0206177 51 | M15 52 | G01Y0204996 53 | M16 54 | G00X0144031Y0206177 55 | M15 56 | G01Y0204996 57 | M16 58 | G00X0144031Y0186492 59 | M15 60 | G01Y0185311 61 | M16 62 | G00X0144031Y0366492 63 | M15 64 | G01Y0365311 65 | M16 66 | G00X0144031Y0386177 67 | M15 68 | G01Y0384996 69 | M16 70 | G00X0324031Y0386177 71 | M15 72 | G01Y0384996 73 | M16 74 | G00X0324031Y0366492 75 | M15 76 | G01Y0365311 77 | M16 78 | M17 79 | M30 80 | -------------------------------------------------------------------------------- /hardware/panel-macro.APR_LIB: -------------------------------------------------------------------------------- 1 | G04:AMPARAMS|DCode=11|XSize=31.5mil|YSize=35.43mil|CornerRadius=7.87mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=270.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 2 | %AMROUNDEDRECTD11* 3 | 21,1,0.03150,0.01969,0,0,270.0* 4 | 21,1,0.01575,0.03543,0,0,270.0* 5 | 1,1,0.01575,-0.00984,-0.00787* 6 | 1,1,0.01575,-0.00984,0.00787* 7 | 1,1,0.01575,0.00984,0.00787* 8 | 1,1,0.01575,0.00984,-0.00787* 9 | % 10 | G04:AMPARAMS|DCode=18|XSize=31.5mil|YSize=31.5mil|CornerRadius=7.87mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=90.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 11 | %AMROUNDEDRECTD18* 12 | 21,1,0.03150,0.01575,0,0,90.0* 13 | 21,1,0.01575,0.03150,0,0,90.0* 14 | 1,1,0.01575,0.00787,0.00787* 15 | 1,1,0.01575,0.00787,-0.00787* 16 | 1,1,0.01575,-0.00787,-0.00787* 17 | 1,1,0.01575,-0.00787,0.00787* 18 | % 19 | G04:AMPARAMS|DCode=20|XSize=27.56mil|YSize=51.18mil|CornerRadius=6.89mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=90.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 20 | %AMROUNDEDRECTD20* 21 | 21,1,0.02756,0.03740,0,0,90.0* 22 | 21,1,0.01378,0.05118,0,0,90.0* 23 | 1,1,0.01378,0.01870,0.00689* 24 | 1,1,0.01378,0.01870,-0.00689* 25 | 1,1,0.01378,-0.01870,-0.00689* 26 | 1,1,0.01378,-0.01870,0.00689* 27 | % 28 | G04:AMPARAMS|DCode=22|XSize=23.62mil|YSize=35.43mil|CornerRadius=5.91mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=270.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 29 | %AMROUNDEDRECTD22* 30 | 21,1,0.02362,0.02362,0,0,270.0* 31 | 21,1,0.01181,0.03543,0,0,270.0* 32 | 1,1,0.01181,-0.01181,-0.00591* 33 | 1,1,0.01181,-0.01181,0.00591* 34 | 1,1,0.01181,0.01181,0.00591* 35 | 1,1,0.01181,0.01181,-0.00591* 36 | % 37 | G04:AMPARAMS|DCode=25|XSize=78.74mil|YSize=39.37mil|CornerRadius=9.84mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=0.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 38 | %AMROUNDEDRECTD25* 39 | 21,1,0.07874,0.01969,0,0,0.0* 40 | 21,1,0.05906,0.03937,0,0,0.0* 41 | 1,1,0.01969,0.02953,-0.00984* 42 | 1,1,0.01969,-0.02953,-0.00984* 43 | 1,1,0.01969,-0.02953,0.00984* 44 | 1,1,0.01969,0.02953,0.00984* 45 | % 46 | G04:AMPARAMS|DCode=27|XSize=9.84mil|YSize=33.47mil|CornerRadius=0mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=135.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=Round|* 47 | %AMOVALD27* 48 | 21,1,0.02362,0.00984,0.00000,0.00000,225.0* 49 | 1,1,0.00984,0.00835,0.00835* 50 | 1,1,0.00984,-0.00835,-0.00835* 51 | % 52 | G04:AMPARAMS|DCode=28|XSize=9.84mil|YSize=35.43mil|CornerRadius=0mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=135.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=Round|* 53 | %AMOVALD28* 54 | 21,1,0.02559,0.00984,0.00000,0.00000,225.0* 55 | 1,1,0.00984,0.00905,0.00905* 56 | 1,1,0.00984,-0.00905,-0.00905* 57 | % 58 | G04:AMPARAMS|DCode=29|XSize=9.84mil|YSize=33.47mil|CornerRadius=0mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=225.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=Round|* 59 | %AMOVALD29* 60 | 21,1,0.02362,0.00984,0.00000,0.00000,315.0* 61 | 1,1,0.00984,-0.00835,0.00835* 62 | 1,1,0.00984,0.00835,-0.00835* 63 | % 64 | G04:AMPARAMS|DCode=30|XSize=9.84mil|YSize=35.43mil|CornerRadius=0mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=225.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=Round|* 65 | %AMOVALD30* 66 | 21,1,0.02559,0.00984,0.00000,0.00000,315.0* 67 | 1,1,0.00984,-0.00905,0.00905* 68 | 1,1,0.00984,0.00905,-0.00905* 69 | % 70 | G04:AMPARAMS|DCode=31|XSize=9.84mil|YSize=33.47mil|CornerRadius=2.46mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=225.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 71 | %AMROUNDEDRECTD31* 72 | 21,1,0.00984,0.02854,0,0,225.0* 73 | 21,1,0.00492,0.03347,0,0,225.0* 74 | 1,1,0.00492,-0.01183,0.00835* 75 | 1,1,0.00492,-0.00835,0.01183* 76 | 1,1,0.00492,0.01183,-0.00835* 77 | 1,1,0.00492,0.00835,-0.01183* 78 | % 79 | G04:AMPARAMS|DCode=63|XSize=23.62mil|YSize=62.99mil|CornerRadius=5.91mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=0.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 80 | %AMROUNDEDRECTD63* 81 | 21,1,0.02362,0.05118,0,0,0.0* 82 | 21,1,0.01181,0.06299,0,0,0.0* 83 | 1,1,0.01181,0.00591,-0.02559* 84 | 1,1,0.01181,-0.00591,-0.02559* 85 | 1,1,0.01181,-0.00591,0.02559* 86 | 1,1,0.01181,0.00591,0.02559* 87 | % 88 | G04:AMPARAMS|DCode=72|XSize=39.5mil|YSize=43.43mil|CornerRadius=11.87mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=270.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 89 | %AMROUNDEDRECTD72* 90 | 21,1,0.03950,0.01969,0,0,270.0* 91 | 21,1,0.01575,0.04343,0,0,270.0* 92 | 1,1,0.02375,-0.00984,-0.00787* 93 | 1,1,0.02375,-0.00984,0.00787* 94 | 1,1,0.02375,0.00984,0.00787* 95 | 1,1,0.02375,0.00984,-0.00787* 96 | % 97 | G04:AMPARAMS|DCode=79|XSize=39.5mil|YSize=39.5mil|CornerRadius=11.87mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=90.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 98 | %AMROUNDEDRECTD79* 99 | 21,1,0.03950,0.01575,0,0,90.0* 100 | 21,1,0.01575,0.03950,0,0,90.0* 101 | 1,1,0.02375,0.00787,0.00787* 102 | 1,1,0.02375,0.00787,-0.00787* 103 | 1,1,0.02375,-0.00787,-0.00787* 104 | 1,1,0.02375,-0.00787,0.00787* 105 | % 106 | G04:AMPARAMS|DCode=81|XSize=35.56mil|YSize=59.18mil|CornerRadius=10.89mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=90.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 107 | %AMROUNDEDRECTD81* 108 | 21,1,0.03556,0.03740,0,0,90.0* 109 | 21,1,0.01378,0.05918,0,0,90.0* 110 | 1,1,0.02178,0.01870,0.00689* 111 | 1,1,0.02178,0.01870,-0.00689* 112 | 1,1,0.02178,-0.01870,-0.00689* 113 | 1,1,0.02178,-0.01870,0.00689* 114 | % 115 | G04:AMPARAMS|DCode=83|XSize=31.62mil|YSize=43.43mil|CornerRadius=9.91mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=270.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 116 | %AMROUNDEDRECTD83* 117 | 21,1,0.03162,0.02362,0,0,270.0* 118 | 21,1,0.01181,0.04343,0,0,270.0* 119 | 1,1,0.01981,-0.01181,-0.00591* 120 | 1,1,0.01981,-0.01181,0.00591* 121 | 1,1,0.01981,0.01181,0.00591* 122 | 1,1,0.01981,0.01181,-0.00591* 123 | % 124 | G04:AMPARAMS|DCode=86|XSize=86.74mil|YSize=47.37mil|CornerRadius=13.84mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=0.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 125 | %AMROUNDEDRECTD86* 126 | 21,1,0.08674,0.01969,0,0,0.0* 127 | 21,1,0.05906,0.04737,0,0,0.0* 128 | 1,1,0.02769,0.02953,-0.00984* 129 | 1,1,0.02769,-0.02953,-0.00984* 130 | 1,1,0.02769,-0.02953,0.00984* 131 | 1,1,0.02769,0.02953,0.00984* 132 | % 133 | G04:AMPARAMS|DCode=88|XSize=17.84mil|YSize=41.47mil|CornerRadius=0mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=135.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=Round|* 134 | %AMOVALD88* 135 | 21,1,0.02362,0.01784,0.00000,0.00000,225.0* 136 | 1,1,0.01784,0.00835,0.00835* 137 | 1,1,0.01784,-0.00835,-0.00835* 138 | % 139 | G04:AMPARAMS|DCode=89|XSize=17.84mil|YSize=43.43mil|CornerRadius=0mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=135.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=Round|* 140 | %AMOVALD89* 141 | 21,1,0.02559,0.01784,0.00000,0.00000,225.0* 142 | 1,1,0.01784,0.00905,0.00905* 143 | 1,1,0.01784,-0.00905,-0.00905* 144 | % 145 | G04:AMPARAMS|DCode=90|XSize=17.84mil|YSize=41.47mil|CornerRadius=0mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=225.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=Round|* 146 | %AMOVALD90* 147 | 21,1,0.02362,0.01784,0.00000,0.00000,315.0* 148 | 1,1,0.01784,-0.00835,0.00835* 149 | 1,1,0.01784,0.00835,-0.00835* 150 | % 151 | G04:AMPARAMS|DCode=91|XSize=17.84mil|YSize=43.43mil|CornerRadius=0mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=225.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=Round|* 152 | %AMOVALD91* 153 | 21,1,0.02559,0.01784,0.00000,0.00000,315.0* 154 | 1,1,0.01784,-0.00905,0.00905* 155 | 1,1,0.01784,0.00905,-0.00905* 156 | % 157 | G04:AMPARAMS|DCode=92|XSize=17.84mil|YSize=41.47mil|CornerRadius=6.46mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=225.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 158 | %AMROUNDEDRECTD92* 159 | 21,1,0.01784,0.02854,0,0,225.0* 160 | 21,1,0.00492,0.04147,0,0,225.0* 161 | 1,1,0.01292,-0.01183,0.00835* 162 | 1,1,0.01292,-0.00835,0.01183* 163 | 1,1,0.01292,0.01183,-0.00835* 164 | 1,1,0.01292,0.00835,-0.01183* 165 | % 166 | G04:AMPARAMS|DCode=112|XSize=31.62mil|YSize=70.99mil|CornerRadius=9.91mil|HoleSize=0mil|Usage=FLASHONLY|Rotation=0.000|XOffset=0mil|YOffset=0mil|HoleType=Round|Shape=RoundedRectangle|* 167 | %AMROUNDEDRECTD112* 168 | 21,1,0.03162,0.05118,0,0,0.0* 169 | 21,1,0.01181,0.07099,0,0,0.0* 170 | 1,1,0.01981,0.00591,-0.02559* 171 | 1,1,0.01981,-0.00591,-0.02559* 172 | 1,1,0.01981,-0.00591,0.02559* 173 | 1,1,0.01981,0.00591,0.02559* 174 | % 175 | -------------------------------------------------------------------------------- /hardware/panel.1: -------------------------------------------------------------------------------- 1 | G04 Layer_Color=255* 2 | %FSLAX25Y25*% 3 | %MOIN*% 4 | G70* 5 | G01* 6 | G75* 7 | M02* 8 | -------------------------------------------------------------------------------- /hardware/panel.DRR: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------------------------------------- 2 | NCDrill File Report For: panel.PcbDoc 10/11/2016 7:25:51 AM 3 | ---------------------------------------------------------------------------------------------------------------------------------- 4 | 5 | Layer Pair : Top Layer to Bottom Layer 6 | ASCII RoundHoles File : panel-RoundHoles.TXT 7 | ASCII SlotHoles File : panel-SlotHoles.TXT 8 | 9 | Tool Hole Size Hole Tolerance Hole Type Hole Count Plated Tool Travel 10 | ---------------------------------------------------------------------------------------------------------------------------------- 11 | T1 8mil (0.2mm) Round 36 PTH 6.70inch (170.16mm) 12 | T2 12mil (0.305mm) Round 492 PTH 63.35inch (1609.14mm) 13 | T3 20mil (0.5mm) Slot 8 PTH 13.21inch (335.65mm) 14 | T4 22mil (0.55mm) Slot 8 PTH 12.48inch (317.02mm) 15 | T5 27mil (0.686mm) Round 40 PTH 7.00inch (177.80mm) 16 | T6 40mil (1.016mm) Round 32 PTH 9.08inch (230.70mm) 17 | T7 43mil (1.1mm) Round 40 PTH 9.00inch (228.60mm) 18 | T8 51mil (1.3mm) Round 8 PTH 6.00inch (152.40mm) 19 | T9 138mil (3.5mm) Round 16 PTH 15.74inch (399.88mm) 20 | T10 31mil (0.787mm) Round 192 NPTH 28.19inch (715.91mm) 21 | ---------------------------------------------------------------------------------------------------------------------------------- 22 | Totals 872 23 | 24 | Total Processing Time (hh:mm:ss) : 00:00:00 25 | -------------------------------------------------------------------------------- /hardware/panel.EXTREP: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------------------ 2 | Gerber File Extension Report For: panel.GBR 10/11/2016 7:23:43 AM 3 | ------------------------------------------------------------------------------------------ 4 | 5 | 6 | ------------------------------------------------------------------------------------------ 7 | Layer Extension Layer Description 8 | ------------------------------------------------------------------------------------------ 9 | .GTL Top Layer 10 | .GBL Bottom Layer 11 | .GPB Bottom Pad Master 12 | .GPT Top Pad Master 13 | .GTO Top Overlay 14 | .GTP Top Paste 15 | .GTS Top Solder 16 | .GBS Bottom Solder 17 | .GBP Bottom Paste 18 | .GBO Bottom Overlay 19 | .GKO Keep-Out Layer 20 | .GM1 Mechanical 1 21 | .GM3 Mechanical 3 22 | .GM2 Mechanical 2 23 | .GM13 Mechanical 13 24 | .GM15 Mechanical 15 25 | .1 Dielectric 1 26 | .GML Multi-Layer 27 | .GD1 Drill Drawing 28 | ------------------------------------------------------------------------------------------ 29 | -------------------------------------------------------------------------------- /hardware/panel.GM1: -------------------------------------------------------------------------------- 1 | G04 Layer_Color=16711935* 2 | %FSLAX25Y25*% 3 | %MOIN*% 4 | G70* 5 | G01* 6 | G75* 7 | M02* 8 | -------------------------------------------------------------------------------- /hardware/panel.GM2: -------------------------------------------------------------------------------- 1 | G04 Layer_Color=8388736* 2 | %FSLAX25Y25*% 3 | %MOIN*% 4 | G70* 5 | G01* 6 | G75* 7 | %ADD68C,0.00500*% 8 | D68* 9 | X134044Y222344D02* 10 | G03* 11 | X134044Y222344I-2000J0D01* 12 | G01* 13 | Y232344D02* 14 | G03* 15 | X134044Y232344I-2000J0D01* 16 | G01* 17 | Y242344D02* 18 | G03* 19 | X134044Y242344I-2000J0D01* 20 | G01* 21 | Y252344D02* 22 | G03* 23 | X134044Y252344I-2000J0D01* 24 | G01* 25 | X237244Y252744D02* 26 | G03* 27 | X237244Y252744I-2000J0D01* 28 | G01* 29 | X227244D02* 30 | G03* 31 | X227244Y252744I-2000J0D01* 32 | G01* 33 | X217244D02* 34 | G03* 35 | X217244Y252744I-2000J0D01* 36 | G01* 37 | X207244D02* 38 | G03* 39 | X207244Y252744I-2000J0D01* 40 | G01* 41 | X314044Y222344D02* 42 | G03* 43 | X314044Y222344I-2000J0D01* 44 | G01* 45 | Y232344D02* 46 | G03* 47 | X314044Y232344I-2000J0D01* 48 | G01* 49 | Y242344D02* 50 | G03* 51 | X314044Y242344I-2000J0D01* 52 | G01* 53 | Y252344D02* 54 | G03* 55 | X314044Y252344I-2000J0D01* 56 | G01* 57 | X417244Y252744D02* 58 | G03* 59 | X417244Y252744I-2000J0D01* 60 | G01* 61 | X407244D02* 62 | G03* 63 | X407244Y252744I-2000J0D01* 64 | G01* 65 | X397244D02* 66 | G03* 67 | X397244Y252744I-2000J0D01* 68 | G01* 69 | X387244D02* 70 | G03* 71 | X387244Y252744I-2000J0D01* 72 | G01* 73 | X134044Y402344D02* 74 | G03* 75 | X134044Y402344I-2000J0D01* 76 | G01* 77 | Y412344D02* 78 | G03* 79 | X134044Y412344I-2000J0D01* 80 | G01* 81 | Y422344D02* 82 | G03* 83 | X134044Y422344I-2000J0D01* 84 | G01* 85 | Y432344D02* 86 | G03* 87 | X134044Y432344I-2000J0D01* 88 | G01* 89 | X237244Y432744D02* 90 | G03* 91 | X237244Y432744I-2000J0D01* 92 | G01* 93 | X227244D02* 94 | G03* 95 | X227244Y432744I-2000J0D01* 96 | G01* 97 | X217244D02* 98 | G03* 99 | X217244Y432744I-2000J0D01* 100 | G01* 101 | X207244D02* 102 | G03* 103 | X207244Y432744I-2000J0D01* 104 | G01* 105 | X314044Y402344D02* 106 | G03* 107 | X314044Y402344I-2000J0D01* 108 | G01* 109 | Y412344D02* 110 | G03* 111 | X314044Y412344I-2000J0D01* 112 | G01* 113 | Y422344D02* 114 | G03* 115 | X314044Y422344I-2000J0D01* 116 | G01* 117 | Y432344D02* 118 | G03* 119 | X314044Y432344I-2000J0D01* 120 | G01* 121 | X417244Y432744D02* 122 | G03* 123 | X417244Y432744I-2000J0D01* 124 | G01* 125 | X407244D02* 126 | G03* 127 | X407244Y432744I-2000J0D01* 128 | G01* 129 | X397244D02* 130 | G03* 131 | X397244Y432744I-2000J0D01* 132 | G01* 133 | X387244D02* 134 | G03* 135 | X387244Y432744I-2000J0D01* 136 | G01* 137 | M02* 138 | -------------------------------------------------------------------------------- /hardware/panel.GM3: -------------------------------------------------------------------------------- 1 | G04 Layer_Color=12566272* 2 | %FSLAX25Y25*% 3 | %MOIN*% 4 | G70* 5 | G01* 6 | G75* 7 | %ADD40C,0.02000*% 8 | %ADD117C,0.04724*% 9 | D40* 10 | X160800Y531193D02* 11 | Y511200D01* 12 | X170797D01* 13 | X174129Y514532D01* 14 | Y517865D01* 15 | X170797Y521197D01* 16 | X160800D01* 17 | X170797D01* 18 | X174129Y524529D01* 19 | Y527861D01* 20 | X170797Y531193D01* 21 | X160800D01* 22 | X184126Y511200D02* 23 | X190790D01* 24 | X194123Y514532D01* 25 | Y521197D01* 26 | X190790Y524529D01* 27 | X184126D01* 28 | X180793Y521197D01* 29 | Y514532D01* 30 | X184126Y511200D01* 31 | X204119Y524529D02* 32 | X210784D01* 33 | X214116Y521197D01* 34 | Y511200D01* 35 | X204119D01* 36 | X200787Y514532D01* 37 | X204119Y517865D01* 38 | X214116D01* 39 | X220781Y524529D02* 40 | Y511200D01* 41 | Y517865D01* 42 | X224113Y521197D01* 43 | X227445Y524529D01* 44 | X230777D01* 45 | X254103Y531193D02* 46 | Y511200D01* 47 | X244106D01* 48 | X240774Y514532D01* 49 | Y521197D01* 50 | X244106Y524529D01* 51 | X254103D01* 52 | X290758Y531193D02* 53 | X284093D01* 54 | X280761Y527861D01* 55 | Y514532D01* 56 | X284093Y511200D01* 57 | X290758D01* 58 | X294090Y514532D01* 59 | Y527861D01* 60 | X290758Y531193D01* 61 | X300755Y524529D02* 62 | Y514532D01* 63 | X304087Y511200D01* 64 | X314084D01* 65 | Y524529D01* 66 | X324081Y527861D02* 67 | Y524529D01* 68 | X320748D01* 69 | X327413D01* 70 | X324081D01* 71 | Y514532D01* 72 | X327413Y511200D01* 73 | X337410D02* 74 | X344074D01* 75 | X340742D01* 76 | Y531193D01* 77 | X337410D01* 78 | X354071Y511200D02* 79 | X360735D01* 80 | X357403D01* 81 | Y524529D01* 82 | X354071D01* 83 | X370732Y511200D02* 84 | Y524529D01* 85 | X380729D01* 86 | X384061Y521197D01* 87 | Y511200D01* 88 | X400723D02* 89 | X394058D01* 90 | X390726Y514532D01* 91 | Y521197D01* 92 | X394058Y524529D01* 93 | X400723D01* 94 | X404055Y521197D01* 95 | Y517865D01* 96 | X390726D01* 97 | D117* 98 | X357900Y124200D02* 99 | X358000Y113200D01* 100 | X358600Y112600D01* 101 | X418000D01* 102 | Y124200D01* 103 | X357900D02* 104 | X418000D01* 105 | X361600Y290100D02* 106 | X361900Y304300D01* 107 | X361600Y290100D02* 108 | X405600D01* 109 | X405900Y289800D01* 110 | X406000Y289900D01* 111 | Y304500D01* 112 | X362100D02* 113 | X406000D01* 114 | X361900Y304300D02* 115 | X362100Y304500D01* 116 | X182100Y112800D02* 117 | Y124400D01* 118 | Y112800D02* 119 | X182800Y112100D01* 120 | X235400D01* 121 | Y123800D01* 122 | X234800Y124400D02* 123 | X235400Y123800D01* 124 | X182100Y124400D02* 125 | X234800D01* 126 | X114600Y407900D02* 127 | X125400Y407800D01* 128 | X114600Y407900D02* 129 | X114700Y407800D01* 130 | Y357300D02* 131 | Y407800D01* 132 | Y357300D02* 133 | X124600D01* 134 | X125400Y358100D01* 135 | Y407800D01* 136 | X115000Y240000D02* 137 | X125400D01* 138 | X115000Y180000D02* 139 | Y240000D01* 140 | Y180000D02* 141 | X125400D01* 142 | Y240000D01* 143 | X291000Y177000D02* 144 | Y228000D01* 145 | Y177000D02* 146 | X305000D01* 147 | Y228000D01* 148 | X291000D02* 149 | X305000D01* 150 | X177100Y304500D02* 151 | X235100D01* 152 | Y290000D02* 153 | Y304500D01* 154 | X177100Y290000D02* 155 | X235100D01* 156 | X177100D02* 157 | Y304500D01* 158 | X291000Y134000D02* 159 | Y150000D01* 160 | X281500Y124500D02* 161 | X291000Y134000D01* 162 | X263000Y124500D02* 163 | X281500D01* 164 | X262500Y125000D02* 165 | X263000Y124500D01* 166 | X262500Y112500D02* 167 | Y125000D01* 168 | Y112500D02* 169 | X332500D01* 170 | X333000Y113000D01* 171 | Y124000D01* 172 | X315500D02* 173 | X333000D01* 174 | X305500Y134000D02* 175 | X315500Y124000D01* 176 | X305500Y134000D02* 177 | Y150000D01* 178 | X291000D02* 179 | X305500D01* 180 | X125000Y133000D02* 181 | Y152500D01* 182 | Y133000D02* 183 | X125500D01* 184 | X134500Y124000D01* 185 | X135000Y124500D01* 186 | X154500D01* 187 | Y112000D02* 188 | Y124500D01* 189 | X154000Y112500D02* 190 | X154500Y112000D01* 191 | X115000Y112500D02* 192 | X154000D01* 193 | X115000D02* 194 | Y152000D01* 195 | X114500Y152500D02* 196 | X115000Y152000D01* 197 | X114500Y152500D02* 198 | X125000D01* 199 | X114550Y330100D02* 200 | X114987Y265000D01* 201 | X125500Y265000D01* 202 | X125500Y280500D01* 203 | X135000Y290000D01* 204 | X149500D01* 205 | Y304500D01* 206 | X134500D02* 207 | X149500D01* 208 | X125500Y313500D02* 209 | X134500Y304500D01* 210 | X125500Y313500D02* 211 | Y330100D01* 212 | X114550D02* 213 | X125500D01* 214 | X290281Y401131D02* 215 | X290900Y402700D01* 216 | X290281Y401131D02* 217 | X291107Y364800D01* 218 | X305500D01* 219 | Y402700D01* 220 | X290900D02* 221 | X305500D01* 222 | X290500Y314000D02* 223 | Y337500D01* 224 | X281000Y304500D02* 225 | X290500Y314000D01* 226 | X262000Y304500D02* 227 | X281000D01* 228 | X262000Y290000D02* 229 | Y304500D01* 230 | Y290000D02* 231 | X281000D01* 232 | X291000Y280000D01* 233 | Y255500D02* 234 | Y280000D01* 235 | Y255500D02* 236 | X304500D01* 237 | X305000Y255000D01* 238 | Y280500D01* 239 | X315000Y290500D01* 240 | X334500D01* 241 | Y304500D01* 242 | X314500D02* 243 | X334500D01* 244 | X314500D02* 245 | Y305000D01* 246 | X305500Y314000D02* 247 | X314500Y305000D01* 248 | X305500Y314000D02* 249 | Y337500D01* 250 | X290500D02* 251 | X305500D01* 252 | X471000Y134000D02* 253 | Y152500D01* 254 | X461500Y124500D02* 255 | X471000Y134000D01* 256 | X444600Y124500D02* 257 | X461500D01* 258 | X444600Y112500D02* 259 | Y124500D01* 260 | Y112500D02* 261 | X480000D01* 262 | X482500Y115000D01* 263 | Y152500D01* 264 | X471000D02* 265 | X482500D01* 266 | X470500Y177500D02* 267 | Y215000D01* 268 | Y177500D02* 269 | X482500D01* 270 | Y215000D01* 271 | X470500D02* 272 | X482500D01* 273 | X471000Y338100D02* 274 | X482500D01* 275 | Y242300D02* 276 | Y338100D01* 277 | X471000Y242300D02* 278 | X482500D01* 279 | X471000D02* 280 | Y280000D01* 281 | X470000D02* 282 | X471000D01* 283 | X459500Y290500D02* 284 | X470000Y280000D01* 285 | X432500Y290500D02* 286 | X459500D01* 287 | X432500D02* 288 | Y304000D01* 289 | X432000Y304500D02* 290 | X432500Y304000D01* 291 | X432000Y304500D02* 292 | X461000D01* 293 | X471000Y314500D01* 294 | Y338100D01* 295 | X471000Y400400D02* 296 | X471000Y365000D01* 297 | X482500D01* 298 | X480000D02* 299 | X482500D01* 300 | X480000D02* 301 | Y367500D01* 302 | X480000Y400400D02* 303 | X480000Y367500D01* 304 | X471000Y400400D02* 305 | X480000D01* 306 | X435000Y470000D02* 307 | Y480000D01* 308 | X480000D01* 309 | Y428000D02* 310 | Y480000D01* 311 | Y428000D02* 312 | X480500Y427500D01* 313 | X470500D02* 314 | X480500D01* 315 | X470500D02* 316 | Y459500D01* 317 | X471000Y460000D01* 318 | X461000Y470000D02* 319 | X471000Y460000D01* 320 | X435000Y470000D02* 321 | X461000D01* 322 | X366100D02* 323 | Y480000D01* 324 | X409500D01* 325 | Y470000D02* 326 | Y480000D01* 327 | X366100Y470000D02* 328 | X409500D01* 329 | X253900D02* 330 | Y480000D01* 331 | X338700D01* 332 | Y470000D02* 333 | Y480000D01* 334 | X315000Y470000D02* 335 | X338700D01* 336 | X305000Y460000D02* 337 | X315000Y470000D01* 338 | X305000Y460000D02* 339 | X305500Y459500D01* 340 | Y430000D02* 341 | Y459500D01* 342 | X291000Y430000D02* 343 | X305500D01* 344 | X291000D02* 345 | Y460000D01* 346 | X290500D02* 347 | X291000D01* 348 | X280500Y470000D02* 349 | X290500Y460000D01* 350 | X253900Y470000D02* 351 | X280500D01* 352 | X190000D02* 353 | X227500D01* 354 | Y480000D01* 355 | X190000D02* 356 | X227500D01* 357 | X190000Y470000D02* 358 | Y480000D01* 359 | X135500Y470000D02* 360 | X157500D01* 361 | X125500Y460000D02* 362 | X135500Y470000D01* 363 | X125000Y460000D02* 364 | X125500D01* 365 | X125000Y435000D02* 366 | Y460000D01* 367 | X115000Y435000D02* 368 | X125000D01* 369 | X115000D02* 370 | Y480000D01* 371 | X157500D01* 372 | Y470000D02* 373 | Y480000D01* 374 | X100000Y100000D02* 375 | X493700D01* 376 | Y493700D01* 377 | X100000D02* 378 | X493700D01* 379 | X100000Y100000D02* 380 | Y493700D01* 381 | M02* 382 | -------------------------------------------------------------------------------- /hardware/panel.GML: -------------------------------------------------------------------------------- 1 | G04 Layer_Color=12632256* 2 | %FSLAX25Y25*% 3 | %MOIN*% 4 | G70* 5 | G01* 6 | G75* 7 | %ADD49C,0.01000*% 8 | %ADD50O,0.04724X0.09449*% 9 | %ADD51O,0.06102X0.03543*% 10 | %ADD52O,0.03740X0.04921*% 11 | %ADD53C,0.07000*% 12 | %ADD54R,0.07000X0.07000*% 13 | %ADD55C,0.04000*% 14 | %ADD56R,0.04000X0.04000*% 15 | %ADD57R,0.07000X0.07000*% 16 | %ADD58C,0.07874*% 17 | D49* 18 | X125000Y260000D02* 19 | D03* 20 | Y265000D02* 21 | D03* 22 | Y255000D02* 23 | D03* 24 | Y250000D02* 25 | D03* 26 | Y245000D02* 27 | D03* 28 | Y240000D02* 29 | D03* 30 | X124600Y152500D02* 31 | D03* 32 | Y157500D02* 33 | D03* 34 | Y162500D02* 35 | D03* 36 | Y167500D02* 37 | D03* 38 | Y177500D02* 39 | D03* 40 | Y172500D02* 41 | D03* 42 | X290600Y150000D02* 43 | D03* 44 | Y155000D02* 45 | D03* 46 | Y160000D02* 47 | D03* 48 | Y165000D02* 49 | D03* 50 | Y175000D02* 51 | D03* 52 | Y170000D02* 53 | D03* 54 | X305100Y150000D02* 55 | D03* 56 | Y155000D02* 57 | D03* 58 | Y160000D02* 59 | D03* 60 | Y165000D02* 61 | D03* 62 | Y175000D02* 63 | D03* 64 | Y170000D02* 65 | D03* 66 | X291400Y229800D02* 67 | D03* 68 | Y234800D02* 69 | D03* 70 | Y239800D02* 71 | D03* 72 | Y244800D02* 73 | D03* 74 | Y254800D02* 75 | D03* 76 | Y249800D02* 77 | D03* 78 | X304800Y229300D02* 79 | D03* 80 | Y234300D02* 81 | D03* 82 | Y239300D02* 83 | D03* 84 | Y244300D02* 85 | D03* 86 | Y254300D02* 87 | D03* 88 | Y249300D02* 89 | D03* 90 | X125200Y409200D02* 91 | D03* 92 | Y414200D02* 93 | D03* 94 | Y419200D02* 95 | D03* 96 | Y424200D02* 97 | D03* 98 | Y434200D02* 99 | D03* 100 | Y429200D02* 101 | D03* 102 | X291200Y338300D02* 103 | D03* 104 | Y343300D02* 105 | D03* 106 | Y348300D02* 107 | D03* 108 | Y353300D02* 109 | D03* 110 | Y363300D02* 111 | D03* 112 | Y358300D02* 113 | D03* 114 | X291000Y404100D02* 115 | D03* 116 | Y409100D02* 117 | D03* 118 | Y414100D02* 119 | D03* 120 | Y419100D02* 121 | D03* 122 | Y429100D02* 123 | D03* 124 | Y424100D02* 125 | D03* 126 | X304900Y404500D02* 127 | D03* 128 | Y409500D02* 129 | D03* 130 | Y414500D02* 131 | D03* 132 | Y419500D02* 133 | D03* 134 | Y429500D02* 135 | D03* 136 | Y424500D02* 137 | D03* 138 | X304700Y338200D02* 139 | D03* 140 | Y343200D02* 141 | D03* 142 | Y348200D02* 143 | D03* 144 | Y353200D02* 145 | D03* 146 | Y363200D02* 147 | D03* 148 | Y358200D02* 149 | D03* 150 | X471200Y401400D02* 151 | D03* 152 | Y406400D02* 153 | D03* 154 | Y411400D02* 155 | D03* 156 | Y416400D02* 157 | D03* 158 | Y426400D02* 159 | D03* 160 | Y421400D02* 161 | D03* 162 | X471600Y339500D02* 163 | D03* 164 | Y344500D02* 165 | D03* 166 | Y349500D02* 167 | D03* 168 | Y354500D02* 169 | D03* 170 | Y364500D02* 171 | D03* 172 | Y359500D02* 173 | D03* 174 | Y216100D02* 175 | D03* 176 | Y221100D02* 177 | D03* 178 | Y226100D02* 179 | D03* 180 | Y231100D02* 181 | D03* 182 | Y241100D02* 183 | D03* 184 | Y236100D02* 185 | D03* 186 | X470600Y152500D02* 187 | D03* 188 | Y157500D02* 189 | D03* 190 | Y162500D02* 191 | D03* 192 | Y167500D02* 193 | D03* 194 | Y177500D02* 195 | D03* 196 | Y172500D02* 197 | D03* 198 | X443700Y124400D02* 199 | D03* 200 | X438700D02* 201 | D03* 202 | X433700D02* 203 | D03* 204 | X428700D02* 205 | D03* 206 | X418700D02* 207 | D03* 208 | X423700D02* 209 | D03* 210 | X357000Y124000D02* 211 | D03* 212 | X352000D02* 213 | D03* 214 | X347000D02* 215 | D03* 216 | X342000D02* 217 | D03* 218 | X332000D02* 219 | D03* 220 | X337000D02* 221 | D03* 222 | X360500Y289900D02* 223 | D03* 224 | X355500D02* 225 | D03* 226 | X350500D02* 227 | D03* 228 | X345500D02* 229 | D03* 230 | X335500D02* 231 | D03* 232 | X340500D02* 233 | D03* 234 | X432500Y290100D02* 235 | D03* 236 | X427500D02* 237 | D03* 238 | X422500D02* 239 | D03* 240 | X417500D02* 241 | D03* 242 | X407500D02* 243 | D03* 244 | X412500D02* 245 | D03* 246 | X431400Y303700D02* 247 | D03* 248 | X426400D02* 249 | D03* 250 | X421400D02* 251 | D03* 252 | X416400D02* 253 | D03* 254 | X406400D02* 255 | D03* 256 | X411400D02* 257 | D03* 258 | X360600Y304500D02* 259 | D03* 260 | X355600D02* 261 | D03* 262 | X350600D02* 263 | D03* 264 | X345600D02* 265 | D03* 266 | X335600D02* 267 | D03* 268 | X340600D02* 269 | D03* 270 | X365000Y469600D02* 271 | D03* 272 | X360000D02* 273 | D03* 274 | X355000D02* 275 | D03* 276 | X350000D02* 277 | D03* 278 | X340000D02* 279 | D03* 280 | X345000D02* 281 | D03* 282 | X435000D02* 283 | D03* 284 | X430000D02* 285 | D03* 286 | X425000D02* 287 | D03* 288 | X420000D02* 289 | D03* 290 | X410000D02* 291 | D03* 292 | X415000D02* 293 | D03* 294 | X252600D02* 295 | D03* 296 | X247600D02* 297 | D03* 298 | X242600D02* 299 | D03* 300 | X237600D02* 301 | D03* 302 | X227600D02* 303 | D03* 304 | X232600D02* 305 | D03* 306 | X183200Y469800D02* 307 | D03* 308 | X178200D02* 309 | D03* 310 | X173200D02* 311 | D03* 312 | X168200D02* 313 | D03* 314 | X158200D02* 315 | D03* 316 | X163200D02* 317 | D03* 318 | X175500Y303900D02* 319 | D03* 320 | X170500D02* 321 | D03* 322 | X165500D02* 323 | D03* 324 | X160500D02* 325 | D03* 326 | X150500D02* 327 | D03* 328 | X155500D02* 329 | D03* 330 | X175700Y290100D02* 331 | D03* 332 | X170700D02* 333 | D03* 334 | X165700D02* 335 | D03* 336 | X160700D02* 337 | D03* 338 | X150700D02* 339 | D03* 340 | X155700D02* 341 | D03* 342 | X260900Y303300D02* 343 | D03* 344 | X255900D02* 345 | D03* 346 | X250900D02* 347 | D03* 348 | X245900D02* 349 | D03* 350 | X235900D02* 351 | D03* 352 | X240900D02* 353 | D03* 354 | X261100Y290100D02* 355 | D03* 356 | X256100D02* 357 | D03* 358 | X251100D02* 359 | D03* 360 | X246100D02* 361 | D03* 362 | X236100D02* 363 | D03* 364 | X241100D02* 365 | D03* 366 | X261300Y123800D02* 367 | D03* 368 | X256300D02* 369 | D03* 370 | X251300D02* 371 | D03* 372 | X246300D02* 373 | D03* 374 | X236300D02* 375 | D03* 376 | X241300D02* 377 | D03* 378 | X180500Y124000D02* 379 | D03* 380 | X175500D02* 381 | D03* 382 | X170500D02* 383 | D03* 384 | X165500D02* 385 | D03* 386 | X155500D02* 387 | D03* 388 | X160500D02* 389 | D03* 390 | X125100Y351700D02* 391 | D03* 392 | Y356700D02* 393 | D03* 394 | Y346700D02* 395 | D03* 396 | Y341700D02* 397 | D03* 398 | Y336700D02* 399 | D03* 400 | Y331700D02* 401 | D03* 402 | D50* 403 | X147744Y146744D02* 404 | D03* 405 | X269791D02* 406 | D03* 407 | Y268791D02* 408 | D03* 409 | X147744D02* 410 | D03* 411 | X327744Y146744D02* 412 | D03* 413 | X449791D02* 414 | D03* 415 | Y268791D02* 416 | D03* 417 | X327744D02* 418 | D03* 419 | X147744Y326744D02* 420 | D03* 421 | X269791D02* 422 | D03* 423 | Y448791D02* 424 | D03* 425 | X147744D02* 426 | D03* 427 | X327744Y326744D02* 428 | D03* 429 | X449791D02* 430 | D03* 431 | Y448791D02* 432 | D03* 433 | X327744D02* 434 | D03* 435 | D51* 436 | X133008Y181964D02* 437 | D03* 438 | Y209524D02* 439 | D03* 440 | X313008Y181964D02* 441 | D03* 442 | Y209524D02* 443 | D03* 444 | X133008Y361964D02* 445 | D03* 446 | Y389524D02* 447 | D03* 448 | X313008Y361964D02* 449 | D03* 450 | Y389524D02* 451 | D03* 452 | D52* 453 | X144031Y185901D02* 454 | D03* 455 | Y205587D02* 456 | D03* 457 | X324031Y185901D02* 458 | D03* 459 | Y205587D02* 460 | D03* 461 | X144031Y365901D02* 462 | D03* 463 | Y385587D02* 464 | D03* 465 | X324031Y365901D02* 466 | D03* 467 | Y385587D02* 468 | D03* 469 | D53* 470 | X132044Y222344D02* 471 | D03* 472 | Y232344D02* 473 | D03* 474 | Y242344D02* 475 | D03* 476 | X235244Y252744D02* 477 | D03* 478 | X225244D02* 479 | D03* 480 | X215244D02* 481 | D03* 482 | X283500Y171200D02* 483 | D03* 484 | Y181200D02* 485 | D03* 486 | Y191200D02* 487 | D03* 488 | Y201200D02* 489 | D03* 490 | Y211200D02* 491 | D03* 492 | Y221200D02* 493 | D03* 494 | Y231200D02* 495 | D03* 496 | Y241200D02* 497 | D03* 498 | Y251200D02* 499 | D03* 500 | X312044Y222344D02* 501 | D03* 502 | Y232344D02* 503 | D03* 504 | Y242344D02* 505 | D03* 506 | X415244Y252744D02* 507 | D03* 508 | X405244D02* 509 | D03* 510 | X395244D02* 511 | D03* 512 | X463500Y171200D02* 513 | D03* 514 | Y181200D02* 515 | D03* 516 | Y191200D02* 517 | D03* 518 | Y201200D02* 519 | D03* 520 | Y211200D02* 521 | D03* 522 | Y221200D02* 523 | D03* 524 | Y231200D02* 525 | D03* 526 | Y241200D02* 527 | D03* 528 | Y251200D02* 529 | D03* 530 | X132044Y402344D02* 531 | D03* 532 | Y412344D02* 533 | D03* 534 | Y422344D02* 535 | D03* 536 | X235244Y432744D02* 537 | D03* 538 | X225244D02* 539 | D03* 540 | X215244D02* 541 | D03* 542 | X283500Y351200D02* 543 | D03* 544 | Y361200D02* 545 | D03* 546 | Y371200D02* 547 | D03* 548 | Y381200D02* 549 | D03* 550 | Y391200D02* 551 | D03* 552 | Y401200D02* 553 | D03* 554 | Y411200D02* 555 | D03* 556 | Y421200D02* 557 | D03* 558 | Y431200D02* 559 | D03* 560 | X312044Y402344D02* 561 | D03* 562 | Y412344D02* 563 | D03* 564 | Y422344D02* 565 | D03* 566 | X415244Y432744D02* 567 | D03* 568 | X405244D02* 569 | D03* 570 | X395244D02* 571 | D03* 572 | X463500Y351200D02* 573 | D03* 574 | Y361200D02* 575 | D03* 576 | Y371200D02* 577 | D03* 578 | Y381200D02* 579 | D03* 580 | Y391200D02* 581 | D03* 582 | Y401200D02* 583 | D03* 584 | Y411200D02* 585 | D03* 586 | Y421200D02* 587 | D03* 588 | Y431200D02* 589 | D03* 590 | D54* 591 | X132044Y252344D02* 592 | D03* 593 | X312044D02* 594 | D03* 595 | X132044Y432344D02* 596 | D03* 597 | X312044D02* 598 | D03* 599 | D55* 600 | X141744Y166744D02* 601 | D03* 602 | Y171744D02* 603 | D03* 604 | X146744Y166744D02* 605 | D03* 606 | Y171744D02* 607 | D03* 608 | X151744Y166744D02* 609 | D03* 610 | Y171744D02* 611 | D03* 612 | X156744Y166744D02* 613 | D03* 614 | Y171744D02* 615 | D03* 616 | X161744Y166744D02* 617 | D03* 618 | X321744D02* 619 | D03* 620 | Y171744D02* 621 | D03* 622 | X326744Y166744D02* 623 | D03* 624 | Y171744D02* 625 | D03* 626 | X331744Y166744D02* 627 | D03* 628 | Y171744D02* 629 | D03* 630 | X336744Y166744D02* 631 | D03* 632 | Y171744D02* 633 | D03* 634 | X341744Y166744D02* 635 | D03* 636 | X141744Y346744D02* 637 | D03* 638 | Y351744D02* 639 | D03* 640 | X146744Y346744D02* 641 | D03* 642 | Y351744D02* 643 | D03* 644 | X151744Y346744D02* 645 | D03* 646 | Y351744D02* 647 | D03* 648 | X156744Y346744D02* 649 | D03* 650 | Y351744D02* 651 | D03* 652 | X161744Y346744D02* 653 | D03* 654 | X321744D02* 655 | D03* 656 | Y351744D02* 657 | D03* 658 | X326744Y346744D02* 659 | D03* 660 | Y351744D02* 661 | D03* 662 | X331744Y346744D02* 663 | D03* 664 | Y351744D02* 665 | D03* 666 | X336744Y346744D02* 667 | D03* 668 | Y351744D02* 669 | D03* 670 | X341744Y346744D02* 671 | D03* 672 | D56* 673 | X161744Y171744D02* 674 | D03* 675 | X341744D02* 676 | D03* 677 | X161744Y351744D02* 678 | D03* 679 | X341744D02* 680 | D03* 681 | D57* 682 | X205244Y252744D02* 683 | D03* 684 | X283500Y161200D02* 685 | D03* 686 | X385244Y252744D02* 687 | D03* 688 | X463500Y161200D02* 689 | D03* 690 | X205244Y432744D02* 691 | D03* 692 | X283500Y341200D02* 693 | D03* 694 | X385244Y432744D02* 695 | D03* 696 | X463500Y341200D02* 697 | D03* 698 | D58* 699 | X235744Y276244D02* 700 | D03* 701 | X215744D02* 702 | D03* 703 | X415744D02* 704 | D03* 705 | X395744D02* 706 | D03* 707 | X235744Y456244D02* 708 | D03* 709 | X215744D02* 710 | D03* 711 | X415744D02* 712 | D03* 713 | X395744D02* 714 | D03* 715 | M02* 716 | -------------------------------------------------------------------------------- /hardware/panel.LDP: -------------------------------------------------------------------------------- 1 | Layer Pairs Export File for PCB: C:\Users\TSTERN\Google Drive\projects\Stepper_feedback\hardware\NZS_A4954_R2.0\panel.PcbDoc 2 | LayersSetName=Top_Bot_Thru_Holes|DrillFile=panel-roundholes.txt|DrillLayers=gtl,gbl 3 | LayersSetName=Top_Bot_Slot_Holes|DrillFile=panel-slotholes.txt|DrillLayers=gtl,gbl 4 | -------------------------------------------------------------------------------- /hardware/panel.REP: -------------------------------------------------------------------------------- 1 | ************************************************************* 2 | FileName = panel.GBR 3 | AutoAperture = True 4 | ************************************************************* 5 | Generating : Top Layer 6 | File : panel.GTL 7 | 8 | Adding Layer : Top Layer 9 | 10 | Adding Layer : Multi-Layer 11 | 12 | 13 | Used DCodes : 14 | D10 15 | D11 16 | D12 17 | D13 18 | D14 19 | D15 20 | D16 21 | D17 22 | D18 23 | D19 24 | D20 25 | D21 26 | D22 27 | D23 28 | D24 29 | D25 30 | D26 31 | D27 32 | D28 33 | D29 34 | D30 35 | D31 36 | D32 37 | D33 38 | D34 39 | D35 40 | D36 41 | D37 42 | D38 43 | D39 44 | D40 45 | D41 46 | D42 47 | D43 48 | D44 49 | D45 50 | D46 51 | D47 52 | D48 53 | D49 54 | D50 55 | D51 56 | D52 57 | D53 58 | D54 59 | D55 60 | D56 61 | D57 62 | D58 63 | D59 64 | D60 65 | ************************************************************* 66 | 67 | ************************************************************* 68 | Generating : Bottom Layer 69 | File : panel.GBL 70 | 71 | Adding Layer : Bottom Layer 72 | 73 | Adding Layer : Multi-Layer 74 | 75 | 76 | Used DCodes : 77 | D13 78 | D24 79 | D38 80 | D40 81 | D41 82 | D43 83 | D48 84 | D49 85 | D50 86 | D51 87 | D52 88 | D53 89 | D54 90 | D55 91 | D56 92 | D57 93 | D58 94 | D59 95 | D60 96 | D61 97 | D62 98 | D63 99 | D64 100 | D65 101 | D66 102 | ************************************************************* 103 | 104 | ************************************************************* 105 | Generating : Bottom Pad Master 106 | File : panel.GPB 107 | 108 | Adding Layer : Bottom Layer 109 | 110 | Adding Layer : Multi-Layer 111 | 112 | 113 | Used DCodes : 114 | D13 115 | D24 116 | D49 117 | D50 118 | D51 119 | D52 120 | D53 121 | D54 122 | D55 123 | D56 124 | D57 125 | D58 126 | D61 127 | D62 128 | D63 129 | D64 130 | D65 131 | D66 132 | ************************************************************* 133 | 134 | ************************************************************* 135 | Generating : Top Pad Master 136 | File : panel.GPT 137 | 138 | Adding Layer : Top Layer 139 | 140 | Adding Layer : Multi-Layer 141 | 142 | 143 | Used DCodes : 144 | D10 145 | D11 146 | D12 147 | D13 148 | D14 149 | D15 150 | D16 151 | D17 152 | D18 153 | D19 154 | D20 155 | D21 156 | D22 157 | D23 158 | D24 159 | D25 160 | D26 161 | D27 162 | D28 163 | D29 164 | D30 165 | D31 166 | D32 167 | D33 168 | D34 169 | D35 170 | D36 171 | D37 172 | D49 173 | D50 174 | D51 175 | D52 176 | D53 177 | D54 178 | D55 179 | D56 180 | D57 181 | D58 182 | ************************************************************* 183 | 184 | ************************************************************* 185 | Generating : Top Overlay 186 | File : panel.GTO 187 | 188 | Adding Layer : Top Overlay 189 | 190 | 191 | Used DCodes : 192 | D43 193 | D45 194 | D67 195 | D68 196 | D69 197 | D70 198 | ************************************************************* 199 | 200 | ************************************************************* 201 | Generating : Top Paste 202 | File : panel.GTP 203 | 204 | Adding Layer : Top Paste 205 | 206 | Adding Layer : Top Layer 207 | 208 | Adding Layer : Multi-Layer 209 | 210 | 211 | Used DCodes : 212 | D10 213 | D11 214 | D12 215 | D13 216 | D14 217 | D15 218 | D16 219 | D17 220 | D18 221 | D19 222 | D20 223 | D21 224 | D22 225 | D23 226 | D24 227 | D25 228 | D26 229 | D27 230 | D28 231 | D29 232 | D30 233 | D31 234 | D32 235 | D33 236 | D34 237 | D35 238 | D36 239 | D37 240 | D43 241 | ************************************************************* 242 | 243 | ************************************************************* 244 | Generating : Top Solder 245 | File : panel.GTS 246 | 247 | Adding Layer : Top Solder 248 | 249 | Adding Layer : Top Layer 250 | 251 | Adding Layer : Multi-Layer 252 | 253 | 254 | Used DCodes : 255 | D43 256 | D71 257 | D72 258 | D73 259 | D74 260 | D75 261 | D76 262 | D77 263 | D78 264 | D79 265 | D80 266 | D81 267 | D82 268 | D83 269 | D84 270 | D85 271 | D86 272 | D87 273 | D88 274 | D89 275 | D90 276 | D91 277 | D92 278 | D93 279 | D94 280 | D95 281 | D96 282 | D97 283 | D98 284 | D99 285 | D100 286 | D101 287 | D102 288 | D103 289 | D104 290 | D105 291 | D106 292 | D107 293 | D108 294 | ************************************************************* 295 | 296 | ************************************************************* 297 | Generating : Bottom Solder 298 | File : panel.GBS 299 | 300 | Adding Layer : Bottom Solder 301 | 302 | Adding Layer : Bottom Layer 303 | 304 | Adding Layer : Multi-Layer 305 | 306 | 307 | Used DCodes : 308 | D43 309 | D74 310 | D85 311 | D99 312 | D100 313 | D101 314 | D102 315 | D103 316 | D104 317 | D105 318 | D106 319 | D107 320 | D108 321 | D109 322 | D110 323 | D111 324 | D112 325 | D113 326 | D114 327 | D115 328 | ************************************************************* 329 | 330 | ************************************************************* 331 | Generating : Bottom Paste 332 | File : panel.GBP 333 | 334 | Adding Layer : Bottom Paste 335 | 336 | Adding Layer : Bottom Layer 337 | 338 | Adding Layer : Multi-Layer 339 | 340 | 341 | Used DCodes : 342 | D13 343 | D24 344 | D43 345 | D61 346 | D62 347 | D63 348 | D64 349 | D65 350 | D66 351 | ************************************************************* 352 | 353 | ************************************************************* 354 | Generating : Bottom Overlay 355 | File : panel.GBO 356 | 357 | Adding Layer : Bottom Overlay 358 | 359 | 360 | Used DCodes : 361 | D43 362 | D67 363 | D69 364 | D116 365 | ************************************************************* 366 | 367 | ************************************************************* 368 | Generating : Keep-Out Layer 369 | File : panel.GKO 370 | 371 | Adding Layer : Keep-Out Layer 372 | 373 | 374 | Used DCodes : 375 | D38 376 | D45 377 | ************************************************************* 378 | 379 | ************************************************************* 380 | Generating : Mechanical 1 381 | File : panel.GM1 382 | 383 | Adding Layer : Mechanical 1 384 | 385 | 386 | Used DCodes : 387 | ************************************************************* 388 | 389 | ************************************************************* 390 | Generating : Mechanical 3 391 | File : panel.GM3 392 | 393 | Adding Layer : Mechanical 3 394 | 395 | 396 | Used DCodes : 397 | D40 398 | D117 399 | ************************************************************* 400 | 401 | ************************************************************* 402 | Generating : Mechanical 2 403 | File : panel.GM2 404 | 405 | Adding Layer : Mechanical 2 406 | 407 | 408 | Used DCodes : 409 | D68 410 | ************************************************************* 411 | 412 | ************************************************************* 413 | Generating : Mechanical 13 414 | File : panel.GM13 415 | 416 | Adding Layer : Mechanical 13 417 | 418 | 419 | Used DCodes : 420 | D118 421 | ************************************************************* 422 | 423 | ************************************************************* 424 | Generating : Mechanical 15 425 | File : panel.GM15 426 | 427 | Adding Layer : Mechanical 15 428 | 429 | 430 | Used DCodes : 431 | D118 432 | D119 433 | ************************************************************* 434 | 435 | ************************************************************* 436 | Generating : Dielectric 1 437 | File : panel.1 438 | 439 | Adding Layer : Dielectric 1 440 | 441 | 442 | Used DCodes : 443 | ************************************************************* 444 | 445 | ************************************************************* 446 | Generating : Multi-Layer 447 | File : panel.GML 448 | 449 | Adding Layer : Multi-Layer 450 | 451 | 452 | Used DCodes : 453 | D49 454 | D50 455 | D51 456 | D52 457 | D53 458 | D54 459 | D55 460 | D56 461 | D57 462 | D58 463 | ************************************************************* 464 | 465 | ************************************************************* 466 | Generating : Drill Drawing 467 | File : panel.GD1 468 | 469 | Adding Drill Pair : Top Layer-Bottom Layer 470 | 471 | Adding Layer : Drill Drawing 472 | 473 | 474 | Used DCodes : 475 | D120 476 | D121 477 | D122 478 | ************************************************************* 479 | 480 | -------------------------------------------------------------------------------- /hardware/panel.RUL: -------------------------------------------------------------------------------- 1 | DRC Rules Export File for PCB: C:\Users\TSTERN\Google Drive\projects\Stepper_feedback\hardware\NZS_A4954_R2.0\panel.PcbDoc 2 | RuleKind=ShortCircuit|RuleName=ShortCircuit|Scope=Board|Allowed=0 3 | RuleKind=Clearance|RuleName=Clearance|Scope=Board|Minimum=10.00 4 | RuleKind=Width|RuleName=Width|Scope=Board|Minimum=10.00 5 | RuleKind=SolderMaskExpansion|RuleName=SolderMaskExpansion|Scope=Board|Minimum=4.00 6 | -------------------------------------------------------------------------------- /hardware/panel.apr: -------------------------------------------------------------------------------- 1 | D10 RECTANGULAR 31.496 35.433 0.000 FLASH 270.000 2 | D12 RECTANGULAR 39.370 70.866 0.000 FLASH 270.000 3 | D13 RECTANGULAR 31.496 33.465 0.000 FLASH 90.000 4 | D14 RECTANGULAR 15.748 68.898 0.000 FLASH 270.000 5 | D15 RECTANGULAR 47.244 94.488 0.000 FLASH 270.000 6 | D16 RECTANGULAR 47.244 122.047 0.000 FLASH 270.000 7 | D17 RECTANGULAR 47.244 70.866 0.000 FLASH 0.000 8 | D19 RECTANGULAR 31.496 31.496 0.000 FLASH 90.000 9 | D21 RECTANGULAR 27.559 51.181 0.000 FLASH 90.000 10 | D23 RECTANGULAR 23.622 35.433 0.000 FLASH 270.000 11 | D24 RECTANGULAR 35.433 29.528 0.000 FLASH 0.000 12 | D26 RECTANGULAR 202.756 202.756 0.000 FLASH 135.000 13 | D32 RECTANGULAR 66.929 39.370 0.000 FLASH 270.000 14 | D33 RECTANGULAR 118.110 118.110 0.000 FLASH 180.000 15 | D34 ROUNDED 17.716 55.118 0.000 FLASH 270.000 16 | D35 RECTANGULAR 17.716 55.118 0.000 FLASH 270.000 17 | D36 RECTANGULAR 27.559 37.402 0.000 FLASH 90.000 18 | D37 RECTANGULAR 125.000 45.000 0.000 FLASH 0.000 19 | D38 ROUNDED 6.000 6.000 0.000 LINE 0.000 20 | D39 ROUNDED 30.000 30.000 0.000 LINE 0.000 21 | D40 ROUNDED 20.000 20.000 0.000 LINE 0.000 22 | D41 ROUNDED 40.000 40.000 0.000 LINE 0.000 23 | D42 ROUNDED 16.000 16.000 0.000 LINE 0.000 24 | D43 ROUNDED 8.000 8.000 0.000 LINE 0.000 25 | D44 ROUNDED 25.000 25.000 0.000 LINE 0.000 26 | D45 ROUNDED 10.000 10.000 0.000 LINE 0.000 27 | D46 ROUNDED 50.000 50.000 0.000 LINE 0.000 28 | D47 ROUNDED 15.000 15.000 0.000 LINE 0.000 29 | D48 ROUNDED 60.000 60.000 0.000 LINE 0.000 30 | D49 ROUNDED 10.000 10.000 0.000 FLASH 0.000 31 | D50 ROUNDED 47.244 94.488 0.000 FLASH 0.000 32 | D51 ROUNDED 35.433 61.024 0.000 FLASH 270.000 33 | D52 ROUNDED 49.213 37.402 0.000 FLASH 270.000 34 | D53 ROUNDED 70.000 70.000 0.000 FLASH 0.000 35 | D54 RECTANGULAR 70.000 70.000 0.000 FLASH 0.000 36 | D55 ROUNDED 40.000 40.000 0.000 FLASH 0.000 37 | D56 RECTANGULAR 40.000 40.000 0.000 FLASH 0.000 38 | D57 RECTANGULAR 70.000 70.000 0.000 FLASH 90.000 39 | D58 ROUNDED 78.740 78.740 0.000 FLASH 0.000 40 | D59 ROUNDED 24.000 24.000 0.000 FLASH 0.000 41 | D60 ROUNDED 19.685 19.685 0.000 FLASH 0.000 42 | D61 RECTANGULAR 31.496 33.465 0.000 FLASH 180.000 43 | D62 RECTANGULAR 35.433 29.528 0.000 FLASH 90.000 44 | D64 RECTANGULAR 23.622 62.992 0.000 FLASH 0.000 45 | D65 RECTANGULAR 17.716 55.118 0.000 FLASH 0.000 46 | D66 ROUNDED 17.716 55.118 0.000 FLASH 0.000 47 | D67 ROUNDED 9.842 9.842 0.000 LINE 0.000 48 | D68 ROUNDED 5.000 5.000 0.000 LINE 0.000 49 | D69 ROUNDED 7.874 7.874 0.000 LINE 0.000 50 | D70 ROUNDED 14.000 14.000 0.000 LINE 0.000 51 | D71 RECTANGULAR 39.496 43.433 0.000 FLASH 270.000 52 | D73 RECTANGULAR 47.370 78.866 0.000 FLASH 270.000 53 | D74 RECTANGULAR 39.496 41.465 0.000 FLASH 90.000 54 | D75 RECTANGULAR 23.748 76.898 0.000 FLASH 270.000 55 | D76 RECTANGULAR 55.244 102.488 0.000 FLASH 270.000 56 | D77 RECTANGULAR 55.244 130.047 0.000 FLASH 270.000 57 | D78 RECTANGULAR 55.244 78.866 0.000 FLASH 0.000 58 | D80 RECTANGULAR 39.496 39.496 0.000 FLASH 90.000 59 | D82 RECTANGULAR 35.559 59.181 0.000 FLASH 90.000 60 | D84 RECTANGULAR 31.622 43.433 0.000 FLASH 270.000 61 | D85 RECTANGULAR 43.433 37.528 0.000 FLASH 0.000 62 | D87 RECTANGULAR 210.756 210.756 0.000 FLASH 135.000 63 | D93 RECTANGULAR 74.929 47.370 0.000 FLASH 270.000 64 | D94 RECTANGULAR 126.110 126.110 0.000 FLASH 180.000 65 | D95 ROUNDED 25.716 63.118 0.000 FLASH 270.000 66 | D96 RECTANGULAR 25.716 63.118 0.000 FLASH 270.000 67 | D97 RECTANGULAR 35.559 45.402 0.000 FLASH 90.000 68 | D98 RECTANGULAR 133.000 53.000 0.000 FLASH 0.000 69 | D99 ROUNDED 18.000 18.000 0.000 FLASH 0.000 70 | D100 ROUNDED 55.244 102.488 0.000 FLASH 0.000 71 | D101 ROUNDED 43.433 69.024 0.000 FLASH 270.000 72 | D102 ROUNDED 57.213 45.402 0.000 FLASH 270.000 73 | D103 ROUNDED 78.000 78.000 0.000 FLASH 0.000 74 | D104 RECTANGULAR 78.000 78.000 0.000 FLASH 0.000 75 | D105 ROUNDED 48.000 48.000 0.000 FLASH 0.000 76 | D106 RECTANGULAR 48.000 48.000 0.000 FLASH 0.000 77 | D107 RECTANGULAR 78.000 78.000 0.000 FLASH 90.000 78 | D108 ROUNDED 86.740 86.740 0.000 FLASH 0.000 79 | D109 RECTANGULAR 130.000 250.000 0.000 FLASH 0.000 80 | D110 RECTANGULAR 39.496 41.465 0.000 FLASH 180.000 81 | D111 RECTANGULAR 43.433 37.528 0.000 FLASH 90.000 82 | D113 RECTANGULAR 31.622 70.992 0.000 FLASH 0.000 83 | D114 RECTANGULAR 25.716 63.118 0.000 FLASH 0.000 84 | D115 ROUNDED 25.716 63.118 0.000 FLASH 0.000 85 | D116 ROUNDED 23.622 23.622 0.000 LINE 0.000 86 | D117 ROUNDED 47.244 47.244 0.000 LINE 0.000 87 | D118 ROUNDED 3.937 3.937 0.000 LINE 0.000 88 | D119 ROUNDED 1.968 1.968 0.000 LINE 0.000 89 | D120 ROUNDED 2.000 2.000 0.000 LINE 0.000 90 | D121 ROUNDED 2.667 2.667 0.000 LINE 0.000 91 | D122 ROUNDED 1.333 1.333 0.000 LINE 0.000 92 | -------------------------------------------------------------------------------- /stl/Helm.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/stl/Helm.SLDPRT -------------------------------------------------------------------------------- /stl/Helm.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/stl/Helm.STL -------------------------------------------------------------------------------- /stl/cover1.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/stl/cover1.SLDPRT -------------------------------------------------------------------------------- /stl/cover1.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/stl/cover1.STL -------------------------------------------------------------------------------- /stl/cover2.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/stl/cover2.SLDPRT -------------------------------------------------------------------------------- /stl/cover2.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizhi-singtown/stepServo/82482ecb6c9cf0ee52a0698e996605d1f5935393/stl/cover2.STL --------------------------------------------------------------------------------