Accessories
Arduino for motors and lights library.
AccessoryServo.cpp
1 /*************************************************************
2 project: <Accessories>
3 author: <Thierry PARIS>
4 description: <Class for a servo accessory>
5 *************************************************************/
6 
7 #include "Accessories.h"
8 
9 #ifndef NO_SERVO
10 #include "ActionsStack.hpp"
11 
13 {
14  this->pPort = NULL;
15  this->minimumPosition = 0;
16  this->maximumPosition = 180;
17  this->powerState = PowerNoAction;
18 }
19 
20 void AccessoryServo::begin(Port *inpPort, unsigned long inDurationMilli,
21  int inMinimumPosition, int inMaximumPosition, int inMovingPositionsNumber)
22 {
23  this->pPort = inpPort;
24 
25  this->SetDuration(inDurationMilli);
26  Accessory::begin(STATE_NONE);
27  this->minimumPosition = inMinimumPosition;
28  this->maximumPosition = inMaximumPosition;
29  this->prevState = STATE_NONE;
30  inpPort->beginByAccessory(this->minimumPosition);
31  this->prevState = MINIMUM;
32  this->currentPosition = this->minimumPosition;
33  this->targetPosition = -1;
34  this->targetSpeed = 0;
35  this->powerCommandPin = (GPIO_pin_t)DP_INVALID;
36  this->powerDelay = 0;
37  this->powerState = PowerNoAction;
38  this->AdjustMovingPositionsSize(inMovingPositionsNumber);
39 }
40 
41 void AccessoryServo::SetPowerCommand(int inPin, unsigned long inDelay)
42 {
43  this->powerCommandPin = Arduino_to_GPIO_pin(inPin);
44 
45  pinMode2f(this->powerCommandPin, OUTPUT);
46  this->PowerOn();
47 
48  this->powerDelay = inDelay;
49 }
50 
51 void AccessoryServo::PowerOn()
52 {
53  if (this->powerCommandPin != DP_INVALID)
54  digitalWrite2f(this->powerCommandPin, HIGH);
55 }
56 
57 void AccessoryServo::PowerOff()
58 {
59  if (this->powerCommandPin != DP_INVALID)
60  digitalWrite2f(this->powerCommandPin, LOW);
61 
62  this->pPort->MoveStop();
63 }
64 
66 {
67 #ifdef ACCESSORIES_DEBUG_MODE
68  Serial.println(F("AccessoryServo MoveMinimum()"));
69 #endif
70 
71  this->MovePosition(this->minimumPosition);
72 }
73 
75 {
76 #ifdef ACCESSORIES_DEBUG_MODE
77  Serial.println(F("AccessoryServo MoveMaximum()"));
78 #endif
79 
80  this->MovePosition(this->maximumPosition);
81 }
82 
84 {
85  if (this->IsActionDelayPending())
86  return this->GetState();
87 
88 #ifdef ACCESSORIES_DEBUG_MODE
89  Serial.print(F("AccessoryServo MoveToggle() : "));
90 #endif
91 
92  if (this->prevState == MAXIMUM)
93  this->MovePosition(this->minimumPosition);
94  else
95  this->MovePosition(this->maximumPosition);
96 
97  return this->GetState();
98 }
99 
100 void AccessoryServo::SetState(ACC_STATE inState)
101 {
102 #ifdef ACCESSORIES_DEBUG_MODE
103  Serial.print(F("AccessoryServo SetState("));
104 #endif
105 
106  switch (inState)
107  {
108  case MINIMUM:
109 #ifdef ACCESSORIES_DEBUG_MODE
110  Serial.println(F("MINIMUM)"));
111 #endif
112  this->MovePosition(this->minimumPosition);
113  break;
114 
115  case MAXIMUM:
116 #ifdef ACCESSORIES_DEBUG_MODE
117  Serial.println(F("MAXIMUM)"));
118 #endif
119  this->MovePosition(this->maximumPosition);
120  break;
121 
122  default:
123  this->ResetAction();
124  }
125 }
126 
127 void AccessoryServo::Move(unsigned long inId)
128 {
129 #ifdef ACCESSORIES_DEBUG_MODE
130  Serial.println(F("AccessoryServo Move()"));
131 #endif
132 
133  if (this->GetMovingPositionSize() == 1)
134  {
135  this->MoveToggle();
136  return;
137  }
138 
140  int position = this->GetMovingPositionValueById(inId);
141 
142  if (position == MINIMUM || position == MAXIMUM)
143  this->SetState((ACC_STATE)position);
144  else
145  this->MovePosition(position);
146 }
147 
148 void AccessoryServo::MovePosition(int inPosition)
149 {
151  return;
152 
153  this->InternalMovePosition(inPosition);
154 }
155 
156 void AccessoryServo::Event(unsigned long inId, ACCESSORIES_EVENT_TYPE inEvent, int inData)
157 {
158  switch (inEvent)
159  {
160  case ACCESSORIES_EVENT_MOVE:
161  switch (inData)
162  {
163  case ACCESSORIES_MOVE_STRAIGHT:
164  case ACCESSORIES_MOVE_TOP:
165  case ACCESSORIES_MOVE_LEFT:
166  this->MoveMinimum();
167  break;
168  case ACCESSORIES_MOVE_DIVERGE:
169  case ACCESSORIES_MOVE_BOTTOM:
170  case ACCESSORIES_MOVE_RIGHT:
171  this->MoveMaximum();
172  break;
173  case ACCESSORIES_MOVE_OFF:
174  case ACCESSORIES_MOVE_STOP:
175  this->pPort->MoveStop();
176  this->ResetAction();
177  this->SetStateRaw(STOP);
178  break;
179  case ACCESSORIES_MOVE_MORE:
180  case ACCESSORIES_MOVE_LESS:
181  {
182  int pos = this->currentPosition + inData;
183  if (pos > this->maximumPosition)
184  pos = this->maximumPosition;
185  if (pos < this->minimumPosition)
186  pos = this->minimumPosition;
187  this->MovePosition(pos);
188  }
189  break;
190  }
191  break;
192 
193  case ACCESSORIES_EVENT_MOVEPOSITION:
194  this->MovePosition(inData);
195  break;
196 
197  case ACCESSORIES_EVENT_TOGGLE:
198  case ACCESSORIES_EVENT_MOVEPOSITIONID:
199  this->Move(inId);
200  break;
201 
202  case ACCESSORIES_EVENT_MOVEPOSITIONINDEX:
203  this->Move(this->GetMovingPositionIdByIndex(inData));
204  break;
205 
206  case ACCESSORIES_EVENT_SETSPEED:
207  this->pPort->SetSpeed(inData);
208  break;
209 
210  case ACCESSORIES_EVENT_SETDURATION:
211  this->SetDuration(inData);
212  break;
213 
214  case ACCESSORIES_EVENT_EXTERNALMOVE:
215  this->ExternalMove((ACC_STATE)inData);
216  break;
217 
218  default:
219  break;
220  }
221 }
222 
223 void AccessoryServo::InternalMovePosition(int inPosition)
224 {
225  if (this->currentPosition == inPosition)
226  {
227 #ifdef ACCESSORIES_DEBUG_MODE
228  Serial.println(F("AccessoryServo::MovePosition : same position - no move!"));
229 #endif
230  return;
231  }
232 
233 #ifdef ACCESSORIES_DEBUG_MODE
234  Serial.println(F("AccessoryServo InternalMovePosition()"));
235 #endif
236 
237  MovementSpeed speed = this->GetMovementSpeed();
238 
239  switch (speed)
240  {
241  case ServoFast:
242  this->pPort->MovePosition(this->GetDuration(), inPosition);
243  this->currentPosition = inPosition;
244  break;
245 
246  case ServoAlone:
247  for (int pos = this->currentPosition; pos < inPosition; pos++)
248  this->pPort->MovePosition(this->GetDuration(), pos);
249  this->currentPosition = inPosition;
250  break;
251 
252  case ServoActionStack:
253  StartAction();
254  this->targetPosition = inPosition;
255  this->targetSpeed = (this->currentPosition < this->targetPosition) ? 1 : -1;
257  break;
258 
259  case ServoSlow:
260  StartAction();
261  this->targetPosition = inPosition;
262  this->targetSpeed = (this->currentPosition < this->targetPosition) ? 1 : -1;
263  break;
264  }
265 
266  if (inPosition == this->minimumPosition)
267  {
268  this->SetStateRaw(MINIMUM);
269  this->prevState = MINIMUM;
270  }
271  else
272  if (inPosition == this->maximumPosition)
273  {
274  this->SetStateRaw(MAXIMUM);
275  this->prevState = MAXIMUM;
276  }
277  else
278  {
279  this->SetStateRaw(STATE_NONE);
280  this->prevState = STATE_NONE;
281  }
282 }
283 
284 bool AccessoryServo::ActionEnded()
285 {
286  if (this->GetActionStartingMillis() <= 0)
287  return true;
288 
289  if (this->powerCommandPin == DP_INVALID || this->powerState == PowerRunning)
290  {
291  if (this->targetSpeed == 0)
292  {
293  // Abort
294  this->targetPosition = -1;
296  if (this->powerState == PowerRunning && this->powerCommandPin != DP_INVALID)
297  {
298 #ifdef ACCESSORIES_DEBUG_MODE
299  Serial.println(F("AccessoryServo after running"));
300 #endif
301  this->powerState = PowerAfterRunning;
302  StartAction();
303  return false;
304  }
305 
306  this->ResetAction();
307  return true;
308  }
309 
310  if (millis() - this->GetActionStartingMillis() > this->GetDuration())
311  {
312  this->currentPosition += this->targetSpeed;
313  this->pPort->MovePosition(this->GetDuration(), this->currentPosition);
314 
315  if (this->targetPosition == this->currentPosition)
316  {
317  this->targetPosition = -1;
318  this->targetSpeed = 0;
320  if (this->powerState == PowerRunning && this->powerCommandPin != DP_INVALID)
321  {
322 #ifdef ACCESSORIES_DEBUG_MODE
323  Serial.println(F("AccessoryServo after running"));
324 #endif
325  this->powerState = PowerAfterRunning;
326  StartAction();
327  return false;
328  }
329  this->ResetAction();
330  return true;
331  }
332  StartAction();
333  }
334  }
335  else
336  {
337  if (this->powerState == PowerNoAction)
338  {
339 #ifdef ACCESSORIES_DEBUG_MODE
340  Serial.println(F("AccessoryServo start power command"));
341 #endif
342  this->PowerOff();
343  this->powerState = PowerBeforeRunning;
344  StartAction();
345  return false;
346  }
347 
348  // Action time elapsed, do the next work...
349  if (millis() - this->GetActionStartingMillis() > this->powerDelay)
350  {
351  if (this->powerState == PowerBeforeRunning)
352  {
353 #ifdef ACCESSORIES_DEBUG_MODE
354  Serial.println(F("AccessoryServo running"));
355 #endif
356  this->powerState = PowerRunning;
357  StartAction();
358  return false;
359  }
360 
361  if (this->powerState == PowerAfterRunning)
362  {
363 #ifdef ACCESSORIES_DEBUG_MODE
364  Serial.println(F("AccessoryServo end running"));
365 #endif
366  this->powerState = PowerNoAction;
367  this->PowerOn();
368  this->ResetAction();
369  return true;
370  }
371  }
372  }
373 
374  return false;
375 }
376 
377 MovementSpeed AccessoryServo::GetMovementSpeed() const
378 {
379  if (this->GetDuration() == 0)
380  return ServoFast;
381  if (this->GetDuration() < 6)
382  return ServoAlone;
383  if (this->GetDuration() < 20)
384  return ServoActionStack;
385  return ServoSlow;
386 }
387 
388 #ifndef NO_EEPROM
389 int AccessoryServo::EEPROMLoad(int inPos)
390 {
391  inPos = this->Accessory::EEPROMLoad(inPos);
392 
393  this->PowerOn();
394  this->pPort->MovePosition(0, this->currentPosition);
395  delay(200); //can be done here because we are in setup timing...
396  this->PowerOff();
397 
398  return inPos;
399 }
400 #endif
401 
402 #ifdef ACCESSORIES_PRINT_ACCESSORIES
403 void AccessoryServo::printAccessory()
404 {
405  Serial.print(F(" Servo : "));
406  this->printMovingPositions();
407 
408  if (this->GetPort() != NULL)
409  {
410  Serial.print(F(" / Speed "));
411  Serial.print(this->GetPort()->GetSpeed());
412  }
413  if (this->powerCommandPin != (GPIO_pin_t)DP_INVALID)
414  {
415  Serial.print(F(" / PowerPin "));
416  Port::printPortPin(this->powerCommandPin, DIGITAL);
417  Serial.print(F(" / PowerDelay "));
418  Serial.print(this->powerDelay);
419  }
420  Serial.print(F(" / Delay "));
421  Serial.print(this->GetDebounceDelay());
422  Serial.print(F("ms / "));
423  if (this->GetPort() != NULL)
424  this->GetPort()->printPort();
425  Serial.println(F(" "));
426 }
427 #endif
428 
429 #endif
unsigned int GetDebounceDelay() const
Definition: Accessory.hpp:255
Port * GetPort() const
Definition: Accessory.hpp:205
int EEPROMLoad(int inPos)
unsigned long GetActionStartingMillis() const
Definition: Accessory.hpp:392
virtual void StartAction()
Definition: Accessory.cpp:135
virtual void MovePosition(unsigned long inDuration, int inEndPosition)
Definition: Port.hpp:180
MovementSpeed GetMovementSpeed() const
void ExternalMove(ACC_STATE inNewState)
unsigned long GetMovingPositionIdByIndex(uint8_t inIndex) const
Definition: Accessory.hpp:339
void SetStateRaw(ACC_STATE inNewState)
Definition: Accessory.cpp:223
void Event(unsigned long inId, ACCESSORIES_EVENT_TYPE inEvent = ACCESSORIES_EVENT_MOVEPOSITIONID, int inData = 0)
static bool FillingStack
int GetMovingPositionValueById(unsigned long inId) const
Definition: Accessory.hpp:327
uint8_t IndexOfMovingPositionById(unsigned long inId) const
Definition: Accessory.cpp:94
void SetLastMovingPosition(uint8_t inLastPositionIndex)
Definition: Accessory.cpp:215
const uint8_t GetMovingPositionSize() const
Definition: Accessory.hpp:349
virtual void ResetAction()
Definition: Accessory.hpp:411
bool IsActionDelayPending() const
Definition: Accessory.hpp:424
unsigned long GetDuration() const
Definition: Accessory.hpp:266
ACC_STATE MoveToggle()
void MovePosition(int inPosition)
ACC_STATE GetState() const
Definition: Accessory.hpp:229
virtual void MoveStop()
Definition: Port.hpp:174
void SetPowerCommand(int inPin, unsigned long inDelay = 100)
void AdjustMovingPositionsSize(uint8_t inNewSize)
Definition: Accessory.cpp:30
virtual void beginByAccessory(int inStartingPosition)
Definition: Port.hpp:120
virtual int EEPROMLoad(int inPos)
void Move(unsigned long inId)
void begin(ACC_STATE inStartingState = STATE_NONE)
Definition: Accessory.hpp:200
void SetDuration(unsigned long inDuration)
Definition: Accessory.hpp:370
Definition: Port.hpp:61
virtual int SetSpeed(int inSpeed)
Definition: Port.cpp:108
void begin(Port *inpPort, unsigned long inDurationMilli = 0, int inMinimumPosition = 0, int inMaximumPosition = 180, int inMovingPositionsNumber = 1)
ACC_STATE prevState
Definition: Accessory.hpp:190
Port * pPort
Definition: Accessory.hpp:187