13
13
Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
14
14
Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
15
15
Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
16
- Copyright (C) 2009-2013 Jeff Hoefs. All rights reserved.
16
+ Copyright (C) 2009-2014 Jeff Hoefs. All rights reserved.
17
17
18
18
This library is free software; you can redistribute it and/or
19
19
modify it under the terms of the GNU Lesser General Public
@@ -83,10 +83,55 @@ signed char queryIndex = -1;
83
83
unsigned int i2cReadDelayTime = 0 ; // default delay time between i2c read request and Wire.requestFrom()
84
84
85
85
Servo servos[MAX_SERVOS];
86
+ byte servoPinMap[TOTAL_PINS];
87
+ byte detachedServos[MAX_SERVOS];
88
+ byte detachedServoCount = 0 ;
89
+ byte servoCount = 0 ;
90
+
91
+
86
92
/* ==============================================================================
87
93
* FUNCTIONS
88
94
*============================================================================*/
89
95
96
+ void attachServo (byte pin, int minPulse, int maxPulse)
97
+ {
98
+ if (servoCount < MAX_SERVOS) {
99
+ // reuse indexes of detached servos until all have been reallocated
100
+ if (detachedServoCount > 0 ) {
101
+ servoPinMap[pin] = detachedServos[detachedServoCount - 1 ];
102
+ if (detachedServoCount > 0 ) detachedServoCount--;
103
+ } else {
104
+ servoPinMap[pin] = servoCount;
105
+ servoCount++;
106
+ }
107
+ if (minPulse > 0 && maxPulse > 0 ) {
108
+ servos[servoPinMap[pin]].attach (PIN_TO_DIGITAL (pin), minPulse, maxPulse);
109
+ } else {
110
+ servos[servoPinMap[pin]].attach (PIN_TO_DIGITAL (pin));
111
+ }
112
+ setPinModeCallback (pin, SERVO);
113
+ } else {
114
+ Firmata.sendString (" Max servos attached" );
115
+ }
116
+ }
117
+
118
+ void detachServo (byte pin)
119
+ {
120
+ servos[servoPinMap[pin]].detach ();
121
+ // if we're detaching the last servo, decrement the count
122
+ // otherwise store the index of the detached servo
123
+ if (servoPinMap[pin] == servoCount && servoCount > 0 ) {
124
+ servoCount--;
125
+ } else if (servoCount > 0 ) {
126
+ // keep track of detached servos because we want to reuse their indexes
127
+ // before incrementing the count of attached servos
128
+ detachedServoCount++;
129
+ detachedServos[detachedServoCount - 1 ] = servoPinMap[pin];
130
+ }
131
+
132
+ servoPinMap[pin] = 255 ;
133
+ }
134
+
90
135
void readAndReportData (byte address, int theRegister, byte numBytes) {
91
136
// allow I2C requests that don't require a register read
92
137
// for example, some devices using an interrupt pin to signify new data available
@@ -180,8 +225,10 @@ void setPinModeCallback(byte pin, int mode)
180
225
// the following if statements should reconfigure the pins properly
181
226
disableI2CPins ();
182
227
}
183
- if (IS_PIN_SERVO (pin) && mode != SERVO && servos[PIN_TO_SERVO (pin)].attached ()) {
184
- servos[PIN_TO_SERVO (pin)].detach ();
228
+ if (IS_PIN_DIGITAL (pin) && mode != SERVO) {
229
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached ()) {
230
+ detachServo (pin);
231
+ }
185
232
}
186
233
if (IS_PIN_ANALOG (pin)) {
187
234
reportAnalogCallback (PIN_TO_ANALOG (pin), mode == ANALOG ? 1 : 0 ); // turn on/off reporting
@@ -226,10 +273,13 @@ void setPinModeCallback(byte pin, int mode)
226
273
}
227
274
break ;
228
275
case SERVO:
229
- if (IS_PIN_SERVO (pin)) {
276
+ if (IS_PIN_DIGITAL (pin)) {
230
277
pinConfig[pin] = SERVO;
231
- if (!servos[PIN_TO_SERVO (pin)].attached ()) {
232
- servos[PIN_TO_SERVO (pin)].attach (PIN_TO_DIGITAL (pin));
278
+ if (!servos[servoPinMap[pin]].attached ()) {
279
+ // servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
280
+ // pass -1 for min and max pulse values to use default values set
281
+ // by Servo library
282
+ attachServo (pin, -1 , -1 );
233
283
}
234
284
}
235
285
break ;
@@ -251,8 +301,8 @@ void analogWriteCallback(byte pin, int value)
251
301
if (pin < TOTAL_PINS) {
252
302
switch (pinConfig[pin]) {
253
303
case SERVO:
254
- if (IS_PIN_SERVO (pin))
255
- servos[PIN_TO_SERVO ( pin) ].write (value);
304
+ if (IS_PIN_DIGITAL (pin))
305
+ servos[servoPinMap[ pin] ].write (value);
256
306
pinState[pin] = value;
257
307
break ;
258
308
case PWM:
@@ -430,11 +480,11 @@ void sysexCallback(byte command, byte argc, byte *argv)
430
480
int minPulse = argv[1 ] + (argv[2 ] << 7 );
431
481
int maxPulse = argv[3 ] + (argv[4 ] << 7 );
432
482
433
- if (IS_PIN_SERVO (pin)) {
434
- if (servos[PIN_TO_SERVO ( pin)] .attached ())
435
- servos[ PIN_TO_SERVO (pin)]. detach ( );
436
- servos[ PIN_TO_SERVO (pin)]. attach ( PIN_TO_DIGITAL (pin), minPulse, maxPulse);
437
- setPinModeCallback (pin, SERVO );
483
+ if (IS_PIN_DIGITAL (pin)) {
484
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[ pin]] .attached ()) {
485
+ detachServo (pin);
486
+ }
487
+ attachServo (pin, minPulse, maxPulse );
438
488
}
439
489
}
440
490
break ;
@@ -474,7 +524,7 @@ void sysexCallback(byte command, byte argc, byte *argv)
474
524
Firmata.write (PWM);
475
525
Firmata.write (8 );
476
526
}
477
- if (IS_PIN_SERVO (pin)) {
527
+ if (IS_PIN_DIGITAL (pin)) {
478
528
Firmata.write (SERVO);
479
529
Firmata.write (14 );
480
530
}
@@ -550,25 +600,38 @@ void systemResetCallback()
550
600
if (isI2CEnabled) {
551
601
disableI2CPins ();
552
602
}
603
+
604
+ for (byte i=0 ; i < MAX_SERVOS; i++) {
605
+ if (servoPinMap[i] < MAX_SERVOS) {
606
+ // servos[servoPinMap[i]].detach();
607
+ }
608
+ }
609
+
553
610
for (byte i=0 ; i < TOTAL_PORTS; i++) {
554
611
reportPINs[i] = false ; // by default, reporting off
555
612
portConfigInputs[i] = 0 ; // until activated
556
613
previousPINs[i] = 0 ;
557
614
}
558
- // pins with analog capability default to analog input
559
- // otherwise, pins default to digital output
615
+
560
616
for (byte i=0 ; i < TOTAL_PINS; i++) {
617
+ // pins with analog capability default to analog input
618
+ // otherwise, pins default to digital output
561
619
if (IS_PIN_ANALOG (i)) {
562
620
// turns off pullup, configures everything
563
621
setPinModeCallback (i, ANALOG);
564
622
} else {
565
623
// sets the output to 0, configures portConfigInputs
566
624
setPinModeCallback (i, OUTPUT);
567
625
}
626
+
627
+ servoPinMap[i] = 255 ;
568
628
}
569
629
// by default, do not report any analog inputs
570
630
analogInputsToReport = 0 ;
571
631
632
+ detachedServoCount = 0 ;
633
+ servoCount = 0 ;
634
+
572
635
/* send digital inputs to set the initial state on the host computer,
573
636
* since once in the loop(), this firmware will only send on change */
574
637
/*
0 commit comments