Skip to content

Commit

Permalink
Provide workaround to use Servo.h if Servo library installed
Browse files Browse the repository at this point in the history
Sigh.
  • Loading branch information
SpenceKonde committed Jul 8, 2019
1 parent 50ede00 commit 1b770ac
Show file tree
Hide file tree
Showing 8 changed files with 475 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,16 @@ These parts all have 11 ADC channels available (except for the 8-pin parts, whic
* INTERNAL1V5
* INTERNAL2V5
* INTERNAL4V3
* EXTERNAL (1-series, not including 412/212 only)
* EXTERNAL (1-series, not including, 412/212 only)

### DAC Support (new in 1.0.1)
The 1-series parts have an 8-bit DAC which can generate a real analog voltage (note that this provides very low current and can only be used as a voltage reference, it cannot be used to power other devices). This generates voltages between 0 and the selected VREF (which cannot be VCC, unfortunately) - select the DAC VREF voltage from the Tools -> DAC Voltage Reference submenu. This voltage must be lower than Vcc to get the correct voltages. Call analogWrite() on the DAC pin to set the voltage to be output by the DAC. To turn off the DAC output, call digitalWrite() on that pin.

### Servo Support (new in 1.0.1)
This core provides a version of the Servo library which will select an appropriate timer (Timer B 0, except on the 3216, 3217, 1617, 1616 and 1614, where there is a Timer B 1 available; except on the aforementioned parts, tone cannot be used at the same time as the Servo library). Servo output is better the higher the clock speed - when using servos, it is recommended to run at the highest frequency permitted by the operating voltage to minimize jitter.

**Warning** If you have installed a version of the Servo library to your <sketchbook>/libraries folder (including via library manager), the IDE will use that version of the library (which is not compatible with these parts) instead of the one supplied with megaTinyCore (which is). As a workaround, a duplicate of the Servo library is included with a different name - to use it, `#include <Servo_megaTinyCore.h>` instead of `#include <Servo.h>`

### Pin Interrupts
All pins can be used with attachInterrupt() and detachInterrupt(), on RISING, FALLING, CHANGE, or LOW. All pins can wake the chip from sleep on CHANGE or LOW. Pins marked as ASync Interrupt pins on the pinout chart can be used to wake from sleep on RISING and FALLING edge as well.

Expand Down
27 changes: 27 additions & 0 deletions megaavr/libraries/Servo_megaTinyCore/examples/Knob/Knob.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
Controlling a servo position using a potentiometer (variable resistor)
by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
modified on 8 Nov 2013
by Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Knob
*/

#include <Servo.h>

Servo myservo; // create servo object to control a servo

int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin

void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}

void loop() {
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}

32 changes: 32 additions & 0 deletions megaavr/libraries/Servo_megaTinyCore/examples/Sweep/Sweep.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* Sweep
by BARRAGAN <http://barraganstudio.com>
This example code is in the public domain.
modified 8 Nov 2013
by Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Sweep
*/

#include <Servo.h>

Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0; // variable to store the servo position

void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}

void loop() {
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}

24 changes: 24 additions & 0 deletions megaavr/libraries/Servo_megaTinyCore/keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#######################################
# Syntax Coloring Map Servo
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

Servo KEYWORD1 Servo

#######################################
# Methods and Functions (KEYWORD2)
#######################################
attach KEYWORD2
detach KEYWORD2
write KEYWORD2
read KEYWORD2
attached KEYWORD2
writeMicroseconds KEYWORD2
readMicroseconds KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################
9 changes: 9 additions & 0 deletions megaavr/libraries/Servo_megaTinyCore/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=Servo_megaTinyCore
version=1.1.4
author=Spence Konde based on work by Michael Margolis, Arduino
maintainer=Spence Konde <[email protected]>
sentence=Allows megaTinyCore-supported parts to control a variety of servo motors.
paragraph=This library can control a great number of servos.<br />It makes careful use of timers: the library can control 12 servos using only 1 timer.<br />
category=Device Control
url=http://www.arduino.cc/en/Reference/Servo
architectures=megaavr
114 changes: 114 additions & 0 deletions megaavr/libraries/Servo_megaTinyCore/src/Servo_megaTinyCore.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
Copyright (c) 2009 Michael Margolis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

/*
A servo is activated by creating an instance of the Servo class passing
the desired pin to the attach() method.
The servos are pulsed in the background using the value most recently
written using the write() method.
Note that analogWrite of PWM on pins associated with the timer are
disabled when the first servo is attached.
Timers are seized as needed in groups of 12 servos - 24 servos use two
timers, 48 servos will use four.
The sequence used to sieze timers is defined in timers.h
The methods are:
Servo - Class for manipulating servo motors connected to Arduino pins.
attach(pin ) - Attaches a servo motor to an i/o pin.
attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
default min is 544, max is 2400
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
writeMicroseconds() - Sets the servo pulse width in microseconds
read() - Gets the last written servo pulse width as an angle between 0 and 180.
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
attached() - Returns true if there is a servo attached.
detach() - Stops an attached servos from pulsing its i/o pin.
*/

#ifndef Servo_h
#define Servo_h

#include <inttypes.h>

/*
* Defines for 16 bit timers used with Servo library
*
* If _useTimerX is defined then TimerX is a 16 bit timer on the current board
* timer16_Sequence_t enumerates the sequence that the timers should be allocated
* _Nbr_16timers indicates how many 16 bit timers are available.
*/

// Architecture specific include
#if defined(ARDUINO_ARCH_MEGAAVR) && defined(MEGATINYCORE)
#include "megaavr/ServoTimers.h"
#if (F_CPU==1000000)
#warning "Running at 1MHz results in unstable servo signal."
#endif
#else
#error "This version of the library only supports megaTinyCore-supported processors."
#endif

#define Servo_VERSION 2 // software version of this library

#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds

#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)

#define INVALID_SERVO 255 // flag indicating an invalid servo index

#if !defined(ARDUINO_ARCH_STM32F4)

typedef struct {
uint8_t nbr :6 ; // a pin number from 0 to 63
uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false
} ServoPin_t ;

typedef struct {
ServoPin_t Pin;
volatile unsigned int ticks;
} servo_t;

class Servo
{
public:
Servo();
uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
void detach();
void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // Write pulse width in microseconds
int read(); // returns current pulse width as an angle between 0 and 180 degrees
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
bool attached(); // return true if this servo is attached, otherwise false
private:
uint8_t servoIndex; // index into the channel data for this servo
int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
};

#endif
#endif
56 changes: 56 additions & 0 deletions megaavr/libraries/Servo_megaTinyCore/src/megaavr/ServoTimers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright (c) 2018 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

/*
* Defines for 16 bit timers used with Servo library
*
*/

// Adapted by Spence Konde for megaTinyCore 2019


#ifndef __SERVO_TIMERS_H__
#define __SERVO_TIMERS_H__

#ifdef TCB1
#define USE_TIMERB1
#else
#define USE_TIMERB0
#endif

#if !defined(USE_TIMERB1) && !defined(USE_TIMERB2) && !defined(USE_TIMERB0)
# error "Can't Happen: No timer available for servo. Please report this to github.com/SpenceKonde/megaTinyCore"
#endif

static volatile TCB_t* _timer =
#if defined(USE_TIMERB0)
&TCB0;
#endif
#if defined(USE_TIMERB1)
&TCB1;
#endif
#if defined(USE_TIMERB2)
&TCB2;
#endif

typedef enum {
timer0,
_Nbr_16timers } timer16_Sequence_t;


#endif /* __SERVO_TIMERS_H__ */
Loading

0 comments on commit 1b770ac

Please sign in to comment.