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