egoShield
egoShieldS.cpp
Go to the documentation of this file.
1 /********************************************************************************************
2 * File: egoShieldTimeLapse.cpp *
3 * Version: 1.1.0 *
4 * Date: April 1st, 2020 *
5 * Author: Mogens Groth Nicolaisen *
6 * *
7 *********************************************************************************************
8 * (C) 2020 *
9 * *
10 * uStepper ApS *
11 * www.ustepper.com *
12 * administration@ustepper.com *
13 * *
14 * The code contained in this file is released under the following open source license: *
15 * *
16 * Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International *
17 * *
18 * The code in this file is provided without warranty of any kind - use at own risk! *
19 * neither uStepper ApS nor the author, can be held responsible for any damage *
20 * caused by the use of the code contained in this file ! *
21 * *
22 ********************************************************************************************/
33 #include "egoShieldS.h"
34 #include "screen.h"
35 egoShield *egoPointer;
36 
37 extern "C" {
38  void TIMER4_COMPA_vect(void)
39  {
40  uint8_t temp = TCCR3B, temp1 = TCCR1B;
41  TCCR3B &= ~(1 << CS30);
42  TCCR1B &= ~(1 << CS10);
43  egoPointer->inputs();
44  TCCR3B = temp;
45  TCCR1B = temp1;
46  }
47 }
48 
50 {
51 }
52 
53 void egoShield::setup(uint16_t acc, uint16_t vel, float P, float I, float D, float res, int8_t stallsens, uint16_t shutterDelay)//brake mode?
54 {
55  #ifdef ARDUINO_AVR_USTEPPER_S
56  this->screen = new Screen(1);
57  #endif
58 
59  #ifdef ARDUINO_AVR_USTEPPER_S_LITE
60  this->screen = new Screen(0);
61  #endif
62 
63 
64  this->screen->init();
65  egoPointer = this;
66 
67 
68  this->acceleration = acc;
69  this->velocity = vel;
70  this->pTerm = P;
71  this->iTerm = I;
72  this->dTerm = D;
73  this->resolution = res;
74  this->stepSize = 2;
75  this->interval = 2000;
76  this->stallSensitivity=stallsens;
77  this->shutterDelay = shutterDelay;
78  DRAWPAGE(this->startPage());//show startpage
79 
80  brakeFlag = 1;
81 
82  #ifdef ARDUINO_AVR_USTEPPER_S
83  stepper.setMaxVelocity(this->velocity/16.0);
84  #else
85  stepper.setMaxVelocity(this->velocity);
86  #endif
87  stepper.setMaxAcceleration(this->acceleration);
88 
89  #ifdef ARDUINO_AVR_USTEPPER_S
90  stepper.setup(PID,200);
91  stepper.checkOrientation(10.0);
92  #else
93  stepper.setup(PID,3200.0,pTerm,iTerm,dTerm);
94  #endif
95 
96  if(this->stallSensitivity!=100)
97  {
98  #ifdef ARDUINO_AVR_USTEPPER_S
99  stepper.moveToEnd(CCW,vel*0.019,this->stallSensitivity);
100  #else
101  stepper.moveToEnd(CCW, map(stallsens, -64, 63, 0.0, 1.0));
102  #endif
103  }
104  stepper.encoder.setHome();
105 
106  pinMode(FWBT ,INPUT);
107  pinMode(PLBT ,INPUT);
108  pinMode(RECBT ,INPUT);
109  pinMode(BWBT ,INPUT);
110  pinMode(OPTO,OUTPUT);
111  digitalWrite(OPTO ,HIGH);
112  digitalWrite(FWBT ,HIGH);//pull-up
113  digitalWrite(PLBT ,HIGH);//pull-up
114  digitalWrite(RECBT ,HIGH);//pull-up
115  digitalWrite(BWBT ,HIGH);//pull-up
116 
117  this->resetAllButton();
118  state = 'a';//start in idle
119  stepper.disablePid();
120  stepper.stop();
121  stepper.encoder.setHome();
122  delay(1000);
123  if(this->stallSensitivity!=100)
124  {
125  stepper.moveAngle(30);
126  while(stepper.getMotorState());
127  }
128  stepper.encoder.setHome();
129 
130  setPoint = stepper.encoder.getAngleMoved();//set manual move setpoint to current position
131  TCNT4 = 0;
132  ICR4 = 35000;
133  TIFR4 = 0;
134  TIMSK4 = (1 << OCIE4A);
135  TCCR4A = (1 << WGM41);
136  TCCR4B = (1 << WGM42) | (1 << WGM43) | ( 1 << CS41);
137 }
138 
139 void egoShieldTimeLapse::loop(void)
140 {
141  setPoint = stepper.encoder.getAngleMoved();
142 
143  switch (state)
144  {
145  case 'a'://if we are in idle
146  idleMode();
147  break;
148 
149  case 'b'://if we are in play
150  state = 'a';
151  break;
152 
153  case 'c'://if we are in record
154  timeMode();
155  break;
156 
157  case 'd'://in pause
158  pauseMode();
159  break;
160  }
161 }
162 
163 void egoShieldTeach::loop(void)
164 {
165  setPoint = stepper.encoder.getAngleMoved();
166  switch (state)
167  {
168  case 'a'://if we are in idle
169  idleMode();
170  break;
171 
172  case 'b'://if we are in play
173  playMode();
174  break;
175 
176  case 'c'://if we are in record
177  recordMode();
178  break;
179 
180  case 'd'://in pause
181  pauseMode();
182  break;
183  }
184 }
185 
187 {
188  static bool continousForward = 0;
189  static bool continousBackwards = 0;
190 
191  DRAWPAGE(this->recordPage(pidFlag,0,place,setPoint));
192 
193  if(continousForward)
194  {
195  if(this->forwardBtn.state != HOLD)
196  {
197  stepper.stop();
198  this->resetAllButton();
199  continousForward = 0;
200  }
201  }
202  else if(continousBackwards)
203  {
204  if(this->backwardsBtn.state != HOLD)
205  {
206  stepper.stop();
207  this->resetAllButton();
208  continousBackwards = 0;
209  }
210  }
211  if(this->forwardBtn.btn)//if manual forward signal
212  {
213  if(this->forwardBtn.state == HOLD)
214  {
215  if(!continousForward)
216  {
217  stepper.runContinous(CCW);
218  continousForward = 1;
219  }
220  this->forwardBtn.btn = 0;
221  }
222  else
223  {
224  stepper.moveAngle(-5.0);//move 5deg
225  this->forwardBtn.btn = 0;
226  }
227  }
228  else if(this->backwardsBtn.btn)//if manual backward signal
229  {
230  if(this->backwardsBtn.state == HOLD)
231  {
232  if(!continousBackwards)
233  {
234  stepper.runContinous(CW);
235  continousBackwards = 1;
236  }
237  this->backwardsBtn.btn = 0;
238  }
239  else
240  {
241  stepper.moveAngle(5.0);//move 5deg
242  this->backwardsBtn.btn = 0;
243  }
244  }
245  else if(this->recordBtn.btn == 1)//record position
246  {
247  this->recordBtn.btn = 0;
248  if(record == 0)//If we were not recording before
249  {
250  place = 0;//Reset the array counter
251  record = 1;//Record flag
252  }
253  DRAWPAGE(this->recordPage(pidFlag,1,place,setPoint));
254  delay(500);
255  if(record == 1)//If we have initialized recording
256  {
257  pos[place] = setPoint;//Save current position
258  place++;//Increment array counter
259  if(place>CNT)
260  {
261  place=0;
262  }
263  }
264  }
265  else if(this->playBtn.btn == 1)//stop pressed
266  {
267  endmove = place-1;//set the endmove to the current position
268  place = 0;//reset array counter
269  record = 0;//reset record flag
270  state = 'a';//stop state
271  continousForward = 0;
272  continousBackwards = 0;
273  stepper.moveToAngle(pos[0]);
274  do
275  {
276  DRAWPAGE(this->idlePage(pidFlag,setPoint));
277  }
278  while(this->playBtn.state == HOLD);
279  this->resetAllButton();
280  }
281 }
282 
284 {
285  static bool continousForward = 0;
286  static bool continousBackwards = 0;
287 
288  DRAWPAGE(this->idlePage(pidFlag,setPoint));
289  if(continousForward)
290  {
291  if(this->forwardBtn.state != HOLD)
292  {
293  stepper.stop();
294  this->resetAllButton();
295  continousForward = 0;
296  stepper.moveAngle(0.01);
297  }
298  }
299  else if(continousBackwards)
300  {
301  if(this->backwardsBtn.state != HOLD)
302  {
303  stepper.stop();
304  this->resetAllButton();
305  continousBackwards = 0;
306  stepper.moveAngle(-0.01);
307  }
308  }
309  if(this->playBtn.btn)//if play/stop/pause is pressed for long time, invert the pid mode
310  {
311  while(this->playBtn.state == PRESSED);
312  if(this->playBtn.state == DEPRESSED)//we want to play sequence when doing a short press
313  {
314  state = 'b';
315  continousForward = 0;
316  continousBackwards = 0;
317  this->resetAllButton();
318  }
319  else
320  {
321  stepper.stop();
322  if(pidFlag == 0)
323  {
324  pidFlag = 1;
325  stepper.enablePid();
326  stepper.moveAngle(0.01);
327  }
328  else
329  {
330  pidFlag = 0;
331  stepper.disablePid();
332  stepper.stop();
333  }
334  DRAWPAGE(this->idlePage(pidFlag,setPoint));
335  while(this->playBtn.state == HOLD);
336  }
337  this->resetButton(&playBtn);
338  }
339  else if(this->forwardBtn.btn)//if manual forward signal
340  {
341  if(this->forwardBtn.state == HOLD)
342  {
343  if(!continousForward)
344  {
345  stepper.runContinous(CCW);
346  continousForward = 1;
347  }
348  this->forwardBtn.btn = 0;
349  }
350  else
351  {
352  stepper.moveAngle(-5.0);//move 5deg
353  this->forwardBtn.btn = 0;
354  }
355  }
356  else if(this->backwardsBtn.btn)//if manual backward signal
357  {
358  if(this->backwardsBtn.state == HOLD)
359  {
360  if(!continousBackwards)
361  {
362  stepper.runContinous(CW);
363  continousBackwards = 1;
364  }
365  this->backwardsBtn.btn = 0;
366  }
367  else
368  {
369  stepper.moveAngle(5.0);//move 5deg
370  this->backwardsBtn.btn = 0;
371  }
372  }
373  else if(this->recordBtn.btn == 1)
374  {
375  this->resetAllButton();
376  continousForward = 0;
377  continousBackwards = 0;
378  state = 'c';
379  }
380 }
381 
383 {
384  static uint8_t started = 0;
385  static bool lastMove = 0;
386 
387  DRAWPAGE(this->playPage(loopMode,pidFlag,place,0));
388 
389  if(this->recordBtn.btn)//play/stop/pause
390  {
391  while(this->recordBtn.state == PRESSED);
392  if(this->recordBtn.state == DEPRESSED)//we want to play sequence when doing a short press
393  {
394  state = 'd';
395  this->resetAllButton();
396  return;
397  }
398  else //Long press = stop
399  {
400  this->resetAllButton();
401  this->changeVelocity();
402  }
403  }
404  else if(this->playBtn.btn)//play/stop/pause
405  {
406  while(this->playBtn.state == PRESSED);
407  if(this->playBtn.state == DEPRESSED)//we want to play sequence when doing a short press
408  {
409  started = 1;
410  }
411  else //Long press = stop
412  {
413  place = 0;//reset array counter
414  loopMode = 0;
415  lastMove = 0;
416  started = 0;
417  state = 'a';//idle
418  stepper.moveToAngle(pos[0]);
419  do
420  {
421  DRAWPAGE(this->idlePage(pidFlag,setPoint));
422  }
423  while(this->playBtn.state == HOLD);
424  }
425  this->resetAllButton();
426  return;
427  }
428  else if(started || loopMode)
429  {
430  #ifdef ARDUINO_AVR_USTEPPER_S
431  if(!stepper.driver.readRegister(VACTUAL))
432  #else
433  if(!stepper.getMotorState())
434  #endif
435  {
436  place++;//increment array counter
437  if(lastMove && loopMode)
438  {
439  lastMove = 0;
440  }
441  if(loopMode && place > endmove)
442  {
443  place = 0;
444  lastMove = 1;
445  }
446  else if(place > endmove)//If we are at the end move
447  {
448  place = 0;//reset array counter
449  lastMove = 1;
450  }
451  else if(lastMove)//If we are at the end move
452  {
453  place = 0;//reset array counter
454  started = 0;
455  lastMove = 0;
456  state = 'a';
457  this->resetAllButton();
458  return;
459  }
460  stepper.moveToAngle(pos[place]);
461  }
462  }
463 
464  if(this->forwardBtn.state == HOLD)//loop mode start
465  {
466  this->resetButton(&forwardBtn);
467  loopMode = 1;
468  }
469  else if(this->backwardsBtn.state == HOLD)//loop mode stop
470  {
471  this->resetButton(&backwardsBtn);
472  loopMode = 0;
473  }
474 }
475 
477 {
478  for(;;)
479  {
480  DRAWPAGE(this->playPage(loopMode,pidFlag,place,1));
481  if(this->forwardBtn.btn == 1 && this->velocity <= 9900 && this->acceleration <= 19900)//increase speed
482  {
483  this->forwardBtn.btn = 0;
484  this->velocity+=10;
485  this->acceleration+=10;
486  }
487  else if(this->backwardsBtn.btn == 1 && this->velocity >= 10 && this->acceleration >= 10)//decrease speed
488  {
489  this->backwardsBtn.btn = 0;
490  this->velocity-=10;
491  this->acceleration-=10;
492  }
493  else if(this->playBtn.btn == 1)
494  {
495  #ifdef ARDUINO_AVR_USTEPPER_S
496  stepper.setMaxVelocity(this->velocity/16.0);
497  #else
498  stepper.setMaxVelocity(this->velocity);
499  #endif
500  stepper.setMaxAcceleration(this->acceleration);
501  this->resetAllButton();
502  return;
503  }
504  }
505 }
506 
508 {
509  DRAWPAGE(this->pausePage(loopMode,pidFlag,place));
510  if(this->playBtn.btn)//play/stop/pause
511  {
512  while(this->playBtn.state == PRESSED);
513  if(this->playBtn.state == DEPRESSED) //Short press = unpause
514  {
515  state = 'b';
516  }
517  else //Long press = stop
518  {
519  state = 'a';
520  loopMode = 0;
521  DRAWPAGE(this->idlePage(pidFlag,setPoint));
522  while(this->playBtn.state == HOLD);
523  this->resetAllButton();
524  }
525  this->resetButton(&playBtn);
526  }
527  if(this->forwardBtn.state == HOLD)//loop mode start
528  {
529  this->resetButton(&forwardBtn);
530  loopMode = 1;
531  }
532  else if(this->backwardsBtn.state == HOLD)//loop mode stop
533  {
534  this->resetButton(&backwardsBtn);
535  loopMode = 0;
536  }
537 }
538 
540 {
541  static uint8_t step = 0;
542  static uint32_t i = 0, j = 0;
543  static uint8_t runState = 0;
544  int32_t OLD=0;
545  stepper.disablePid();
546  stepper.getMotorState();
547 
548  DRAWPAGE(this->timePage(step,pidFlag));
549  if(step == 0)//first put in how long to move at every step in mm
550  {
551  digitalWrite(OPTO, HIGH);
552  if(this->forwardBtn.btn == 1 && stepSize < 100.0)
553  {
554  this->forwardBtn.btn = 0;
555  stepSize=stepSize+0.25;
556  }
557  else if(this->backwardsBtn.btn == 1 && stepSize >= 0.5)
558  {
559  this->backwardsBtn.btn = 0;
560  stepSize=stepSize-0.25;
561  }
562  else if(this->recordBtn.btn == 1)
563  {
564  this->recordBtn.btn = 0;
565  step = 1;
566  }
567  }
568  else if(step == 1)//next put in how long the intervals between moves are in milliseconds
569  {
570  if(this->forwardBtn.btn == 1 && interval < 65000)
571  {
572  this->forwardBtn.btn = 0;
573  interval=interval+250;
574  }
575  else if(this->backwardsBtn.btn == 1 && interval >= (500 + this->shutterDelay))
576  {
577  this->backwardsBtn.btn = 0;
578  interval=interval-250;
579  }
580  else if(this->recordBtn.btn == 1)
581  {
582  delay(200);
583  this->recordBtn.btn = 0;
584  step = 2;
585  }
586  }
587  else if(step == 2)//ready to play
588  {
589  if(this->playBtn.btn)//play/stop/pause
590  {
591  while(this->playBtn.state == PRESSED);
592  if(this->playBtn.state == DEPRESSED) //Short press = unpause
593  {
594  step = 3;
595  i = millis();
596  }
597  else //Long press = stop
598  {
599  state = 'a';
600  step = 0;
601  this->resetAllButton();
602  }
603  this->resetButton(&playBtn);
604  }
605  }
606  else if(step == 3)//playing until the end
607  {
608  if(runState == 0) //start new movement
609  {
610  OLD=stepper.encoder.getAngleMoved();
612  stepper.moveAngle((stepSize*resolution));
613  DRAWPAGE(this->timePage(step,pidFlag));
614  i = millis();
615  runState = 1;
616  return;
617  }
618  else if(runState == 1) //Waiting for movement to finish
619  {
620  if(!stepper.getMotorState())
621  {
622  j = millis();
623  runState = 2;
624  return;
625  }
626  }
627  else if(runState == 2) //Waiting 250ms before firing trigger. (to stabilize rail and avoid vibrations)
628  {
629  if(((millis() - j) > this->shutterDelay))
630  {
631  digitalWrite(OPTO, LOW); // sets the LED in the opto on triggering the camera
632  runState = 3;
633  j = millis();
634  return;
635  }
636  }
637  else if(runState == 3) //Waiting to release trigger
638  {
639  if(((millis() - j) > 200))
640  {
641  digitalWrite(OPTO, HIGH); // sets the LED in the opto off releases the camera trigger
642  runState = 4;
643  return;
644  }
645  }
646  else if(runState == 4) //Waiting The remaining period
647  {
648  if((millis() - i) > interval)
649  {
650  runState = 0;
651  return;
652  }
653  }
654  if(this->playBtn.btn == 1)
655  {
656  state = 'a';
657  step = 0;
658  this->resetAllButton();
659  return;
660  }
661  #ifdef ARDUINO_AVR_USTEPPER_S
662  if(!stepper.getMotorState() && (stepSize*resolution*0.9>abs(OLD-stepper.encoder.getAngleMoved())))
663  {
664  delay(500);
665  if(this->stallSensitivity!=100)
666  {
667  stepper.moveToEnd(CCW,this->velocity*0.019,this->stallSensitivity);
668  stepper.encoder.setHome();
669  stepper.moveToAngle(30);
670  while(stepper.getMotorState());
671  stepper.encoder.setHome();
672  }
673  state = 'a';//idle state
674  step = 0;
675  runState=0;
676  this->resetAllButton();
677  return;
678  }
679  #else
680  if(stepper.isStalled())
681  {
682  stepper.moveToEnd(CCW);
683  stepper.encoder.setHome();
684  stepper.moveToAngle(30);
685  while(stepper.getMotorState());
686  stepper.encoder.setHome();
687  state = 'a';//idle state
688  step = 0;
689  runState=0;
690  this->resetAllButton();
691  return;
692  }
693  #endif
694  }
695 }
696 
698 {
699  this->debounce(&forwardBtn,(PINB >> 5) & 0x01);
700  this->debounce(&playBtn,(PINB >> 3) & 0x01);
701  this->debounce(&recordBtn,(PIND >> 2) & 0x01);
702  this->debounce(&backwardsBtn,(PINB >> 4) & 0x01);
703 }
704 
706 {
707  this->screen->clrScreen();
708  this->screen->drawImage(logoBmp, 10, 0, 112, 48);
709 }
710 
711 void egoShield::idlePage(bool pidMode, float pos)
712 {
713  static int32_t position;
714  static bool lastPidMode;
715  char buf[20];
716  String sBuf;
717 
718  if(this->lastPage != IDLEPAGE)
719  {
720  this->screen->clrScreen();
721  lastPidMode = pidMode;
722  this->lastPage = IDLEPAGE;
723  position = (int32_t)(stepper.encoder.getAngleMoved()/this->resolution);
724  sBuf = "Position: ";
725  sBuf += position;
726  sBuf += " mm";
727  sBuf.toCharArray(buf, 20);
728  this->screen->drawRect(0,0,127,7,1);
729  this->screen->drawRect(0,48,127,63,1);
730  this->screen->printString("Idle",2,0,1);
731  if(pidMode)
732  {
733  this->screen->printString("PID ON ",45,0,1);
734  }
735  else
736  {
737  this->screen->printString("PID OFF",45,0,1);
738  }
739  this->screen->drawImage(fastRewindBmp, 0, 48, 16, 16, 1);
740  this->screen->drawImage(playBmp, 28, 48, 16, 16, 1);
741  this->screen->drawImage(stopBmp, 39, 48, 16, 16, 1);
742  this->screen->drawImage(recordBmp, 67, 48, 16, 16, 1);
743  this->screen->drawImage(pauseBmp, 81, 48, 16, 16, 1);
744  this->screen->drawImage(fastForwardBmp, 112, 48, 16, 16, 1);
745  sBuf.toCharArray(buf, 20);
746  this->screen->printString((const uint8_t*)buf,2,24,0);
747  }
748  else
749  {
750  if((int32_t)(stepper.encoder.getAngleMoved()/this->resolution) != position)
751  {
752  position = (int32_t)(stepper.encoder.getAngleMoved()/this->resolution);
753  sBuf = position;
754  sBuf += " mm";
755  sBuf.toCharArray(buf, 20);
756 
757  this->screen->drawRect(62,24,100,31,0);
758  this->screen->printString((const uint8_t*)buf,62,24,0);
759  }
760 
761  if(pidMode != lastPidMode)
762  {
763  lastPidMode = pidMode;
764  if(pidMode)
765  {
766  this->screen->printString("PID ON ",45,0,1);
767  }
768  else
769  {
770  this->screen->printString("PID OFF",45,0,1);
771  }
772  }
773  }
774 }
775 
776 void egoShield::recordPage(bool pidMode, bool recorded, uint8_t index, float pos)
777 {
778  static int32_t position;
779  static bool lastPidMode, updatePosition;
780  char buf[22];
781  String sBuf;
782 
783  if(this->lastPage != RECORDPAGE)
784  {
785  this->screen->clrScreen();
786  lastPidMode = pidMode;
787  this->lastPage = RECORDPAGE;
788  position = (int32_t)(pos/this->resolution);
789  sBuf = "Position: ";
790  sBuf += position;
791  sBuf += " mm";
792  sBuf.toCharArray(buf, 20);
793  this->screen->drawRect(0,0,127,7,1);
794  this->screen->drawRect(0,48,127,63,1);
795  if(pidMode)
796  {
797  this->screen->printString("PID ON ",45,0,1);
798  }
799  else
800  {
801  this->screen->printString("PID OFF",45,0,1);
802  }
803  this->screen->drawImage(fastRewindBmp, 0, 48, 16, 16, 1);
804  this->screen->drawImage(stopBmp, 35, 48, 16, 16, 1);
805  this->screen->drawImage(recordBmp, 73, 48, 16, 16, 1);
806  this->screen->drawImage(fastForwardBmp, 112, 48, 16, 16, 1);
807 
808  if(recorded)
809  {
810  sBuf = "Position: ";
811  sBuf += index;
812  sBuf += " recorded";
813  sBuf.toCharArray(buf, 22);
814  this->screen->printString((const uint8_t*)buf,2,24,0);
815  updatePosition = 1;
816  }
817  else
818  {
819  sBuf = "Position: ";
820  sBuf += (int32_t)(pos/this->resolution);
821  sBuf += " mm";
822  sBuf.toCharArray(buf, 22);
823  this->screen->printString((const uint8_t*)buf,2,24,0);
824  updatePosition = 0;
825  }
826  }
827  else
828  {
829  if(recorded)
830  {
831  sBuf = "Position: ";
832  sBuf += index;
833  sBuf += " recorded";
834  sBuf.toCharArray(buf, 22);
835  this->screen->drawRect(0,24,127,31,0);
836  this->screen->printString((const uint8_t*)buf,2,24,0);
837  updatePosition = 1;
838  }
839  else
840  {
841  if((int32_t)(pos/this->resolution) != position || updatePosition)
842  {
843  updatePosition = 0;
844  position = (int32_t)(pos/this->resolution);
845 
846  sBuf = position;
847  sBuf += " mm";
848  sBuf.toCharArray(buf, 20);
849 
850  this->screen->drawRect(62,24,127,31,0);
851  this->screen->printString((const uint8_t*)buf,62,24,0);
852  }
853  }
854 
855  if(pidMode != lastPidMode)
856  {
857  this->screen->drawRect(0,0,127,7,1);
858  lastPidMode = pidMode;
859  if(pidMode)
860  {
861  this->screen->printString("PID ON ",45,0,1);
862  }
863  else
864  {
865  this->screen->printString("PID OFF",45,0,1);
866  }
867  }
868  }
869 }
870 
871 void egoShield::playPage(bool loopMode, bool pidMode, uint8_t index, bool mode)
872 {
873  static int32_t position;
874  static bool lastPidMode, lastMode, lastLoopMode, lastIndex;
875  static float lastVelocity;
876  char buf[22];
877  String sBuf;
878 
879  if(this->lastPage != PLAYPAGE)
880  {
881  this->screen->clrScreen();
882  lastPidMode = pidMode;
883  this->lastPage = PLAYPAGE;
884  this->screen->drawRect(0,0,127,7,1);
885  this->screen->drawRect(0,48,127,63,1);
886  this->screen->printString("Play",2,0,1);
887  if(pidMode)
888  {
889  this->screen->printString("PID ON ",45,0,1);
890  }
891  else
892  {
893  this->screen->printString("PID OFF",45,0,1);
894  }
895  this->screen->drawImage(fastRewindBmp, 0, 48, 16, 16, 1);
896  this->screen->drawImage(playBmp, 34, 48, 16, 16, 1);
897  this->screen->drawImage(stopBmp, 48, 48, 16, 16, 1);
898  this->screen->drawImage(pauseBmp, 79, 48, 16, 16, 1);
899  this->screen->drawImage(fastForwardBmp, 112, 48, 16, 16, 1);
900 
901  lastLoopMode = loopMode;
902 
903  if(loopMode)
904  {
905  this->screen->drawImage(repeatBmp, 112, 0, 16, 8, 1);
906  }
907 
908  lastMode = mode;
909  if(mode)
910  {
911  this->screen->printString("Adjust velocity",2,24,0);
912  }
913  else
914  {
915  this->screen->printString("Moving to pos",2,24,0);
916  String(index).toCharArray(buf, 5);
917  this->screen->printString((const uint8_t*)buf,90,24,0);
918  }
919  lastVelocity = this->velocity;
920  this->screen->printString("Speed: ",2,32,0);
921  String(this->velocity).toCharArray(buf, 5);
922  this->screen->printString((const uint8_t*)buf,60,32,0);
923  }
924  else
925  {
926  if(lastVelocity != this->velocity)
927  {
928  String(this->velocity).toCharArray(buf, 5);
929  this->screen->printString((const uint8_t*)buf,60,32,0);
930  }
931 
932  lastVelocity = this->velocity;
933 
934  if(mode)
935  {
936  if(lastMode != mode)
937  {
938  this->screen->drawRect(0,24,127,31,0);
939  this->screen->printString("Adjust velocity",2,24,0);
940  }
941  }
942  else
943  {
944  if(lastMode != mode)
945  {
946  this->screen->drawRect(0,24,127,31,0);
947  this->screen->printString("Moving to pos",2,24,0);
948  String(index).toCharArray(buf, 5);
949  this->screen->printString((const uint8_t*)buf,90,24,0);
950  }
951  else
952  {
953  if(lastIndex != index)
954  {
955  String(index).toCharArray(buf, 5);
956  this->screen->printString((const uint8_t*)buf,90,24,0);
957  }
958  }
959  lastIndex = index;
960  }
961 
962  lastMode = mode;
963 
964  if(loopMode != lastLoopMode)
965  {
966  this->screen->drawRect(110,0,127,7,1);
967  if(loopMode)
968  {
969  this->screen->drawImage(repeatBmp, 112, 0, 16, 8, 1);
970  }
971  }
972  lastLoopMode = loopMode;
973 
974  if(pidMode != lastPidMode)
975  {
976  this->screen->drawRect(0,0,127,7,1);
977  lastPidMode = pidMode;
978  if(pidMode)
979  {
980  this->screen->printString("PID ON ",45,0,1);
981  }
982  else
983  {
984  this->screen->printString("PID OFF",45,0,1);
985  }
986  }
987  }
988 }
989 
990 void egoShield::pausePage(bool loopMode, bool pidMode, uint8_t index)
991 {
992  static bool lastPidMode, lastLoopMode;
993  char buf[22];
994  String sBuf;
995 
996  if(this->lastPage != PAUSEPAGE)
997  {
998  lastPidMode = pidMode;
999  this->lastPage = PAUSEPAGE;
1000  this->screen->clrScreen();
1001  this->screen->drawRect(0,0,127,7,1);
1002  this->screen->drawRect(0,48,127,63,1);
1003  this->screen->printString("Pause",2,0,1);
1004  if(pidMode)
1005  {
1006  this->screen->printString("PID ON ",45,0,1);
1007  }
1008  else
1009  {
1010  this->screen->printString("PID OFF",45,0,1);
1011  }
1012  this->screen->drawImage(playBmp, 22, 48, 16, 16, 1);
1013  this->screen->drawImage(stopBmp, 35, 48, 16, 16, 1);
1014 
1015  lastLoopMode = loopMode;
1016 
1017  if(loopMode)
1018  {
1019  this->screen->drawImage(repeatBmp, 112, 0, 16, 8, 1);
1020  }
1021 
1022  this->screen->printString("Paused at Position ",2,24,0);
1023  String(index).toCharArray(buf, 5);
1024  this->screen->printString((const uint8_t*)buf,114,24,0);
1025  }
1026  else
1027  {
1028  if(loopMode != lastLoopMode)
1029  {
1030  this->screen->drawRect(110,0,127,7,1);
1031  if(loopMode)
1032  {
1033  this->screen->drawImage(repeatBmp, 112, 0, 16, 8, 1);
1034  }
1035  }
1036 
1037  lastLoopMode = loopMode;
1038 
1039  if(pidMode != lastPidMode)
1040  {
1041  this->screen->drawRect(45,0,127,7,1);
1042  lastPidMode = pidMode;
1043  if(pidMode)
1044  {
1045  this->screen->printString("PID ON ",45,0,1);
1046  }
1047  else
1048  {
1049  this->screen->printString("PID OFF",45,0,1);
1050  }
1051  }
1052  }
1053 }
1054 
1055 
1056 void egoShield::timePage(uint8_t step, bool pidMode)
1057 {
1058 
1059  static bool lastPidMode;
1060  static uint8_t lastStep;
1061  static float lastStepSize, lastInterval;
1062  int32_t angle;
1063  static int32_t lastAngle;
1064  char buf[22];
1065  String sBuf;
1066 
1067  if(this->lastPage != TIMEPAGE)
1068  {
1069  lastPidMode = pidMode;
1070  this->lastPage = TIMEPAGE;
1071  this->screen->clrScreen();
1072  this->screen->drawRect(0,0,127,7,1);
1073  this->screen->drawRect(0,48,127,63,1);
1074  this->screen->printString("Time",2,0,1);
1075 
1076 
1077  if(step == 0)//we are waiting for the distance interval to be put in
1078  {
1079  this->screen->drawImage(fastRewindBmp, 0, 48, 16, 16, 1);
1080  this->screen->drawImage(recordBmp, 73, 48, 16, 16, 1);
1081  this->screen->drawImage(fastForwardBmp, 112, 48, 16, 16, 1);
1082  this->screen->printString("<-",115,24,0);
1083  }
1084  else if(step == 1)//we are waiting for the time interval to be put in
1085  {
1086  this->screen->drawImage(fastRewindBmp, 0, 48, 16, 16, 1);
1087  this->screen->drawImage(recordBmp, 73, 48, 16, 16, 1);
1088  this->screen->drawImage(fastForwardBmp, 112, 48, 16, 16, 1);
1089  this->screen->printString("<-",115,32,0);
1090  }
1091  else if(step == 2)//we are waiting for play to be issued
1092  {
1093  this->screen->drawImage(playBmp, 28, 48, 16, 16, 1);
1094  this->screen->drawImage(stopBmp, 35, 48, 16, 16, 1);
1095  }
1096  else if(step == 3)//we are playing sequence until end of rail
1097  {
1098  this->screen->drawImage(stopBmp, 35, 48, 16, 16, 1);
1099  }
1100 
1101  lastStep = step;
1102  this->screen->drawRect(45,0,127,7,1);
1103  if(pidMode)
1104  {
1105  this->screen->printString("PID ON ",45,0,1);
1106  }
1107  else
1108  {
1109  this->screen->printString("PID OFF",45,0,1);
1110  }
1111 
1112  angle = (int32_t)(stepper.encoder.getAngleMoved()/resolution);
1113 
1114  sBuf = "Stepsize: ";
1115  sBuf += stepSize;
1116  lastStepSize = stepSize;
1117  sBuf += " mm";
1118  sBuf.toCharArray(buf, 22);
1119  this->screen->printString((const uint8_t*)buf,2,24,0);
1120  sBuf = "Interval: ";
1121  sBuf += interval*0.001;
1122  lastInterval = interval;
1123  sBuf += " s";
1124  sBuf.toCharArray(buf, 22);
1125  this->screen->printString((const uint8_t*)buf,2,32,0);
1126  sBuf = "Encoder: ";
1127  sBuf += angle;
1128  lastAngle = angle;
1129  sBuf += " mm";
1130  sBuf.toCharArray(buf, 22);
1131  this->screen->printString((const uint8_t*)buf,2,40,0);
1132  }
1133  else
1134  {
1135  angle = (int32_t)(stepper.encoder.getAngleMoved()/resolution);
1136 
1137  if(lastStepSize != stepSize)
1138  {
1139  sBuf = stepSize;
1140  lastStepSize = stepSize;
1141  sBuf += " mm";
1142  sBuf.toCharArray(buf, 22);
1143  this->screen->drawRect(66,24,127,31,0);
1144  this->screen->printString((const uint8_t*)buf,68,24,0);
1145  }
1146 
1147  if(lastInterval != interval)
1148  {
1149  sBuf = interval*0.001;
1150  lastInterval = interval;
1151  sBuf += " s";
1152  sBuf.toCharArray(buf, 22);
1153  this->screen->drawRect(66,32,127,39,0);
1154  this->screen->printString((const uint8_t*)buf,68,32,0);
1155  }
1156 
1157  if(lastAngle != angle)
1158  {
1159  sBuf = angle;
1160  lastAngle = angle;
1161  sBuf += " mm";
1162  sBuf.toCharArray(buf, 22);
1163  this->screen->drawRect(68,40,114,47,0);
1164  this->screen->printString((const uint8_t*)buf,68,40,0);
1165  }
1166 
1167  if(step != lastStep)
1168  {
1169  this->screen->drawRect(0,48,127,63,1);
1170  this->screen->drawRect(115,24,127,39,0);
1171  if(step == 0)//we are waiting for the distance interval to be put in
1172  {
1173  this->screen->drawImage(fastRewindBmp, 0, 48, 16, 16, 1);
1174  this->screen->drawImage(recordBmp, 73, 48, 16, 16, 1);
1175  this->screen->drawImage(fastForwardBmp, 112, 48, 16, 16, 1);
1176  this->screen->printString("<-",115,24,0);
1177  }
1178  else if(step == 1)//we are waiting for the time interval to be put in
1179  {
1180  this->screen->drawImage(fastRewindBmp, 0, 48, 16, 16, 1);
1181  this->screen->drawImage(recordBmp, 73, 48, 16, 16, 1);
1182  this->screen->drawImage(fastForwardBmp, 112, 48, 16, 16, 1);
1183  this->screen->printString("<-",115,32,0);
1184  }
1185  else if(step == 2)//we are waiting for play to be issued
1186  {
1187  this->screen->drawImage(playBmp, 35, 48, 16, 16, 1);
1188  }
1189  else if(step == 3)//we are playing sequence until end of rail
1190  {
1191  this->screen->drawImage(stopBmp, 35, 48, 16, 16, 1);
1192  }
1193 
1194  lastStep = step;
1195  }
1196 
1197  if(pidMode != lastPidMode)
1198  {
1199  this->screen->drawRect(45,0,127,7,1);
1200  lastPidMode = pidMode;
1201  if(pidMode)
1202  {
1203  this->screen->printString("PID ON ",45,0,1);
1204  }
1205  else
1206  {
1207  this->screen->printString("PID OFF",45,0,1);
1208  }
1209  }
1210  }
1211 }
1212 
1213 void egoShield::debounce(buttons *btn, uint8_t sample)
1214 {
1215  if(btn->state == DEPRESSED)
1216  {
1217  btn->debounce &= (0xFE + sample);
1218 
1219  if( (btn->debounce & 0x1F) == 0x00)
1220  {
1221  btn->state = PRESSED;
1222  btn->btn = 1;
1223  return;
1224  }
1225 
1226  btn->debounce <<= 1;
1227  btn->debounce |= 0x01;
1228  }
1229 
1230  else if((btn->state == PRESSED) || (btn->state == HOLD))
1231  {
1232  btn->debounce |= sample;
1233 
1234  if(btn->state != HOLD)
1235  {
1236  if((btn->debounce & 0x1F) == 0x00)
1237  {
1238  if(btn->holdCnt >= HOLDTIME)
1239  {
1240  btn->state = HOLD;
1241  }
1242  btn->holdCnt++;
1243  }
1244  }
1245 
1246  if( (btn->debounce & 0x1F) == 0x1F)
1247  {
1248  btn->state = DEPRESSED;
1249  btn->holdCnt = 0;
1250  return;
1251  }
1252 
1253  btn->debounce <<= 1;
1254  btn->debounce &= 0xFE;
1255  }
1256 
1257  if(btn->state == HOLD)
1258  {
1259  if(btn->time == HOLDTICK)
1260  {
1261  btn->btn = 1;
1262  btn->time = 0;
1263  }
1264 
1265  else
1266  {
1267  btn->time++;
1268  }
1269  }
1270 }
1271 
1273 {
1274  btn->time = 0;
1275  btn->state = DEPRESSED;
1276  btn->debounce = 0x1F;
1277  btn->holdCnt = 0;
1278  btn->btn = 0;
1279 }
1281 {
1282  this->resetButton(&playBtn);
1283  this->resetButton(&forwardBtn);
1284  this->resetButton(&backwardsBtn);
1285  this->resetButton(&recordBtn);
1286 }
buttons::holdCnt
uint8_t holdCnt
Definition: egoShieldS.h:149
egoShield
Definition: egoShieldS.h:177
egoShield::pidFlag
bool pidFlag
Definition: egoShieldS.h:244
egoShield::acceleration
uint16_t acceleration
Definition: egoShieldS.h:264
egoShield::changeVelocity
void changeVelocity(void)
Holds the code for the changing velocity during sequence play.
Definition: egoShieldS.cpp:476
egoShield::egoShield
egoShield(void)
Constructor of egoShield class.
Definition: egoShieldS.cpp:49
egoShield::stallSensitivity
int8_t stallSensitivity
Definition: egoShieldS.h:286
egoShield::recordPage
void recordPage(bool pidMode, bool recorded, uint8_t index, float pos)
Holds the code for the record page of the OLED.
Definition: egoShieldS.cpp:776
egoShield::playPage
void playPage(bool loopMode, bool pidMode, uint8_t index, bool mode)
Holds the code for the play page of the OLED.
Definition: egoShieldS.cpp:871
egoShield::interval
uint16_t interval
Definition: egoShieldS.h:282
buttons::btn
uint8_t btn
Definition: egoShieldS.h:149
buttons::state
uint8_t state
Definition: egoShieldS.h:149
egoShield::setPoint
float setPoint
Definition: egoShieldS.h:262
screen.h
class definitions for the screen handling
PLBT
#define PLBT
Definition: egoShieldS.h:124
egoShield::timePage
void timePage(uint8_t step, bool pidMode)
Holds the code for the timelapse page of the OLED.
Definition: egoShieldS.cpp:1056
egoShield::iTerm
float iTerm
Definition: egoShieldS.h:276
egoShield::screen
Screen * screen
Contains the main logic of the shield functionality, e.g. transition between states (idle,...
Definition: egoShieldS.h:233
Screen
Definition: screen.h:293
egoShield::recordMode
void recordMode(void)
This function handles the debouncing and tracking of whether buttons are pressed, released or held.
Definition: egoShieldS.cpp:186
egoShield::pTerm
float pTerm
Definition: egoShieldS.h:274
egoShield::idlePage
void idlePage(bool pidMode, float pos)
Holds the code for the idle page of the OLED.
Definition: egoShieldS.cpp:711
egoShield::resetAllButton
void resetAllButton()
Resets the state of all 4 buttons at once.
Definition: egoShieldS.cpp:1280
egoShield::resolution
float resolution
Definition: egoShieldS.h:284
egoShield::pos
float pos[CNT]
Definition: egoShieldS.h:242
egoShield::state
char state
Definition: egoShieldS.h:252
egoShield::setup
void setup(uint16_t acc=1500, uint16_t vel=100, float P=1.0, float I=0.02, float D=0.006, float res=1, int8_t stallsens=2, uint16_t shutterDelay=250)
Initializes buttons, OLED, uStepper and BT-module.
Definition: egoShieldS.cpp:53
buttons::time
uint16_t time
Definition: egoShieldS.h:153
egoShieldS.h
Class definition for the egoShieldS library.
egoShield::lastPage
uint8_t lastPage
Definition: egoShieldS.h:236
egoShield::shutterDelay
uint16_t shutterDelay
Definition: egoShieldS.h:295
egoShield::stepSize
float stepSize
Definition: egoShieldS.h:280
egoShield::playMode
void playMode(void)
Holds the play logic, showing play page and running the recorded sequence.
Definition: egoShieldS.cpp:382
TIMER4_COMPA_vect
void TIMER4_COMPA_vect(void) __attribute__((signal
Watchdog timer interrupt handler, for examining the buttons periodically.
Definition: egoShieldS.cpp:38
BWBT
#define BWBT
Definition: egoShieldS.h:122
OPTO
#define OPTO
Definition: egoShieldS.h:132
egoShield::timeMode
void timeMode(void)
Holds the timelapse logic, showing the timelapse page.
Definition: egoShieldS.cpp:539
CNT
#define CNT
Definition: egoShieldS.h:130
egoShield::startPage
void startPage(void)
Holds the code for the start page of the OLED.
Definition: egoShieldS.cpp:705
RECBT
#define RECBT
Definition: egoShieldS.h:126
egoShield::velocity
uint16_t velocity
Definition: egoShieldS.h:266
egoShield::idleMode
void idleMode(void)
Holds the idle logic; page to show, what buttons to enable etc.
Definition: egoShieldS.cpp:283
egoShield::inputs
void inputs(void)
Reads the four buttons and writes their value; no push, short push or long push, to global variables.
Definition: egoShieldS.cpp:697
egoShield::pauseMode
void pauseMode(void)
Holds the pause logic, showing the pause page and pausing the playing of a sequence.
Definition: egoShieldS.cpp:507
egoShield::loopMode
bool loopMode
Definition: egoShieldS.h:248
egoShield::dTerm
float dTerm
Definition: egoShieldS.h:278
egoShield::brakeFlag
bool brakeFlag
Definition: egoShieldS.h:288
egoShield::record
bool record
Definition: egoShieldS.h:246
egoShield::resetButton
void resetButton(buttons *btn)
Function for resetting the state of a button seperately.
Definition: egoShieldS.cpp:1272
FWBT
#define FWBT
Definition: egoShieldS.h:128
buttons
struct to hold information required to debounce button.
Definition: egoShieldS.h:148
buttons::debounce
uint8_t debounce
Definition: egoShieldS.h:149
egoShield::place
uint8_t place
Definition: egoShieldS.h:238
egoShield::endmove
uint8_t endmove
Definition: egoShieldS.h:240
egoShield::pausePage
void pausePage(bool loopMode, bool pidMode, uint8_t index)
Holds the code for the pause page of the OLED.
Definition: egoShieldS.cpp:990