uStepper S-lite
uStepperSLite.cpp
Go to the documentation of this file.
1 /********************************************************************************************
2 * File: uStepperSLite.cpp *
3 * Version: 1.1.0 *
4 * Date: June 14, 2020 *
5 * Author: Thomas Hørring Olsen *
6 * *
7 *********************************************************************************************
8 * uStepper S-lite class *
9 * *
10 * This file contains the implementation of the class methods, incorporated in the *
11 * uStepper S-lite arduino library. The library is used by instantiating an uStepper *
12 * S-lite object by calling either of the two overloaded constructors: *
13 * *
14 * example: *
15 * *
16 * uStepperSLite stepper; *
17 * *
18 * OR *
19 * *
20 * uStepperSLite stepper(500, 2000); *
21 * *
22 * The first instantiation above creates a uStepper S-lite object with default *
23 * acceleration and maximum speed (1000 steps/s^2 and 1000steps/s respectively). *
24 * The second instantiation overwrites the default settings of acceleration and *
25 * maximum speed (in this case 500 steps/s^2 and 2000 steps/s, respectively); *
26 * *
27 * After instantiation of the object, the object setup function should be called within *
28 * Arduino's setup function: *
29 * *
30 * example: *
31 * *
32 * uStepperSLite stepper; *
33 * *
34 * void setup() *
35 * { *
36 * stepper.setup(); *
37 * } *
38 * *
39 * void loop() *
40 * { *
41 * *
42 * } *
43 * *
44 * After this, the library is ready to control the motor! *
45 * *
46 *********************************************************************************************
47 * (C) 2018 *
48 * *
49 * uStepper ApS *
50 * www.ustepper.com *
51 * administration@ustepper.com *
52 * *
53 * The code contained in this file is released under the following open source license: *
54 * *
55 * Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International *
56 * *
57 * The code in this file is provided without warranty of any kind - use at own risk! *
58 * neither uStepper ApS nor the author, can be held responsible for any damage *
59 * caused by the use of the code contained in this file ! *
60 * *
61 ********************************************************************************************/
71 #include <uStepperSLite.h>
72 #include <math.h>
73 uStepperSLite *pointer;
74 volatile int32_t *p __attribute__((used));
76 extern "C" {
77 
78 void INT0_vect(void)
79 {
80  if(PIND & 0x04)
81  {
82  PORTD |= (1 << 4);
83  }
84  else
85  {
86  PORTD &= ~(1 << 4);
87  }
88  if((PINB & (0x08))) //CCW
89  {
90  if(!pointer->invertPidDropinDirection)
91  {
92  pointer->stepCnt--; //DIR is set to CCW, therefore we subtract 1 step from step count (negative values = number of steps in CCW direction from initial postion)
93  }
94  else
95  {
96  pointer->stepCnt++; //DIR is set to CW, therefore we add 1 step to step count (positive values = number of steps in CW direction from initial postion)
97  }
98 
99  }
100  else //CW
101  {
102  if(!pointer->invertPidDropinDirection)
103  {
104  pointer->stepCnt++; //DIR is set to CW, therefore we add 1 step to step count (positive values = number of steps in CW direction from initial postion)
105  }
106  else
107  {
108  pointer->stepCnt--; //DIR is set to CCW, therefore we subtract 1 step from step count (negative values = number of steps in CCW direction from initial postion)
109  }
110  }
111 }
112 
113 void INT1_vect(void)
114 {
115  if(PIND & 0x04)
116  {
117  PORTD |= (1 << 4);
118  }
119  else
120  {
121  PORTD &= ~(1 << 4);
122  }
123 }
124 
125 void TIMER3_COMPA_vect(void)
126 {
127  asm volatile("push r16 \n\t");
128  asm volatile("in r16,0x3F \n\t");
129  asm volatile("push r16 \n\t");
130  asm volatile("push r30 \n\t");
131  asm volatile("push r31 \n\t");
132  asm volatile("lds r30,p \n\t");
133  asm volatile("lds r31,p+1 \n\t");
134 
135  asm volatile("jmp _stepGenerator \n\t"); //Execute the acceleration profile algorithm
136 
137 }
138 
139 void TIMER1_COMPA_vect(void)
140  {
141  uint8_t data[2];
142  uint16_t curAngle;
143  int16_t deltaAngle;
144  float posError = 0.0;
145  static float posEst = 0.0;
146  static float velIntegrator = 0.0;
147  static float velEst = 0.0;
148  uint32_t temp;
149  int32_t stepCntTemp;
150  int32_t pidTargetPositionTruncated;
151  int32_t *stepsSinceResetPointer;
152  float tempFloat;
153  sei();
154 
155  if(I2C.getStatus() != I2CFREE)
156  {
157  return;
158  }
159 
160  I2C.read(ENCODERADDR, ANGLE, 2, data);
161 
162  curAngle = (((uint16_t)data[0]) << 8 ) | (uint16_t)data[1];
163  pointer->encoder.angle = curAngle;
164  curAngle -= pointer->encoder.encoderOffset;
165 
166  if(curAngle > 4095)
167  {
168  curAngle -= 61440;
169  }
170 
171  deltaAngle = (int16_t)pointer->encoder.oldAngle - (int16_t)curAngle;
172 
173  if(deltaAngle < -2047)
174  {
175  deltaAngle += 4096;
176  }
177 
178  else if(deltaAngle > 2047)
179  {
180  deltaAngle -= 4096;
181  }
182 
183  pointer->encoder.angleMoved -= deltaAngle; //The AS5600 encoder counts in the opposite direction
184  //as the AEAT8800 (the encoder on uStepper S).
185  //Therefore it is subtracted here, so the two boards
186  //behave similar
187 
188  pointer->encoder.oldAngle = curAngle;
189 
190  if(pointer->mode == DROPIN)
191  {
192  cli();
193  stepCntTemp = pointer->stepCnt;
194  sei();
195 
196  // Speed filter
197  posEst += velEst * ENCODERINTSAMPLETIME;
198  posError = (float)stepCntTemp - posEst;
199  velIntegrator += posError * PULSEFILTERKI;
200  velEst = (posError * PULSEFILTERKP) + velIntegrator;
201  pointer->currentPidSpeed = velIntegrator;
202 
203  posError = (float)stepCntTemp - ((float)pointer->encoder.angleMoved * pointer->stepConversion);
204 
205  pointer->pidDropin(posError);
206  return;
207  }
208  else
209  {
210  /*
211  // Speed filter
212  posEst += velEst * ENCODERINTSAMPLETIME;
213  posError = (float)pointer->encoder.angleMoved - posEst;
214  velIntegrator += posError * PULSEFILTERKI;
215  velEst = (posError * PULSEFILTERKP) + velIntegrator;
216  pointer->encoder.curSpeed = velIntegrator * pointer->stepConversion;
217  */
218 
219  //stepGenerator speed integrator
220  pointer->currentPidSpeed += pointer->currentPidAcceleration;
221  if(pointer->direction == CW)
222  {
223  if(pointer->currentPidSpeed >= pointer->velocity)
224  {
225  pointer->currentPidSpeed = pointer->velocity;
226  }
227  else if(pointer->currentPidSpeed < 0.0)
228  {
229  pointer->currentPidSpeed = 0.0;
230  }
231  }
232  else
233  {
234  if(pointer->currentPidSpeed <= -pointer->velocity)
235  {
236  pointer->currentPidSpeed = -pointer->velocity;
237  }
238  else if(pointer->currentPidSpeed > 0.0)
239  {
240  pointer->currentPidSpeed = 0.0;
241  }
242  }
243 
244 
245  //stepgenerator targetposition integrator
246  pointer->pidTargetPosition += pointer->currentPidSpeed * ENCODERINTSAMPLETIME;
247 
248  if(pointer->mode == PID)
249  {
250  pidTargetPositionTruncated = (int32_t)pointer->pidTargetPosition;
251  stepsSinceResetPointer = &pidTargetPositionTruncated;
252  }
253  else
254  {
255  stepsSinceResetPointer = &pointer->stepsSinceReset;
256  }
257 
258  if(pointer->continous == 1)
259  {
260  pointer->targetPosition = (float)pointer->pidTargetPosition;
261  }
262  else
263  {
264  if(pointer->targetPosition < 0)
265  {
266  if(pointer->pidTargetPosition < (float)pointer->targetPosition)
267  {
268  pointer->pidTargetPosition = (float)pointer->targetPosition;
269  }
270  }
271  else
272  {
273  if(pointer->pidTargetPosition > (float)pointer->targetPosition)
274  {
275  pointer->pidTargetPosition = (float)pointer->targetPosition;
276  }
277  }
278  }
279 
280  //acceleration profile generator
281  if(pointer->state == INITDECEL)
282  {
283  if(pointer->direction == CCW)
284  {
285  pointer->currentPidAcceleration = -(pointer->acceleration * ENCODERINTSAMPLETIME);
286  if(*stepsSinceResetPointer >= pointer->decelToAccelThreshold)
287  {
288  pointer->state = ACCEL;
289  }
290  }
291  else
292  {
293  pointer->currentPidAcceleration = pointer->acceleration * ENCODERINTSAMPLETIME;
294  if(*stepsSinceResetPointer <= pointer->decelToAccelThreshold)
295  {
296  pointer->state = ACCEL;
297  }
298  }
299 
300  }
301  else if(pointer->state == ACCEL)
302  {
303  if(pointer->direction == CCW)
304  {
305  if(*stepsSinceResetPointer <= pointer->accelToCruiseThreshold)
306  {
307  pointer->state = CRUISE;
308  }
309  pointer->currentPidAcceleration = -(pointer->acceleration * ENCODERINTSAMPLETIME);
310  }
311  else
312  {
313  if(*stepsSinceResetPointer >= pointer->accelToCruiseThreshold)
314  {
315  pointer->state = CRUISE;
316  }
317  pointer->currentPidAcceleration = pointer->acceleration * ENCODERINTSAMPLETIME;
318  }
319  }
320  else if(pointer->state == CRUISE)
321  {
322  if(pointer->continous == 1)
323  {
324  pointer->state = CRUISE;
325  }
326  else
327  {
328  if(pointer->direction == CCW)
329  {
330  if(*stepsSinceResetPointer <= pointer->cruiseToDecelThreshold)
331  {
332  pointer->state = DECEL;
333  }
334  }
335  else
336  {
337  if(*stepsSinceResetPointer >= pointer->cruiseToDecelThreshold)
338  {
339  pointer->state = DECEL;
340  }
341  }
342  }
343 
344  pointer->currentPidAcceleration = 0;
345 
346  }
347  else if(pointer->state == DECEL)
348  {
349  if(pointer->direction == CW)
350  {
351  if(*stepsSinceResetPointer >= pointer->decelToStopThreshold)
352  {
353  pointer->state = STOP;
354  }
355  pointer->currentPidAcceleration = -(pointer->acceleration * ENCODERINTSAMPLETIME);
356  }
357  else
358  {
359  if(*stepsSinceResetPointer <= pointer->decelToStopThreshold)
360  {
361  pointer->state = STOP;
362  }
363  pointer->currentPidAcceleration = pointer->acceleration * ENCODERINTSAMPLETIME;
364  }
365  }
366  else if(pointer->state == STOP)
367  {
368  pointer->currentPidAcceleration = 0.0;
369  pointer->currentPidSpeed = 0.0;
370  TCCR3B &= ~(1 << CS30);
371  if(pointer->mode == NORMAL)
372  {
373  if(pointer->brake == BRAKEON)
374  {
375  PORTD &= ~(1 << 4);
376  }
377  else
378  {
379  PORTD |= (1 << 4);
380  }
381  }
382  }
383 
384  if(pointer->mode == PID && !pointer->pidDisabled)
385  {
386  tempFloat = (float)pointer->encoder.angleMoved * pointer->stepConversion;
387  pointer->stepsSinceReset = (int32_t)(tempFloat);
388  pointer->pid((float)pointer->pidTargetPosition - tempFloat);
389  }
390  if(pointer->mode == NORMAL || pointer->pidDisabled)
391  {
392  if(pointer->currentPidSpeed > 5.0)
393  {
394  temp = (uint32_t)((STEPGENERATORFREQUENCY/(pointer->currentPidSpeed)) + 0.5);
395  cli();
396  pointer->stepDelay = temp;
397  sei();
398  }
399  else if(pointer->currentPidSpeed < -5.0)
400  {
401  temp = (uint32_t)((STEPGENERATORFREQUENCY/(-pointer->currentPidSpeed)) + 0.5);
402  cli();
403  pointer->stepDelay = temp;
404  sei();
405  }
406  else
407  {
408  cli();
409  pointer->stepDelay = 20000;
410  sei();
411  }
412  }
413 
414  pointer->detectStall();
415  }
416  }
417 }
418 
420 {
421  I2C.begin();
422 }
423 
425 {
426  return (float)this->angleMoved*0.087890625;
427 }
428 
430 {
431  if(unit == RPM)
432  {
433  return this->curSpeed * pointer->stepsPerSecondToRPM;
434  }
435  else //StepsPerSecond
436  {
437  return this->curSpeed;
438  }
439 }
440 
442 {
443  TCNT1 = 0;
444  ICR1 = 32000;
445  TIFR1 = 0;
446  TIMSK1 = (1 << OCIE1A);
447  TCCR1A = (1 << WGM11);
448  TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS10);
449 }
450 
452 {
453  cli();
454  uint8_t data[2];
455  TIMSK1 &= ~(1 << OCIE1A);
456  I2C.read(ENCODERADDR, ANGLE, 2, data);
457  TIMSK1 |= (1 << OCIE1A);
458  this->encoderOffset = (((uint16_t)data[0]) << 8 ) | (uint16_t)data[1];
459  pointer->stepsSinceReset = 0;
460  this->angle = 0;
461  this->oldAngle = 0;
462  this->angleMoved = 0;
463  pointer->pidTargetPosition = 0.0;
464  pointer->targetPosition = 0;
465  pointer->pidError = 0;
466  sei();
467 }
468 
470 {
471  return (float)this->angle*0.087890625;
472 }
473 
475 {
476  uint8_t data[2];
477 
478  TIMSK1 &= ~(1 << OCIE1A);
479  I2C.read(ENCODERADDR, MAGNITUDE, 2, data);
480  TIMSK1 |= (1 << OCIE1A);
481 
482  return (((uint16_t)data[0]) << 8 )| (uint16_t)data[1];
483 }
484 
486 {
487  uint8_t data;
488  TIMSK1 &= ~(1 << OCIE1A);
489  I2C.read(ENCODERADDR, AGC, 1, &data);
490  TIMSK1 |= (1 << OCIE1A);
491  return data;
492 }
493 
495 {
496  uint8_t data;
497  TIMSK1 &= ~(1 << OCIE1A);
498  I2C.read(ENCODERADDR, STATUS, 1, &data);
499  TIMSK1 |= (1 << OCIE1A);
500  data &= 0x38; //For some reason the encoder returns random values on reserved bits. Therefore we make sure reserved bits are cleared before checking the reply !
501 
502  if(data == 0x08)
503  {
504  return 1; //magnet too strong
505  }
506 
507  else if(data == 0x10)
508  {
509  return 2; //magnet too weak
510  }
511 
512  else if(data == 0x20)
513  {
514  return 0; //magnet detected and within limits
515  }
516 
517  return 3; //Something went horribly wrong !
518 }
519 
520 uStepperSLite::uStepperSLite(float accel, float vel)
521 {
522  this->state = STOP;
523 
524  this->setMaxVelocity(vel);
525  this->setMaxAcceleration(accel);
526 
527  pointer = this;
528 
529  DDRB |= (1 << 2); //set direction pin to output
530  DDRD |= (1 << 7); //set step pin to output
531  DDRD |= (1 << 4); //set enable pin to output
532 }
533 
535 {
536  this->acceleration = accel;
537 
538  if(this->state != STOP)
539  {
540  if(this->continous == 1) //If motor was running continously
541  {
542  this->runContinous(this->direction); //We should make it run continously again
543  }
544  else //If motor still needs to perform some steps
545  {
546  this->moveSteps(abs(this->targetPosition - this->stepsSinceReset + 1), this->direction, this->brake); //we should make sure the motor gets to execute the remaining steps
547  }
548  }
549 }
550 
552 {
553 
554  if(vel < 0.5005)
555  {
556  this->velocity = 0.5005; //Limit velocity in order to not overflow delay variable
557 
558  }
559 
560  else if(vel > 100000.0)
561  {
562  this->velocity = 100000.0; //limit velocity in order to not underflow delay variable
563  }
564 
565  else
566  {
567  this->velocity = vel;
568  }
569 
570  if(this->state != STOP) //If motor was running, we should make sure it runs again
571  {
572 
573  if(this->continous == 1) //If motor was running continously
574  {
575  this->runContinous(this->direction); //We should make it run continously again
576  }
577  else //If motor still needs to perform some steps
578  {
579  this->moveSteps(abs(this->targetPosition - this->stepsSinceReset + 1), this->direction, this->brake); //we should make sure the motor gets to execute the remaining steps
580  }
581  }
582 }
583 
585 {
586  float curVel, startVelocity = 0;
587  uint8_t tempState;
588  uint32_t accelSteps;
589  uint32_t initialDecelSteps;
590 
591  if(this->mode == DROPIN)
592  {
593  return; //Drop in feature is activated. just return since this function makes no sense with drop in activated!
594  }
595 
596  curVel = this->currentPidSpeed;
597 
598  if(this->state == STOP) //If motor is currently running at desired speed
599  {
600  initialDecelSteps = 0;
601  tempState = ACCEL; //We should just run at cruise speed
602  startVelocity = 0.0;//sqrt(2.0*this->acceleration); //number of interrupts before the first step should be performed.
603  accelSteps = (uint32_t)((this->velocity * this->velocity)/(2.0*this->acceleration)); //Number of steps to bring the motor to max speed (S = (V^2 - V0^2)/(2*a)))
604 
605  }
606  else if((dir == CW && curVel < 0) || (dir == CCW && curVel > 0)) //If motor turns CCW and should turn CW, or if motor turns CW and shoúld turn CCW
607  {
608  tempState = INITDECEL; //We should decelerate the motor to full stop
609  initialDecelSteps = (uint32_t)((curVel*curVel)/(2.0*this->acceleration)); //the amount of steps needed to bring the motor to full stop. (S = (V^2 - V0^2)/(2*-a)))
610  accelSteps = (uint32_t)((this->velocity * this->velocity)/(2.0*this->acceleration)); //Number of steps to bring the motor to max speed (S = (V^2 - V0^2)/(2*a)))
611 
612  startVelocity = curVel;//sqrt((curVel*curVel) + 2.0*this->acceleration); //number of interrupts before the first step should be performed.
613  }
614  else if((dir == CW && curVel > 0) || (dir == CCW && curVel < 0)) //If the motor is currently rotating the same direction as the desired direction
615  {
616  if(abs(curVel) > this->velocity) //If current velocity is greater than desired velocity
617  {
618  tempState = INITDECEL; //We need to decelerate the motor to desired velocity
619  initialDecelSteps = (uint32_t)(((this->velocity*this->velocity) - (curVel*curVel))/(-2.0*this->acceleration)); //Number of steps to bring the motor down from current speed to max speed (S = (V^2 - V0^2)/(2*-a)))
620  accelSteps = 0; //No acceleration phase is needed
621  }
622 
623  else if(abs(curVel) < this->velocity) //If the current velocity is less than the desired velocity
624  {
625  tempState = ACCEL; //Start accelerating
626  accelSteps = (uint32_t)(((this->velocity*this->velocity) - (curVel*curVel))/(2.0*this->acceleration)); //Number of Steps needed to accelerate from current velocity to full speed
627  initialDecelSteps = 0;
628  }
629 
630  else //If motor is currently running at desired speed
631  {
632  initialDecelSteps = 0;
633  tempState = CRUISE; //We should just run at cruise speed
634  accelSteps = 0; //No acceleration phase is needed
635  }
636  }
637  else
638  {
639  initialDecelSteps = 0;
640  tempState = ACCEL; //We should just run at cruise speed
641  startVelocity = 0.0;//sqrt(2.0*this->acceleration); //number of interrupts before the first step should be performed.
642  accelSteps = (uint32_t)((this->velocity * this->velocity)/(2.0*this->acceleration)); //Number of steps to bring the motor to max speed (S = (V^2 - V0^2)/(2*a)))
643  }
644  cli();
645  this->direction = dir;
646  this->stepGeneratorDirection = dir;
647 
648  this->continous = 1;
649 
650  if(dir == CW)
651  {
652  this->decelToAccelThreshold = this->stepsSinceReset + initialDecelSteps;
653  this->accelToCruiseThreshold = this->decelToAccelThreshold + accelSteps;
654  PORTB |= (1 << 2);
655  }
656  else
657  {
658  this->decelToAccelThreshold = this->stepsSinceReset - initialDecelSteps;
659  this->accelToCruiseThreshold = this->decelToAccelThreshold - accelSteps;
660  PORTB &= ~(1 << 2);
661  }
662  this->currentPidSpeed = startVelocity;
663  if(pointer->currentPidSpeed > 5.0)
664  {
665  pointer->stepDelay = (uint32_t)((STEPGENERATORFREQUENCY/(pointer->currentPidSpeed)) + 0.5);
666  }
667  else if(pointer->currentPidSpeed < -5.0)
668  {
669  pointer->stepDelay = (uint32_t)((STEPGENERATORFREQUENCY/(-pointer->currentPidSpeed)) + 0.5);
670  }
671  else
672  {
673  pointer->stepDelay = 20000;
674  }
675  this->state = tempState;
676  sei();
677 
678  PORTD &= ~(1 << 4);
679  TCCR3B |= (1 << CS30);
680 }
681 
682 void uStepperSLite::moveSteps(int32_t steps, bool dir, bool holdMode)
683 {
684  float curVel, startVelocity = 0;
685  uint8_t state;
686  uint32_t totalSteps;
687  uint32_t accelSteps;
688  uint32_t decelSteps;
689  uint32_t initialDecelSteps;
690  uint32_t cruiseSteps = 0;
691 
692  if(this->mode == DROPIN)
693  {
694  return; //Drop in feature is activated. just return since this function makes no sense with drop in activated!
695  }
696 
697  if(steps < 1)
698  {
699  return;
700  }
701  //steps--;
702  totalSteps = steps;
703  cli();
704  curVel = this->currentPidSpeed;
705  sei();
706 
707 
708  initialDecelSteps = 0;
709 
710  if(this->state == STOP) //If motor is currently at full stop (state = STOP)
711  {
712  state = ACCEL;
713  accelSteps = (uint32_t)((this->velocity * this->velocity)/(2.0*this->acceleration)); //Number of steps to bring the motor to max speed (S = (V^2 - V0^2)/(2*a)))
714  //No initial deceleration phase needed
715 
716  if(accelSteps > (totalSteps >> 1)) //If we need to accelerate for longer than half of the total steps, we need to start decelerating before we reach max speed
717  {
718  cruiseSteps = 0; //No cruise phase needed
719  accelSteps = decelSteps = (totalSteps >> 1); //Accelerate and decelerate for the same amount of steps (half the total steps)
720  accelSteps += totalSteps - accelSteps - decelSteps; //if there are still a step left to perform, due to rounding errors, do this step as an acceleration step
721  }
722 
723  else
724  {
725  decelSteps = accelSteps; //If top speed is reached before half the total steps are performed, deceleration period should be same length as acceleration period
726  cruiseSteps = totalSteps - accelSteps - decelSteps; //Perform remaining steps as cruise steps
727  }
728  startVelocity = 0.0;//sqrt(2.0*this->acceleration); //number of interrupts before the first step should be performed.
729  }
730  else if((dir == CW && curVel < 0) || (dir == CCW && curVel > 0)) //If motor turns CCW and should turn CW, or if motor turns CW and shoúld turn CCW
731  {
732  state = INITDECEL; //We should decelerate the motor to full stop
733  initialDecelSteps = (uint32_t)((curVel*curVel)/(2.0*this->acceleration)); //the amount of steps needed to bring the motor to full stop. (S = (V^2 - V0^2)/(2*-a)))
734  accelSteps = (uint32_t)((this->velocity * this->velocity)/(2.0*this->acceleration)); //Number of steps to bring the motor to max speed (S = (V^2 - V0^2)/(2*a)))
735  totalSteps += initialDecelSteps; //Add the steps used for initial deceleration to the totalSteps variable, since we moved this number of steps, passed the initial position, and therefore need to move this amount of steps extra, in the desired direction
736 
737  if(accelSteps > (totalSteps >> 1)) //If we need to accelerate for longer than half of the total steps, we need to start decelerating before we reach max speed
738  {
739  accelSteps = decelSteps = (totalSteps >> 1); //Accelerate and decelerate for the same amount of steps (half the total steps)
740  accelSteps += totalSteps - accelSteps - decelSteps; //If there are still a step left to perform, due to rounding errors, do this step as an acceleration step
741  cruiseSteps = 0;
742  }
743  else
744  {
745  decelSteps = accelSteps; //If top speed is reached before half the total steps are performed, deceleration period should be same length as acceleration period
746  cruiseSteps = totalSteps - accelSteps - decelSteps; //Perform remaining steps, as cruise steps
747  }
748  startVelocity = curVel; //sqrt((curVel*curVel) + 2.0*this->acceleration); //number of interrupts before the first step should be performed.
749  }
750  else if((dir == CW && curVel > 0) || (dir == CCW && curVel < 0)) //If the motor is currently rotating the same direction as desired, we dont necessarily need to decelerate
751  {
752  if(abs(curVel) > this->velocity) //If current velocity is greater than desired velocity
753  {
754  state = INITDECEL; //We need to decelerate the motor to desired velocity
755  initialDecelSteps = (uint32_t)(((this->velocity*this->velocity) - (curVel*curVel))/(-2.0*this->acceleration)); //Number of steps to bring the motor down from current speed to max speed (S = (V^2 - V0^2)/(2*-a)))
756  accelSteps = 0; //No acceleration phase is needed
757  decelSteps = (uint32_t)((this->velocity*this->velocity)/(2.0*this->acceleration)); //Number of steps needed to decelerate the motor from top speed to full stop
758  startVelocity = curVel;//sqrt((curVel*curVel) + (2.0*this->acceleration));
759  if(totalSteps <= (initialDecelSteps + decelSteps))
760  {
761  cruiseSteps = 0;
762  }
763  else
764  {
765  cruiseSteps = steps - initialDecelSteps - decelSteps; //Perform remaining steps as cruise steps
766  }
767  }
768 
769  else if(abs(curVel) < this->velocity) //If current velocity is less than desired velocity
770  {
771  state = ACCEL; //Start accelerating
772  accelSteps = (int32_t)((((this->velocity*this->velocity) - curVel*curVel))/(2.0*this->acceleration)); //Number of Steps needed to accelerate from current velocity to full speed
773 
774  if(accelSteps > (totalSteps >> 1)) //If we need to accelerate for longer than half of the total steps, we need to start decelerating before we reach max speed
775  {
776  accelSteps = decelSteps = (totalSteps >> 1); //Accelerate and decelerate for the same amount of steps (half the total steps)
777  accelSteps += totalSteps - accelSteps - decelSteps; //If there are still a step left to perform, due to rounding errors, do this step as an acceleration step
778  cruiseSteps = 0;
779  }
780  else
781  {
782  decelSteps = accelSteps; //If top speed is reached before half the total steps are performed, deceleration period should be same length as acceleration period
783  cruiseSteps = totalSteps - accelSteps - decelSteps; //Perform remaining steps, as cruise steps
784  }
785 
786  cruiseSteps = totalSteps - accelSteps - decelSteps; //Perform remaining steps as cruise steps
787  initialDecelSteps = 0; //No initial deceleration phase needed
788  }
789 
790  else //If current velocity is equal to desired velocity
791  {
792  state = CRUISE; //We are already at desired speed, therefore we start at cruise phase
793  decelSteps = (int32_t)((this->velocity*this->velocity)/(2.0*this->acceleration)); //Number of steps needed to decelerate the motor from top speed to full stop
794  accelSteps = 0; //No acceleration phase needed
795  initialDecelSteps = 0; //No initial deceleration phase needed
796 
797  if(decelSteps >= totalSteps)
798  {
799  cruiseSteps = 0;
800  decelSteps = totalSteps;
801  }
802  else
803  {
804  cruiseSteps = totalSteps - decelSteps; //Perform remaining steps as cruise steps
805  }
806  }
807  startVelocity = curVel;
808  }
809  else
810  {
811  state = ACCEL;
812  accelSteps = (uint32_t)((this->velocity * this->velocity)/(2.0*this->acceleration)); //Number of steps to bring the motor to max speed (S = (V^2 - V0^2)/(2*a)))
813  //No initial deceleration phase needed
814 
815  if(accelSteps > (totalSteps >> 1)) //If we need to accelerate for longer than half of the total steps, we need to start decelerating before we reach max speed
816  {
817  cruiseSteps = 0; //No cruise phase needed
818  accelSteps = decelSteps = (totalSteps >> 1); //Accelerate and decelerate for the same amount of steps (half the total steps)
819  accelSteps += totalSteps - accelSteps - decelSteps; //if there are still a step left to perform, due to rounding errors, do this step as an acceleration step
820  }
821 
822  else
823  {
824  decelSteps = accelSteps; //If top speed is reached before half the total steps are performed, deceleration period should be same length as acceleration period
825  cruiseSteps = totalSteps - accelSteps - decelSteps; //Perform remaining steps as cruise steps
826  }
827  startVelocity = 0.0;
828  }
829  cli();
830  this->direction = dir;
831  this->stepGeneratorDirection = dir;
832 
833  this->continous = 0;
834 
835  if(dir == CW)
836  {
837  this->decelToAccelThreshold = this->stepsSinceReset + initialDecelSteps;
838  this->accelToCruiseThreshold = this->decelToAccelThreshold + accelSteps;
839  this->cruiseToDecelThreshold = this->accelToCruiseThreshold + cruiseSteps;
840  this->decelToStopThreshold = this->cruiseToDecelThreshold + decelSteps;
841  PORTB |= (1 << 2);
842  }
843  else
844  {
845  this->decelToAccelThreshold = this->stepsSinceReset - initialDecelSteps;
846  this->accelToCruiseThreshold = this->decelToAccelThreshold - accelSteps;
847  this->cruiseToDecelThreshold = this->accelToCruiseThreshold - cruiseSteps;
848  this->decelToStopThreshold = this->cruiseToDecelThreshold - decelSteps;
849  PORTB &= ~(1 << 2);
850  }
851  this->currentPidSpeed = startVelocity;
852  if(pointer->currentPidSpeed > 5.0)
853  {
854  pointer->stepDelay = (uint32_t)((STEPGENERATORFREQUENCY/(pointer->currentPidSpeed)) + 0.5);
855  }
856  else if(pointer->currentPidSpeed < -5.0)
857  {
858  pointer->stepDelay = (uint32_t)((STEPGENERATORFREQUENCY/(-pointer->currentPidSpeed)) + 0.5);
859  }
860  else
861  {
862  pointer->stepDelay = 20000;
863  }
864  this->state = state;
865  this->targetPosition = this->decelToStopThreshold;
866  this->brake = holdMode;
867  sei();
868 
869  PORTD &= ~(1 << 4);
870  TCCR3B |= (1 << CS30);
871 }
872 
873 void uStepperSLite::hardStop(bool holdMode)
874 {
875  if(this->mode == DROPIN)
876  {
877  return; //Drop in feature is activated. just return since this function makes no sense with drop in activated!
878  }
879 
880  cli();
881 
882  this->stepsSinceReset = (int32_t)((float)this->encoder.angleMoved * this->stepConversion);
883  this->targetPosition = this->stepsSinceReset;
884  this->pidTargetPosition = this->targetPosition;
885  this->decelToStopThreshold = this->targetPosition;
886 
887  this->state = DECEL;
888  this->brake = holdMode;
889  this->continous = 0;
890  this->stepDelay = 2;
891 
892  sei();
893 
894  PORTD &= ~(1 << 4);
895  TCCR3B |= (1 << CS30);
896 }
897 
898 void uStepperSLite::stop(bool brake)
899 {
900  this->softStop(brake);
901 }
902 
903 void uStepperSLite::softStop(bool holdMode)
904 {
905  uint32_t decelSteps = 0;
906  float curVel = 0.0;
907 
908  if(this->mode == DROPIN)
909  {
910  return; //Drop in feature is activated. just return since this function makes no sense with drop in activated!
911  }
912 
913  cli();
914  curVel = this->currentPidSpeed;
915  decelSteps = (uint32_t)((curVel*curVel)/(2.0*this->acceleration));
916  if(this->direction == CW)
917  {
918  this->targetPosition = this->stepsSinceReset + decelSteps;
919  pointer->decelToStopThreshold = this->targetPosition;
920  }
921  else
922  {
923  this->targetPosition = this->stepsSinceReset - decelSteps;
924  pointer->decelToStopThreshold = this->targetPosition;
925  }
926 
927  this->state = DECEL;
928  this->brake = holdMode;
929  this->continous = 0;
930  this->currentPidSpeed = curVel;
931  if(pointer->currentPidSpeed > 5.0)
932  {
933  pointer->stepDelay = (uint32_t)((STEPGENERATORFREQUENCY/(pointer->currentPidSpeed)) + 0.5);
934  }
935  else if(pointer->currentPidSpeed < -5.0)
936  {
937  pointer->stepDelay = (uint32_t)((STEPGENERATORFREQUENCY/(-pointer->currentPidSpeed)) + 0.5);
938  }
939  else
940  {
941  pointer->stepDelay = 20000;
942  }
943  sei();
944 
945  PORTD &= ~(1 << 4);
946  TCCR3B |= (1 << CS30);
947 }
948 
950 {
951  uint8_t data[2], i;
952  uint16_t angle;
953  int16_t angleDiff[3];
954 
955  I2C.read(ENCODERADDR, ANGLE, 2, data);
956  angle = (((uint16_t)data[0]) << 8 ) | (uint16_t)data[1];
957 
958  PORTB &= ~(1 << 2);
959 
960  for(i = 0; i < 50; i++)
961  {
962  PORTD |= (1 << 7);
963  delayMicroseconds(1);
964  PORTD &= ~(1 << 7);
965  _delay_ms(10);
966  }
967 
968  angleDiff[0] = (int16_t)angle;
969 
970  I2C.read(ENCODERADDR, ANGLE, 2, data);
971  angle = (((uint16_t)data[0]) << 8 ) | (uint16_t)data[1];
972 
973  angleDiff[0] -= (int16_t)angle;
974 
975  PORTB |= (1 << 2);
976 
977  for(i = 0; i < 50; i++)
978  {
979  PORTD |= (1 << 7);
980  delayMicroseconds(1);
981  PORTD &= ~(1 << 7);
982  _delay_ms(10);
983  }
984 
985  angleDiff[1] = (int16_t)angle;
986 
987  I2C.read(ENCODERADDR, ANGLE, 2, data);
988  angle = (((uint16_t)data[0]) << 8 ) | (uint16_t)data[1];
989 
990  angleDiff[1] -= (int16_t)angle;
991 
992  for(i = 0; i < 2; i++)
993  {
994  if(angleDiff[i] > 2048)
995  {
996  angleDiff[i] -= 4096;
997  }
998  else if(angleDiff[i] < -2048)
999  {
1000  angleDiff[i] += 4096;
1001  }
1002  }
1003 
1004  if((angleDiff[0] > 2 && angleDiff[1] < -2))
1005  {
1006  if(mode == DROPIN)
1007  {
1008  this->driver.invertDirection();
1009  }
1010  }
1011  else
1012  {
1013  if(mode != DROPIN)
1014  {
1015  this->driver.invertDirection();
1016  }
1017  }
1018 }
1019 
1020 void uStepperSLite::setup( uint8_t mode = NORMAL,
1021  float stepsPerRevolution = 3200.0,
1022  float pTerm = 0.75,
1023  float iTerm = 3.0,
1024  float dTerm = 0.0,
1025  bool setHome = true,
1026  uint8_t invert,
1027  uint8_t runCurrent,
1028  uint8_t holdCurrent)
1029 {
1030  dropinCliSettings_t tempSettings;
1031 
1032  p = &(this->stepsSinceReset);
1033  this->pidDisabled = 1;
1034  this->mode = mode;
1035  this->encoder.setup();
1036 
1037  this->state = STOP;
1038  this->driver.setup();
1039  this->driver.enableDriver();
1040  _delay_ms(200);
1041 
1042  if((uint16_t)stepsPerRevolution == FULL)
1043  {
1044  stepsPerRevolution = 200.0;
1045  }
1046  else if((uint16_t)stepsPerRevolution == HALF)
1047  {
1048  stepsPerRevolution = 400.0;
1049  }
1050  else if((uint16_t)stepsPerRevolution == QUARTER)
1051  {
1052  stepsPerRevolution = 800.0;
1053  }
1054  else if((uint16_t)stepsPerRevolution == EIGHT)
1055  {
1056  stepsPerRevolution = 1600.0;
1057  }
1058  else if((uint16_t)stepsPerRevolution == SIXTEEN)
1059  {
1060  stepsPerRevolution = 3200.0;
1061  }
1062 
1063  this->stepConversion = (float)(stepsPerRevolution)/4096.0; //Calculate conversion coefficient from raw encoder data, to actual moved steps
1064  this->angleToStep = ((float)(stepsPerRevolution))/360.0; //Calculate conversion coefficient from angle to corresponding number of steps
1065  this->stepToAngle = 360.0/((float)(stepsPerRevolution)); //Calculate conversion coefficient from steps to corresponding angle
1066  this->stepsPerSecondToRPM = 60.0/stepsPerRevolution;
1067  this->RPMToStepsPerSecond = stepsPerRevolution/60.0;
1068  this->RPMToStepDelay = STEPGENERATORFREQUENCY/this->RPMToStepsPerSecond;
1069  this->encoder.setHome();
1070 
1071  if(this->mode)
1072  {
1073  if(this->mode == DROPIN)
1074  {
1075  //Set Enable, Step and Dir signal pins from 3dPrinter controller as inputs
1076  pinMode(2,INPUT);
1077  pinMode(3,INPUT);
1078  pinMode(4,INPUT);
1079  //Enable internal pull-up resistors on the above pins
1080  digitalWrite(2,HIGH);
1081  digitalWrite(3,HIGH);
1082  digitalWrite(4,HIGH);
1083  EICRA = 0x06;
1084  EIMSK = 0x03;
1085 
1086  Serial.begin(9600);
1087 
1088  tempSettings.P.f = pTerm;
1089  tempSettings.I.f = iTerm;
1090  tempSettings.D.f = dTerm;
1091  tempSettings.invert = invert;
1092  tempSettings.runCurrent = runCurrent;
1093  tempSettings.holdCurrent = holdCurrent;
1094  tempSettings.checksum = this->dropinSettingsCalcChecksum(&tempSettings);
1095 
1096  if(tempSettings.checksum != EEPROM.read(sizeof(dropinCliSettings_t)))
1097  {
1098  this->dropinSettings = tempSettings;
1099  this->saveDropinSettings();
1100  EEPROM.put(sizeof(dropinCliSettings_t),this->dropinSettings.checksum);
1101  this->loadDropinSettings();
1102  }
1103  else
1104  {
1105  if(!this->loadDropinSettings())
1106  {
1107  this->dropinSettings = tempSettings;
1108  this->saveDropinSettings();
1109  EEPROM.put(sizeof(dropinCliSettings_t),this->dropinSettings.checksum);
1110  this->loadDropinSettings();
1111  }
1112  }
1113  delay(10000);
1114  this->dropinPrintHelp();
1115  }
1116  else
1117  {
1118  //Scale supplied controller coefficents. This is done to enable the user to use easier to manage numbers for these coefficients.
1119  this->pTerm = pTerm;
1120  this->iTerm = iTerm * ENCODERINTSAMPLETIME;
1121  this->dTerm = dTerm * ENCODERINTFREQ;
1122  }
1123  }
1124 
1126  this->encoder.setHome();
1127 
1128  this->pidDisabled = 0;
1129  TCNT3 = 0;
1130  ICR3 = 159;
1131  TIFR3 = 0;
1132  TIMSK3 = (1 << OCIE3A);
1133  TCCR3A = (1 << WGM31);
1134  TCCR3B = (1 << WGM32) | (1 << WGM33);
1135  sei();
1136 }
1137 
1139 {
1140  this->driver.enableDriver(); //Enable motor driver
1141 }
1142 
1144 {
1145  this->driver.disableDriver(); //Disable motor driver
1146 }
1147 
1149 {
1150  return this->direction;
1151 }
1152 
1154 {
1155  if(this->state != STOP)
1156  {
1157  return this->state; //Motor running
1158  }
1159 
1160  return 0; //Motor not running
1161 }
1162 
1164 {
1165  return this->stepsSinceReset;
1166 }
1167 
1168 void uStepperSLite::setCurrent(uint8_t runCurrent, uint8_t holdCurrent)
1169 {
1170  this->driver.setCurrent(runCurrent, holdCurrent);
1171 }
1172 
1173 void uStepperSLite::setHoldCurrent(uint8_t holdCurrent)
1174 {
1175  this->driver.setHoldCurrent(holdCurrent);
1176 }
1177 
1178 void uStepperSLite::setRunCurrent(uint8_t runCurrent)
1179 {
1180  this->driver.setRunCurrent(runCurrent);
1181 }
1182 
1183 //Skal GennemgÃ¥s !
1184 float uStepperSLite::moveToEnd(bool dir, float stallSensitivity)
1185 {
1186  uint8_t checks = 0;
1187  float pos = 0.0;
1188  float lengthMoved;
1189 
1190  if(this->mode == DROPIN)
1191  {
1192  return 0.0; //Doesn't make sense in dropin mode
1193  }
1194 
1195  lengthMoved = this->encoder.getAngleMoved();
1196 
1197  this->stop(HARD);
1198  _delay_ms(50);
1199  this->runContinous(dir);
1200  _delay_ms(200);
1201  while(!this->isStalled(stallSensitivity));
1202  this->stop(SOFT);//stop motor without brake
1203 
1204  this->moveSteps(20, !dir, SOFT);
1205  while(this->getMotorState())
1206  {
1207  _delay_ms(1);
1208  }
1209  _delay_ms(100);
1210  if(dir == CW)
1211  {
1212  lengthMoved = this->encoder.getAngleMoved() - lengthMoved;
1213  }
1214  else
1215  {
1216  lengthMoved -= this->encoder.getAngleMoved();
1217  }
1218  this->encoder.setHome();//set new home position
1219 
1220  return lengthMoved;
1221 }
1222 
1223 void uStepperSLite::moveToAngle(float angle, bool holdMode)
1224 {
1225  float diff;
1226  uint32_t steps;
1227 
1228  diff = angle - this->encoder.getAngleMoved();
1229  steps = (uint32_t)((abs(diff)*angleToStep) + 0.5);
1230 
1231  if(diff < 0.0)
1232  {
1233  this->moveSteps(steps, CCW, holdMode);
1234  }
1235  else
1236  {
1237  this->moveSteps(steps, CW, holdMode);
1238  }
1239 }
1240 
1241 void uStepperSLite::moveAngle(float angle, bool holdMode)
1242 {
1243  int32_t steps;
1244 
1245  if(angle < 0.0)
1246  {
1247  steps = -(int32_t)((angle*angleToStep) - 0.5);
1248  this->moveSteps(steps, CCW, holdMode);
1249  }
1250  else
1251  {
1252  steps = (int32_t)((angle*angleToStep) + 0.5);
1253  this->moveSteps(steps, CW, holdMode);
1254  }
1255 }
1256 
1257 void uStepperSLite::pid(float error)
1258 {
1259  float u, uSat, temp;
1260  float limit = abs(this->currentPidSpeed) + 6000.0;
1261  static float integral;
1262  static bool integralReset = 0;
1263 
1264  if(this->pidDisabled)
1265  {
1266  integral = 0.0;
1267  integralReset = 0;
1268  this->currentPidError = 0.0;
1269  if(this->state == STOP)
1270  {
1271  if(this->brake == BRAKEON)
1272  {
1273  PORTD &= ~(1 << 4);
1274  }
1275  else
1276  {
1277  PORTD |= (1 << 4);
1278  }
1279  }
1280 
1281  return;
1282  }
1283 
1284  PORTD &= ~(1 << 4);
1285 
1286  this->currentPidError = error;
1287 
1288  u = error*this->pTerm;
1289 
1290  if(u > 0.0)
1291  {
1292  if(u > limit)
1293  {
1294  u = limit;
1295  }
1296  }
1297  else if(u < 0.0)
1298  {
1299  if(u < -limit)
1300  {
1301  u = -limit;
1302  }
1303  }
1304 
1305  integral += error*this->iTerm;
1306 
1307  if(integral > 10000.0)
1308  {
1309  integral = 10000.0;
1310  }
1311  else if(integral < -10000.0)
1312  {
1313  integral = -10000.0;
1314  }
1315 
1316  u += integral;
1317 
1318  if(u > 100000 || u < -100000)
1319  {
1320  uSat = 100000;
1321  uSat = ((u > 0) - (u < 0)) * uSat;
1322  }
1323  else
1324  {
1325  uSat = u;
1326  }
1327 
1328  if(error < -2.0 || error > 2.0)
1329  {
1330  if(error < 0.0)
1331  {
1332  if(error < -255.0)
1333  {
1334  this->pidError = 255;
1335  }
1336  else
1337  {
1338  this->pidError = (uint8_t)-error;
1339  }
1340  }
1341  else
1342  {
1343  if(error > 255.0)
1344  {
1345  this->pidError = 255;
1346  }
1347  else
1348  {
1349  this->pidError = (uint8_t)error;
1350  }
1351  }
1352  TCCR3B |= (1 << CS30);
1353  }
1354  else
1355  {
1356 
1357  if(this->state == STOP)
1358  {
1359  TCCR3B &= ~(1 << CS30);
1360  }
1361  this->pidError = 0;
1362  }
1363 
1364  if(uSat > 5.0)
1365  {
1366  temp = (uint32_t)((STEPGENERATORFREQUENCY/uSat) + 0.5);
1367  this->stepGeneratorDirection = CW;
1368 
1369  cli();
1370  pointer->stepDelay = temp;
1371  sei();
1372  }
1373  else if(uSat < -5.0)
1374  {
1375  this->stepGeneratorDirection = CCW;
1376 
1377  temp = (uint32_t)((STEPGENERATORFREQUENCY/-uSat) + 0.5);
1378  cli();
1379  pointer->stepDelay = temp;
1380  sei();
1381  }
1382  else if(uSat > 0.0)
1383  {
1384  this->stepGeneratorDirection = CW;
1385  cli();
1386  pointer->stepDelay = 20000;
1387  sei();
1388  }
1389  else if(uSat < 0.0)
1390  {
1391  this->stepGeneratorDirection = CCW;
1392 
1393  cli();
1394  pointer->stepDelay = 20000;
1395  sei();
1396  }
1397  else
1398  {
1399  this->stepGeneratorDirection = this->direction;
1400  cli();
1401  pointer->stepDelay = 20000;
1402  sei();
1403  }
1404 }
1405 
1407 {
1408  this->pidDisabled = 1;
1409 }
1410 
1412 {
1413  cli();
1414  this->pidDisabled = 0;
1415  this->pidTargetPosition = this->encoder.angleMoved * this->stepConversion;
1416  this->targetPosition = this->pidTargetPosition;
1417  this->state = STOP;
1418  this->pidError = 0;
1419  sei();
1420 }
1421 
1423 {
1424  return this->currentPidError;
1425 }
1426 
1427 void uStepperSLite::pidDropin(float error)
1428 {
1429  float u;
1430  float limit = abs(this->currentPidSpeed) + 6000.0;
1431  static float integral;
1432  static bool integralReset = 0;
1433 
1434  PORTD &= ~(1 << 4);
1435 
1436  this->currentPidError = error;
1437 
1438  u = error*this->pTerm;
1439 
1440  if(u > 0.0)
1441  {
1442  if(u > limit)
1443  {
1444  u = limit;
1445  }
1446  }
1447  else if(u < 0.0)
1448  {
1449  if(u < -limit)
1450  {
1451  u = -limit;
1452  }
1453  }
1454 
1455  integral += error*this->iTerm;
1456 
1457  if(integral > 10000.0)
1458  {
1459  integral = 10000.0;
1460  }
1461  else if(integral < -10000.0)
1462  {
1463  integral = -10000.0;
1464  }
1465 
1466  if(error > -10 && error < 10)
1467  {
1468  if(!integralReset)
1469  {
1470  integralReset = 1;
1471  integral = 0;
1472  }
1473  }
1474  else
1475  {
1476  integralReset = 0;
1477  }
1478 
1479  u += integral;
1480  u *= this->stepsPerSecondToRPM;
1481 
1482  this->driver.setVelocity(u);
1483 }
1484 
1486 {
1487  static float oldTargetPosition;
1488  static float oldEncoderPosition;
1489  static float encoderPositionChange;
1490  static float targetPositionChange;
1491  float encoderPosition = ((float)this->encoder.angleMoved*this->stepConversion);
1492  static float internalStall = 0.0;
1493 
1494  encoderPositionChange *= 0.99;
1495  encoderPositionChange += 0.01*(oldEncoderPosition - encoderPosition);
1496  oldEncoderPosition = encoderPosition;
1497 
1498  targetPositionChange *= 0.99;
1499  targetPositionChange += 0.01*(oldTargetPosition - this->pidTargetPosition);
1500  oldTargetPosition = this->pidTargetPosition;
1501 
1502  if(abs(encoderPositionChange) < abs(targetPositionChange)*0.5)
1503  {
1504  internalStall *= this->stallSensitivity;
1505  internalStall += 1.0-this->stallSensitivity;
1506  }
1507  else
1508  {
1509  internalStall *= this->stallSensitivity;
1510  }
1511 
1512  if(internalStall >= 0.95) //3 timeconstants
1513  {
1514  this->stall = 1;
1515  }
1516  else
1517  {
1518  this->stall = 0;
1519  }
1520 }
1521 
1522 bool uStepperSLite::isStalled(float stallSensitivity)
1523 {
1524  if(this->stallSensitivity > 1.0)
1525  {
1526  this->stallSensitivity = 1.0;
1527  }
1528  else if(this->stallSensitivity < 0.0)
1529  {
1530  this->stallSensitivity = 0.0;
1531  }
1532  else{
1533  this->stallSensitivity = stallSensitivity;
1534  }
1535 
1536  return this->stall;
1537 }
1538 
1540 {
1541  this->pTerm = P;
1542 }
1543 
1545 {
1546  this->iTerm = I * ENCODERINTSAMPLETIME;
1547 }
1548 
1550 {
1551  this->dTerm = D * ENCODERINTFREQ;
1552 }
1553 
1555 {
1556  this->invertPidDropinDirection = invert;
1557 }
1558 
1560 {
1561  uint8_t i = 0;
1562  String value;
1563 
1564  if(cmd->charAt(2) == ';')
1565  {
1566  Serial.println("COMMAND NOT ACCEPTED");
1567  return;
1568  }
1569 
1570  value.remove(0);
1571  /****************** SET P Parameter ***************************
1572  * *
1573  * *
1574  **************************************************************/
1575  if(cmd->substring(0,2) == String("P="))
1576  {
1577  for(i = 2;;i++)
1578  {
1579  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1580  {
1581  value.concat(cmd->charAt(i));
1582  }
1583  else if(cmd->charAt(i) == '.')
1584  {
1585  value.concat(cmd->charAt(i));
1586  i++;
1587  break;
1588  }
1589  else if(cmd->charAt(i) == ';')
1590  {
1591  break;
1592  }
1593  else
1594  {
1595  Serial.println("COMMAND NOT ACCEPTED");
1596  return;
1597  }
1598  }
1599 
1600  for(;;i++)
1601  {
1602  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1603  {
1604  value.concat(cmd->charAt(i));
1605  }
1606  else if(cmd->charAt(i) == ';')
1607  {
1608  Serial.print("COMMAND ACCEPTED. P = ");
1609  Serial.println(value.toFloat(),4);
1610  this->dropinSettings.P.f = value.toFloat();
1611  this->saveDropinSettings();
1612  this->setProportional(value.toFloat());
1613  return;
1614  }
1615  else
1616  {
1617  Serial.println("COMMAND NOT ACCEPTED");
1618  return;
1619  }
1620  }
1621  }
1622 
1623 /****************** SET I Parameter ***************************
1624  * *
1625  * *
1626  **************************************************************/
1627  else if(cmd->substring(0,2) == String("I="))
1628  {
1629  for(i = 2;;i++)
1630  {
1631  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1632  {
1633  value.concat(cmd->charAt(i));
1634  }
1635  else if(cmd->charAt(i) == '.')
1636  {
1637  value.concat(cmd->charAt(i));
1638  i++;
1639  break;
1640  }
1641  else if(cmd->charAt(i) == ';')
1642  {
1643  break;
1644  }
1645  else
1646  {
1647  Serial.println("COMMAND NOT ACCEPTED");
1648  return;
1649  }
1650  }
1651 
1652  for(;;i++)
1653  {
1654  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1655  {
1656  value.concat(cmd->charAt(i));
1657  }
1658  else if(cmd->charAt(i) == ';')
1659  {
1660  Serial.print("COMMAND ACCEPTED. I = ");
1661  Serial.println(value.toFloat(),4);
1662 
1663  this->dropinSettings.I.f = value.toFloat();
1664  this->saveDropinSettings();
1665  this->setIntegral(value.toFloat());
1666  return;
1667  }
1668  else
1669  {
1670  Serial.println("COMMAND NOT ACCEPTED");
1671  return;
1672  }
1673  }
1674  }
1675 
1676 /****************** SET D Parameter ***************************
1677  * *
1678  * *
1679  **************************************************************/
1680  else if(cmd->substring(0,2) == String("D="))
1681  {
1682  for(i = 2;;i++)
1683  {
1684  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1685  {
1686  value.concat(cmd->charAt(i));
1687  }
1688  else if(cmd->charAt(i) == '.')
1689  {
1690  value.concat(cmd->charAt(i));
1691  i++;
1692  break;
1693  }
1694  else if(cmd->charAt(i) == ';')
1695  {
1696  break;
1697  }
1698  else
1699  {
1700  Serial.println("COMMAND NOT ACCEPTED");
1701  return;
1702  }
1703  }
1704 
1705  for(;;i++)
1706  {
1707  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1708  {
1709  value.concat(cmd->charAt(i));
1710  }
1711  else if(cmd->charAt(i) == ';')
1712  {
1713  Serial.print("COMMAND ACCEPTED. D = ");
1714  Serial.println(value.toFloat(),4);
1715  this->dropinSettings.D.f = value.toFloat();
1716  this->saveDropinSettings();
1717  this->setDifferential(value.toFloat());
1718  return;
1719  }
1720  else
1721  {
1722  Serial.println("COMMAND NOT ACCEPTED");
1723  return;
1724  }
1725  }
1726  }
1727 
1728 /****************** invert Direction ***************************
1729  * *
1730  * *
1731  **************************************************************/
1732  else if(cmd->substring(0,6) == String("invert"))
1733  {
1734  if(cmd->charAt(6) != ';')
1735  {
1736  Serial.println("COMMAND NOT ACCEPTED");
1737  return;
1738  }
1739  if(this->invertPidDropinDirection)
1740  {
1741  Serial.println(F("Direction normal!"));
1742  this->dropinSettings.invert = 0;
1743  this->saveDropinSettings();
1744  this->invertDropinDir(0);
1745  return;
1746  }
1747  else
1748  {
1749  Serial.println(F("Direction inverted!"));
1750  this->dropinSettings.invert = 1;
1751  this->saveDropinSettings();
1752  this->invertDropinDir(1);
1753  return;
1754  }
1755  }
1756 
1757  /****************** get Current Pid Error ********************
1758  * *
1759  * *
1760  **************************************************************/
1761  else if(cmd->substring(0,5) == String("error"))
1762  {
1763  if(cmd->charAt(5) != ';')
1764  {
1765  Serial.println("COMMAND NOT ACCEPTED");
1766  return;
1767  }
1768  Serial.print(F("Current Error: "));
1769  Serial.print(this->getPidError());
1770  Serial.println(F(" Steps"));
1771  }
1772 
1773  /****************** Get run/hold current settings ************
1774  * *
1775  * *
1776  **************************************************************/
1777  else if(cmd->substring(0,7) == String("current"))
1778  {
1779  if(cmd->charAt(7) != ';')
1780  {
1781  Serial.println("COMMAND NOT ACCEPTED");
1782  return;
1783  }
1784  Serial.print(F("Run Current: "));
1785  Serial.print(this->driver.getRunCurrent());
1786  Serial.println(F(" %"));
1787  Serial.print(F("Hold Current: "));
1788  Serial.print(this->driver.getHoldCurrent());
1789  Serial.println(F(" %"));
1790  }
1791 
1792  /****************** Get PID Parameters ***********************
1793  * *
1794  * *
1795  **************************************************************/
1796  else if(cmd->substring(0,10) == String("parameters"))
1797  {
1798  if(cmd->charAt(10) != ';')
1799  {
1800  Serial.println("COMMAND NOT ACCEPTED");
1801  return;
1802  }
1803  Serial.print(F("P: "));
1804  Serial.print(this->dropinSettings.P.f,4);
1805  Serial.print(F(", "));
1806  Serial.print(F("I: "));
1807  Serial.print(this->dropinSettings.I.f,4);
1808  Serial.print(F(", "));
1809  Serial.print(F("D: "));
1810  Serial.println(this->dropinSettings.D.f,4);
1811  }
1812 
1813  /****************** Help menu ********************************
1814  * *
1815  * *
1816  **************************************************************/
1817  else if(cmd->substring(0,4) == String("help"))
1818  {
1819  if(cmd->charAt(4) != ';')
1820  {
1821  Serial.println("COMMAND NOT ACCEPTED");
1822  return;
1823  }
1824  this->dropinPrintHelp();
1825  }
1826 
1827 /****************** SET run current ***************************
1828  * *
1829  * *
1830  **************************************************************/
1831  else if(cmd->substring(0,11) == String("runCurrent="))
1832  {
1833  for(i = 11;;i++)
1834  {
1835  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1836  {
1837  value.concat(cmd->charAt(i));
1838  }
1839  else if(cmd->charAt(i) == '.')
1840  {
1841  value.concat(cmd->charAt(i));
1842  i++;
1843  break;
1844  }
1845  else if(cmd->charAt(i) == ';')
1846  {
1847  break;
1848  }
1849  else
1850  {
1851  Serial.println("COMMAND NOT ACCEPTED");
1852  return;
1853  }
1854  }
1855 
1856  for(;;i++)
1857  {
1858  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1859  {
1860  value.concat(cmd->charAt(i));
1861  }
1862  else if(cmd->charAt(i) == ';')
1863  {
1864  if(value.toFloat() >= 0.0 && value.toFloat() <= 100.0)
1865  {
1866  i = (uint8_t)value.toFloat();
1867  break;
1868  }
1869  else
1870  {
1871  Serial.println("COMMAND NOT ACCEPTED");
1872  return;
1873  }
1874  }
1875  else
1876  {
1877  Serial.println("COMMAND NOT ACCEPTED");
1878  return;
1879  }
1880  }
1881 
1882  Serial.print("COMMAND ACCEPTED. runCurrent = ");
1883  Serial.print(i);
1884  Serial.println(F(" %"));
1885  this->dropinSettings.runCurrent = i;
1886  this->saveDropinSettings();
1887  this->driver.setRunCurrent(i);
1888  }
1889 
1890  /****************** SET run current ***************************
1891  * *
1892  * *
1893  **************************************************************/
1894  else if(cmd->substring(0,12) == String("holdCurrent="))
1895  {
1896  for(i = 12;;i++)
1897  {
1898  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1899  {
1900  value.concat(cmd->charAt(i));
1901  }
1902  else if(cmd->charAt(i) == '.')
1903  {
1904  value.concat(cmd->charAt(i));
1905  i++;
1906  break;
1907  }
1908  else if(cmd->charAt(i) == ';')
1909  {
1910  break;
1911  }
1912  else
1913  {
1914  Serial.println(F("COMMAND NOT ACCEPTED"));
1915  return;
1916  }
1917  }
1918 
1919  for(;;i++)
1920  {
1921  if(cmd->charAt(i) >= '0' && cmd->charAt(i) <= '9')
1922  {
1923  value.concat(cmd->charAt(i));
1924  }
1925  else if(cmd->charAt(i) == ';')
1926  {
1927  if(value.toFloat() >= 0.0 && value.toFloat() <= 100.0)
1928  {
1929  i = (uint8_t)value.toFloat();
1930  break;
1931  }
1932  else
1933  {
1934  Serial.println(F("COMMAND NOT ACCEPTED"));
1935  return;
1936  }
1937  }
1938  else
1939  {
1940  Serial.println(F("COMMAND NOT ACCEPTED"));
1941  return;
1942  }
1943  }
1944 
1945  Serial.print(F("COMMAND ACCEPTED. holdCurrent = "));
1946  Serial.print(i);
1947  Serial.println(F(" %"));
1948  this->dropinSettings.holdCurrent = i;
1949  this->saveDropinSettings();
1950  this->driver.setHoldCurrent(i);
1951  }
1952 
1953  /****************** DEFAULT (Reject!) ************************
1954  * *
1955  * *
1956  **************************************************************/
1957  else
1958  {
1959  Serial.println(F("COMMAND NOT ACCEPTED"));
1960  return;
1961  }
1962 
1963 }
1964 
1966 {
1967  static String stringInput;
1968  static uint32_t t = millis();
1969 
1970  while(1)
1971  {
1972  while(!Serial.available())
1973  {
1974  delay(1);
1975  if((millis() - t) >= 500)
1976  {
1977  stringInput.remove(0);
1978  t = millis();
1979  }
1980  }
1981  t = millis();
1982  stringInput += (char)Serial.read();
1983  if(stringInput.lastIndexOf(';') > -1)
1984  {
1985  this->parseCommand(&stringInput);
1986  stringInput.remove(0);
1987  }
1988  }
1989 }
1990 
1992 {
1993  Serial.println(F("uStepper S-lite Dropin !"));
1994  Serial.println(F(""));
1995  Serial.println(F("Usage:"));
1996  Serial.println(F("Show this command list: 'help;'"));
1997  Serial.println(F("Get PID Parameters: 'parameters;'"));
1998  Serial.println(F("Set Proportional constant: 'P=10.002;'"));
1999  Serial.println(F("Set Integral constant: 'I=10.002;'"));
2000  Serial.println(F("Set Differential constant: 'D=10.002;'"));
2001  Serial.println(F("Invert Direction: 'invert;'"));
2002  Serial.println(F("Get Current PID Error: 'error;'"));
2003  Serial.println(F("Get Run/Hold Current Settings: 'current;'"));
2004  Serial.println(F("Set Run Current (percent): 'runCurrent=50.0;'"));
2005  Serial.println(F("Set Hold Current (percent): 'holdCurrent=50.0;'"));
2006  Serial.println(F(""));
2007  Serial.println(F(""));
2008 }
2009 
2011 {
2012  dropinCliSettings_t tempSettings;
2013 
2014  EEPROM.get(0,tempSettings);
2015 
2016  if(this->dropinSettingsCalcChecksum(&tempSettings) != tempSettings.checksum)
2017  {
2018  return 0;
2019  }
2020 
2021  this->dropinSettings = tempSettings;
2022  this->setProportional(this->dropinSettings.P.f);
2023  this->setIntegral(this->dropinSettings.I.f);
2024  this->setDifferential(this->dropinSettings.D.f);
2025  this->invertDropinDir((bool)this->dropinSettings.invert);
2026  this->setCurrent(this->dropinSettings.runCurrent,this->dropinSettings.holdCurrent);
2027  return 1;
2028 }
2029 
2031 {
2033 
2034  EEPROM.put(0,this->dropinSettings);
2035 }
2036 
2038 {
2039  uint8_t i;
2040  uint8_t checksum = 0xAA;
2041  uint8_t *p = (uint8_t*)settings;
2042 
2043  for(i=0; i < 15; i++)
2044  {
2045  checksum ^= *p++;
2046  }
2047 
2048  return checksum;
2049 }
uStepperSLite::currentPidAcceleration
volatile float currentPidAcceleration
Definition: uStepperSLite.h:552
I2CFREE
#define I2CFREE
Definition: i2cMaster.h:43
uStepperSLite::velocity
float velocity
Definition: uStepperSLite.h:489
dropinCliSettings_t::P
floatBytes_t P
Definition: uStepperSLite.h:156
uStepperSLite::stepsPerSecondToRPM
float stepsPerSecondToRPM
Definition: uStepperSLite.h:508
uStepperEncoder::angle
volatile uint16_t angle
Definition: uStepperSLite.h:320
uStepperSLite
Prototype of class for accessing all features of the uStepper S-lite in a single object.
Definition: uStepperSLite.h:438
Tmc2208::invertDirection
void invertDirection(bool normal=INVERSEDIRECTION)
Invert motor direction.
Definition: TMC2208.cpp:133
uStepperSLite::encoder
uStepperEncoder encoder
Definition: uStepperSLite.h:628
uStepperSLite::acceleration
float acceleration
Definition: uStepperSLite.h:497
Tmc2208::setCurrent
void setCurrent(uint8_t runPercent, uint8_t holdPercent)
Change run and hold current settings of the stepper motor driver - TMC2208.
Definition: TMC2208.cpp:196
uStepperSLite::cruiseToDecelThreshold
volatile int32_t cruiseToDecelThreshold
Definition: uStepperSLite.h:546
uStepperSLite::RPMToStepsPerSecond
float RPMToStepsPerSecond
Definition: uStepperSLite.h:511
uStepperSLite::isStalled
bool isStalled(float stallSensitivity=0.992)
This method returns a bool variable indicating wether the motor is stalled or not.
Definition: uStepperSLite.cpp:1522
uStepperSLite::runContinous
void runContinous(bool dir)
Make the motor rotate continuously.
Definition: uStepperSLite.cpp:584
uStepperSLite::invertDropinDir
void invertDropinDir(bool invert)
This method is used to invert the drop-in direction pin interpretation.
Definition: uStepperSLite.cpp:1554
uStepperSLite::accelToCruiseThreshold
volatile int32_t accelToCruiseThreshold
Definition: uStepperSLite.h:543
uStepperEncoder::angleMoved
volatile int32_t angleMoved
Definition: uStepperSLite.h:308
Tmc2208::setVelocity
void setVelocity(float RPM)
Set motor velocity in RPM.
Definition: TMC2208.cpp:228
i2cMaster::read
bool read(uint8_t slaveAddr, uint8_t regAddr, uint8_t numOfBytes, uint8_t *data)
sets up I2C connection to device, reads a number of data bytes and closes the connection
Definition: i2cMaster.cpp:61
dropinCliSettings_t
Struct to store dropin settings.
Definition: uStepperSLite.h:155
uStepperEncoder::oldAngle
volatile uint16_t oldAngle
Definition: uStepperSLite.h:316
uStepperSLite::invertPidDropinDirection
bool invertPidDropinDirection
Definition: uStepperSLite.h:636
uStepperSLite::stepConversion
volatile float stepConversion
Definition: uStepperSLite.h:501
Tmc2208::setup
void setup(void)
Initializes the different parts of the TMC2208 object.
Definition: TMC2208.cpp:114
uStepperSLite::dropinPrintHelp
void dropinPrintHelp()
This method is used to print the dropinCli menu explainer:
Definition: uStepperSLite.cpp:1991
uStepperSLite::enableMotor
void enableMotor(void)
Enables the stepper driver output stage.
Definition: uStepperSLite.cpp:1138
uStepperSLite::stallSensitivity
float stallSensitivity
Definition: uStepperSLite.h:520
uStepperSLite::pTerm
float pTerm
Definition: uStepperSLite.h:505
dropinCliSettings_t::D
floatBytes_t D
Definition: uStepperSLite.h:158
uStepperSLite::targetPosition
volatile int32_t targetPosition
Definition: uStepperSLite.h:558
i2cMaster::begin
void begin(void)
Setup TWI (I2C) interface.
Definition: i2cMaster.cpp:221
uStepperSLite::pidError
volatile uint8_t pidError
Definition: uStepperSLite.h:468
uStepperSLite::stepDelay
volatile uint32_t stepDelay
Definition: uStepperSLite.h:453
uStepperSLite::stepGeneratorDirection
volatile uint8_t stepGeneratorDirection
Definition: uStepperSLite.h:456
uStepperSLite::continous
bool continous
Definition: uStepperSLite.h:465
Tmc2208::setHoldCurrent
void setHoldCurrent(uint8_t holdPercent)
Change hold current setting of the stepper motor driver - TMC2208.
Definition: TMC2208.cpp:215
uStepperEncoder::getAngle
float getAngle(void)
Measure the current shaft angle.
Definition: uStepperSLite.cpp:469
uStepperSLite::dropinSettingsCalcChecksum
uint8_t dropinSettingsCalcChecksum(dropinCliSettings_t *settings)
This method is used internally for stall detection.
Definition: uStepperSLite.cpp:2037
uStepperSLite::RPMToStepDelay
volatile float RPMToStepDelay
Definition: uStepperSLite.h:536
i2cMaster::getStatus
uint8_t getStatus(void)
Get current I2C status.
Definition: i2cMaster.cpp:216
uStepperSLite::setDifferential
void setDifferential(float D)
This method is used to change the PID differential parameter D.
Definition: uStepperSLite.cpp:1549
uStepperSLite::driver
Tmc2208 driver
Definition: uStepperSLite.h:631
uStepperSLite::brake
bool brake
Definition: uStepperSLite.h:564
dropinCliSettings_t::checksum
uint8_t checksum
Definition: uStepperSLite.h:162
uStepperSLite::enablePid
void enablePid(void)
This method enables the PID after being disabled (disablePid).
Definition: uStepperSLite.cpp:1411
uStepperSLite::setMaxAcceleration
void setMaxAcceleration(float accel)
Set the maximum acceleration of the stepper motor.
Definition: uStepperSLite.cpp:534
uStepperSLite::moveAngle
void moveAngle(float angle, bool holdMode=BRAKEON)
Moves the motor to a relative angle.
Definition: uStepperSLite.cpp:1241
uStepperSLite::currentPidSpeed
volatile float currentPidSpeed
Definition: uStepperSLite.h:549
uStepperSLite::getPidError
float getPidError(void)
This method returns the current PID error.
Definition: uStepperSLite.cpp:1422
Tmc2208::disableDriver
void disableDriver(void)
Disable the stepper motor driver - TMC2208.
Definition: TMC2208.cpp:155
uStepperEncoder::getAngleMoved
float getAngleMoved(void)
Measure the angle moved from reference position.
Definition: uStepperSLite.cpp:424
uStepperEncoder::getSpeed
float getSpeed(bool unit=SPS)
Measure the current speed of the motor.
Definition: uStepperSLite.cpp:429
floatBytes_t::f
float f
Definition: uStepperSLite.h:142
uStepperSLite::decelToAccelThreshold
volatile int32_t decelToAccelThreshold
Definition: uStepperSLite.h:540
dropinCliSettings_t::invert
uint8_t invert
Definition: uStepperSLite.h:159
Tmc2208::enableDriver
void enableDriver(void)
Enable the stepper motor driver - TMC2208.
Definition: TMC2208.cpp:150
uStepperSLite::detectStall
bool detectStall(void)
This method is used internally for stall detection.
Definition: uStepperSLite.cpp:1485
uStepperSLite::stop
void stop(bool brake=BRAKEON)
Stop the motor with deceleration.
Definition: uStepperSLite.cpp:898
uStepperSLite::getMotorState
uint8_t getMotorState(void)
Get the current state of the motor.
Definition: uStepperSLite.cpp:1153
uStepperSLite::getCurrentDirection
bool getCurrentDirection(void)
Returns the direction the motor is currently configured to rotate.
Definition: uStepperSLite.cpp:1148
uStepperSLite::state
volatile uint8_t state
Definition: uStepperSLite.h:473
uStepperSLite::hardStop
void hardStop(bool holdMode=BRAKEON)
Stop the motor without deceleration.
Definition: uStepperSLite.cpp:873
dropinCliSettings_t::I
floatBytes_t I
Definition: uStepperSLite.h:157
uStepperSLite::angleToStep
float angleToStep
Definition: uStepperSLite.h:524
uStepperEncoder::curSpeed
volatile float curSpeed
Definition: uStepperSLite.h:324
uStepperSLite::moveToEnd
float moveToEnd(bool dir, float stallSensitivity=0.992)
Moves the motor to its physical limit, without limit switch.
Definition: uStepperSLite.cpp:1184
uStepperEncoder::detectMagnet
uint8_t detectMagnet(void)
Detect if magnet is present and within range.
Definition: uStepperSLite.cpp:494
uStepperSLite::mode
uint8_t mode
Definition: uStepperSLite.h:477
dropinCliSettings_t::holdCurrent
uint8_t holdCurrent
Definition: uStepperSLite.h:160
Tmc2208::setRunCurrent
void setRunCurrent(uint8_t runPercent)
Change run current setting of the stepper motor driver - TMC2208.
Definition: TMC2208.cpp:202
uStepperEncoder::uStepperEncoder
uStepperEncoder(void)
Constructor.
Definition: uStepperSLite.cpp:419
uStepperSLite::iTerm
float iTerm
Definition: uStepperSLite.h:514
uStepperSLite::setIntegral
void setIntegral(float I)
This method is used to change the PID integral parameter I.
Definition: uStepperSLite.cpp:1544
uStepperSLite::checkConnectorOrientation
void checkConnectorOrientation(uint8_t mode)
This method handles the connector orientation check in order to automatically compensate the PID for ...
Definition: uStepperSLite.cpp:949
uStepperSLite::direction
volatile uint8_t direction
Definition: uStepperSLite.h:484
dropinCliSettings_t::runCurrent
uint8_t runCurrent
Definition: uStepperSLite.h:161
uStepperSLite::stepCnt
volatile int32_t stepCnt
Definition: uStepperSLite.h:481
uStepperSLite::currentPidError
volatile float currentPidError
Definition: uStepperSLite.h:620
uStepperSLite::setProportional
void setProportional(float P)
This method is used to change the PID proportional parameter P.
Definition: uStepperSLite.cpp:1539
uStepperEncoder::setup
void setup(void)
Setup the encoder.
Definition: uStepperSLite.cpp:441
i2cMaster
Prototype of class for accessing the TWI (I2C) interface of the AVR (master mode only).
Definition: i2cMaster.h:94
uStepperSLite::loadDropinSettings
bool loadDropinSettings(void)
This method loads the dropin settings stored in EEPROM.
Definition: uStepperSLite.cpp:2010
uStepperSLite::getStepsSinceReset
int32_t getStepsSinceReset(void)
Get the number of steps applied since reset.
Definition: uStepperSLite.cpp:1163
uStepperSLite::pidDropin
void pidDropin(float error)
This method handles the actual PID Drop-in controller calculations, if enabled.
Definition: uStepperSLite.cpp:1427
uStepperSLite::setHoldCurrent
void setHoldCurrent(uint8_t holdCurrent)
Set motor hold current.
Definition: uStepperSLite.cpp:1173
uStepperEncoder::setHome
void setHome(void)
Define new reference(home) position.
Definition: uStepperSLite.cpp:451
uStepperSLite::pid
void pid(float error)
This method handles the actual PID controller calculations, if enabled.
Definition: uStepperSLite.cpp:1257
uStepperSLite::moveSteps
void moveSteps(int32_t steps, bool dir, bool holdMode=BRAKEON)
Make the motor perform a predefined number of steps.
Definition: uStepperSLite.cpp:682
uStepperSLite::decelToStopThreshold
volatile int32_t decelToStopThreshold
Definition: uStepperSLite.h:460
uStepperSLite::setRunCurrent
void setRunCurrent(uint8_t runCurrent)
Set motor run current.
Definition: uStepperSLite.cpp:1178
uStepperSLite::dropinSettings
dropinCliSettings_t dropinSettings
Definition: uStepperSLite.h:1037
uStepperSLite::dTerm
float dTerm
Definition: uStepperSLite.h:517
uStepperEncoder::getAgc
uint8_t getAgc(void)
Read the current AGC value of the encoder chip.
Definition: uStepperSLite.cpp:485
uStepperEncoder::getStrength
uint16_t getStrength(void)
Measure the strength of the magnet.
Definition: uStepperSLite.cpp:474
uStepperSLite::stepsSinceReset
volatile int32_t stepsSinceReset
Definition: uStepperSLite.h:446
uStepperEncoder::encoderOffset
uint16_t encoderOffset
Definition: uStepperSLite.h:311
uStepperServo::angle
uint8_t angle
Definition: uStepperServo.h:50
uStepperSLite::setMaxVelocity
void setMaxVelocity(float vel)
Sets the maximum rotational velocity of the motor.
Definition: uStepperSLite.cpp:551
uStepperSLite::setup
void setup(uint8_t mode=NORMAL, float stepsPerRevolution=3200.0, float pTerm=0.75, float iTerm=3.0, float dTerm=0.0, bool setHome=true, uint8_t invert=0, uint8_t runCurrent=50, uint8_t holdCurrent=30)
Initializes the different parts of the uStepper S-lite object.
Definition: uStepperSLite.cpp:1020
uStepperSLite::uStepperSLite
uStepperSLite(float accel=1000.0, float vel=1000.0)
Constructor of uStepper S-lite class.
Definition: uStepperSLite.cpp:520
uStepperSLite::parseCommand
void parseCommand(String *cmd)
This method is used for the dropinCli to take in user commands.
Definition: uStepperSLite.cpp:1559
uStepperSLite::softStop
void softStop(bool holdMode=BRAKEON)
Stop the motor with deceleration.
Definition: uStepperSLite.cpp:903
uStepperSLite::stall
volatile bool stall
Definition: uStepperSLite.h:532
uStepperSLite::disablePid
void disablePid(void)
This method disables the PID until calling enablePid.
Definition: uStepperSLite.cpp:1406
uStepperSLite::moveToAngle
void moveToAngle(float angle, bool holdMode=BRAKEON)
Moves the motor to an absolute angle.
Definition: uStepperSLite.cpp:1223
uStepperSLite::saveDropinSettings
void saveDropinSettings(void)
This method stores the current dropin settings in EEPROM.
Definition: uStepperSLite.cpp:2030
uStepperSLite::dropinCli
void dropinCli()
This method is used to tune Drop-in parameters. After tuning uStepper S-lite the parameters are saved...
Definition: uStepperSLite.cpp:1965
uStepperSLite::stepToAngle
float stepToAngle
Definition: uStepperSLite.h:528
uStepperSLite::setCurrent
void setCurrent(uint8_t runCurrent, uint8_t holdCurrent=25)
Set motor run and hold current.
Definition: uStepperSLite.cpp:1168
uStepperSLite::disableMotor
void disableMotor(void)
Disables the stepper driver output stage.
Definition: uStepperSLite.cpp:1143
uStepperSLite::pidTargetPosition
volatile float pidTargetPosition
Definition: uStepperSLite.h:625
I2C
i2cMaster I2C(1)
uStepperSLite::pidDisabled
volatile bool pidDisabled
Definition: uStepperSLite.h:561