added updated tinypinchange and associated libraries to support PRO

This commit is contained in:
Erik Tylek Kettenburg
2014-12-23 13:07:19 -08:00
parent d5fa60a1ec
commit e09b5f479b
71 changed files with 4062 additions and 331 deletions

Binary file not shown.

View File

@@ -0,0 +1,42 @@
==================
SimpleServo - v0.8
==================
"Shh, ya hear that? Me neither… It's simple… Maybe *too* simple…"
This is a simplistic library to bundle up and generalize bit-banging servo PWM. It has some good points and trade-offs and is primarily being developed for the Digispark.
First the good:
- Can control any number of servos
- All software, no fancy hardware required
- Produces a relatively clean signal
- Allows (or will) tuning pulse parameters to suit the widely varied tastes of different servos
- A single instance can be used with multiple similar servos
Now some limitations:
- It can only control one servo at a time
- The program can't do anything else while the servo is being signaled
- Documentation is incomplete (at the moment)
When typical servos stop receiving a control signal, they stay where they are; while they won't actively hold their position, most require some force to backdrive. So if that's enough for your project, you can move each servo in turn, and sample inputs, set LEDs and such in between.
=======
Methods
=======
See comments in SimpleServo.h (and SimpleServo.m) for now.
*(( TODO: Document the additional methods in detail, add an example ))*
=======
License
=======
The MIT License (MIT)
Copyright (c) 2013 Benjamin Holt
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,151 @@
/*
Copyright (c) 2013 Benjamin Holt
The MIT License (MIT) - See README for complete license
*/
#include <SimpleServo.h>
///// Setup /////
SimpleServo::SimpleServo() :
_pin(0xff),
_degrees(0xff),
_microseconds(0),
_maxDegrees(180),
_millisPer60degrees(230), // default from http://www.servodatabase.com/servo/futaba/s3003
_minWriteMillis(0),
_maxWriteMillis(0xffff),
_minPulse(700),
_maxPulse(2300),
_pulseMillis(16)
{}
uint8_t SimpleServo::attach(uint8_t p) {
_pin = p;
_degrees = 0xff;
_microseconds = 0;
// Deliberately not (re)initializing servo parameters
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
return 1;
}
void SimpleServo::detach() {
_pin = 0xff;
}
uint8_t SimpleServo::attached() {
return _pin != 0xff;
}
/////
///// Movement /////
void SimpleServo::_pulse(uint16_t ms) {
// This actually moves the servo
uint16_t elapsedMillis = 0;
while (elapsedMillis < ms) {
digitalWrite(_pin,HIGH);
delayMicroseconds(_microseconds);
digitalWrite(_pin,LOW);
if (ms > 0) { // 0ms: do the pulse, but that's it (probably a bad idea but, hey, if it works with your project, cool)
delay(_pulseMillis); // ENHANCEME: A hook to allow the client to make use (at their own risk of adding jitter) of these millis would be really nice
}
elapsedMillis += _pulseMillis + _microseconds / 1000 + 1;
}
}
void SimpleServo::writeMicrosecondsMillis(uint16_t us, uint16_t ms) {
_microseconds = us; // Allow unconstrained us
if (_minPulse <= us && us <= _maxPulse) {
_degrees = map(us, _minPulse, _maxPulse, 0, _maxDegrees);
} else {
_degrees = 0xff; // Out-of-range us do not convert sensibly to degrees
}
_pulse(ms); // And unconstrained ms, don't point this method at your foot.
}
void SimpleServo::writeMillis(uint8_t deg, uint16_t ms) {
_degrees = constrain(deg, 0, _maxDegrees);
_microseconds = constrain(map(_degrees, 0, _maxDegrees, _minPulse, _maxPulse), _minPulse, _maxPulse);
_pulse(ms); // Allow unconstrained millis
}
uint32_t SimpleServo::millisToTarget(uint8_t deg) {
uint8_t delta = abs(_degrees - deg); // if degrees is 0xff, this will over-estimate, so don't do anything special in that case
return ((uint32_t)_millisPer60degrees * delta) / 60;
}
void SimpleServo::writeMicroseconds(uint16_t us) {
// Simplest to do the us -> deg conversion here, so just finish the job
_microseconds = constrain(us, 0, _maxPulse); // keep degrees sane as much as possible, you have writeMicrosecondsMillis if you need to bend the rules
uint8_t target = map(us, _minPulse, _maxPulse, 0, _maxDegrees);
uint32_t millis = millisToTarget(target);
millis = constrain(millis, _minWriteMillis, _maxWriteMillis);
_degrees = target;
_pulse((uint16_t)millis);
}
void SimpleServo::write(uint8_t deg) {
uint32_t millis = millisToTarget(deg);
millis = constrain(millis, _minWriteMillis, _maxWriteMillis);
writeMillis(deg, (uint16_t)millis);
}
uint8_t SimpleServo::read() {
return _degrees;
}
uint16_t SimpleServo::readMicroseconds() {
return _microseconds;
}
/////
///// Servo Parameters /////
void SimpleServo::setMaximumDegrees(uint8_t deg) {
_maxDegrees = deg;
}
void SimpleServo::setMillisPer60Degrees(uint16_t ms) {
_millisPer60degrees = ms;
}
void SimpleServo::setMinimumMillis(uint16_t ms) {
_minWriteMillis = ms;
}
void SimpleServo::setMaximumMillis(uint16_t ms) {
_maxWriteMillis = ms;
}
void SimpleServo::setMinimumPulse(uint16_t us) {
_minPulse = us;
}
void SimpleServo::setMaximumPulse(uint16_t us) {
_maxPulse = us;
}
void SimpleServo::setPulseMillis(uint8_t ms) {
_pulseMillis = ms;
}
/////

View File

@@ -0,0 +1,59 @@
/*
Copyright (c) 2013 Benjamin Holt
The MIT License (MIT) - See README for complete license
*/
#ifndef _SimpleServo_h_
#define _SimpleServo_h_
#include <inttypes.h>
#include <WProgram.h>
class SimpleServo {
private:
// Movement
uint8_t _pin;
uint8_t _degrees;
uint16_t _microseconds;
// Servo Parameters
// REM: nasty bit about when to constrain vs. not... more below...
uint8_t _maxDegrees;
uint16_t _millisPer60degrees;
uint16_t _minWriteMillis;
uint16_t _maxWriteMillis;
uint16_t _minPulse;
uint16_t _maxPulse;
uint8_t _pulseMillis;
void _pulse(uint16_t);
public:
// TODO: update keywords file
// Setup
SimpleServo();
uint8_t attach(uint8_t); // Note: resets position, but not servo parameters, doesn't signal servo
void detach();
uint8_t attached();
// Movement
void write(uint8_t);
void writeMicroseconds(uint16_t);
uint32_t millisToTarget(uint8_t); // Estimates time from current (expected) position to a target; if millisPer60Degrees is too small, this will come up short and the servo may not reach the target, too large and the write methods may signal longer than needed
void writeMillis(uint8_t, uint16_t); // Allows unconstrained millis
void writeMicrosecondsMillis(uint16_t, uint16_t); // Allows unconstrained microseconds and millis, full manual control
uint8_t read();
uint16_t readMicroseconds();
// Servo Parameters
void setMaximumDegrees(uint8_t); // A lot of servos move a bit more than 180
void setMillisPer60Degrees(uint16_t); // For estimating time from last set position to newly requested position; different for every servo, http://www.servodatabase.com has many specs, default is 230 from Futaba S3003
void setMinimumMillis(uint16_t); // The smallest time to signal the servo; some write methods do not enforce this
void setMaximumMillis(uint16_t); // This longest time to signal the servo, even if it probably has not yet reached the requested position; some write methods do not enforce this
void setMinimumPulse(uint16_t); // The shortest pulse (in microseconds) to send to the servo, maps to 0deg; only writeMicrosecondsMillis does not enforce this
void setMaximumPulse(uint16_t); // The shortest pulse (in microseconds) to send to the servo, maps to 0deg; only writeMicrosecondsMillis does not enforce this
void setPulseMillis(uint8_t); // Delay between pulses; defaults to 16 which is a bit quicker than spec. Experiment, different servos may react differently
};
#endif // _SimpleServo_h_

View File

@@ -0,0 +1,27 @@
#######################################
# Syntax Coloring Map SimpleServo
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
SimpleServo KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
attach KEYWORD2
attached KEYWORD2
detach KEYWORD2
read KEYWORD2
setMaximumPulse KEYWORD2
setMinimumPulse KEYWORD2
write KEYWORD2
writeMillis KEYWORD2
writeMicrosecondsMillis KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################