Skip to content

Servo library #358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion hardware/esp8266com/esp8266/cores/esp8266/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,29 @@ void yield(void);
#define timer1_enabled() ((T1C & (1 << TCTE)) != 0)
#define timer1_interrupted() ((T1C & (1 << TCIS)) != 0)

typedef void(*timercallback)(void);

void timer1_isr_init(void);
void timer1_enable(uint8_t divider, uint8_t int_type, uint8_t reload);
void timer1_disable(void);
void timer1_attachInterrupt(void (*userFunc)(void));
void timer1_attachInterrupt(timercallback userFunc);
void timer1_detachInterrupt(void);
void timer1_write(uint32_t ticks); //maximum ticks 8388607

// timer0 is a special CPU timer that has very high resolution but with
// limited control.
// it uses CCOUNT (ESP.GetCycleCount()) as the non-resetable timer counter
// it does not support divide, type, or reload flags
// it is auto-disabled when the compare value matches CCOUNT
// it is auto-enabled when the compare value changes
#define timer0_interrupted() (ETS_INTR_PENDING() & (_BV(ETS_COMPARE0_INUM)))
#define timer0_read() ((__extension__({uint32_t count;__asm__ __volatile__("esync; rsr %0,ccompare0":"=a" (count));count;})))
#define timer0_write(count) __asm__ __volatile__("wsr %0,ccompare0; esync"::"a" (count) : "memory")

void timer0_isr_init(void);
void timer0_attachInterrupt(timercallback userFunc);
void timer0_detachInterrupt(void);

// undefine stdlib's abs if encountered
#ifdef abs
#undef abs
Expand Down
51 changes: 45 additions & 6 deletions hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,33 @@
*/
#include "wiring_private.h"
#include "pins_arduino.h"
#ifdef __cplusplus
extern "C" {
#endif

#include "c_types.h"
#include "ets_sys.h"

void (*timer1_user_cb)(void);
#ifdef __cplusplus
}
#endif

/ ------------------------------------------------------------------ -
// timer 1

static volatile timercallback timer1_user_cb = NULL;

void timer1_isr_handler(void *para){
if((T1C & ((1 << TCAR) | (1 << TCIT))) == 0) TEIE &= ~TEIE1;//edge int disable
if ((T1C & ((1 << TCAR) | (1 << TCIT))) == 0) TEIE &= ~TEIE1;//edge int disable
T1I = 0;
if(timer1_user_cb) timer1_user_cb();
if (timer1_user_cb) timer1_user_cb();
}

void timer1_isr_init(){
ETS_FRC_TIMER1_INTR_ATTACH(timer1_isr_handler, NULL);
}

void timer1_attachInterrupt(void (*userFunc)(void)) {
void timer1_attachInterrupt(timercallback userFunc) {
timer1_user_cb = userFunc;
ETS_FRC1_INTR_ENABLE();
}
Expand All @@ -52,11 +63,39 @@ void timer1_enable(uint8_t divider, uint8_t int_type, uint8_t reload){
}

void timer1_write(uint32_t ticks){
T1L = ((ticks) & 0x7FFFFF);
if((T1C & (1 << TCIT)) == 0) TEIE |= TEIE1;//edge int enable
T1L = ((ticks)& 0x7FFFFF);
if ((T1C & (1 << TCIT)) == 0) TEIE |= TEIE1;//edge int enable
}

void timer1_disable(){
T1C = 0;
T1I = 0;
}

//-------------------------------------------------------------------
// timer 0

static volatile timercallback timer0_user_cb = NULL;

void timer0_isr_handler(void* para){
if (timer0_user_cb) {
timer0_user_cb();
}
}

void timer0_isr_init(){
ETS_CCOMPARE0_INTR_ATTACH(timer0_isr_handler, NULL);
}

void timer0_attachInterrupt(timercallback userFunc) {
timer0_user_cb = userFunc;
ETS_CCOMPARE0_ENABLE();
}

void timer0_detachInterrupt() {
timer0_user_cb = NULL;
ETS_CCOMPARE0_DISABLE();
}



Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* Sweep
by BARRAGAN <http://barraganstudio.com>
This example code is in the public domain.

modified 28 May 2015
by Michael C. Miller
modified 8 Nov 2013
by Scott Fitzgerald

http://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


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

void loop()
{
int pos;

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 hardware/esp8266com/esp8266/libraries/Servo/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)
#######################################
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=Servo
version=1.0.2
author=Michael C. Miller
maintainer=GitHub/esp8266/arduino
sentence=Allows Esp8266 boards 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://arduino.cc/en/Reference/Servo
architectures=esp8266
93 changes: 93 additions & 0 deletions hardware/esp8266com/esp8266/libraries/Servo/src/Servo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
Servo.h - Interrupt driven Servo library for Esp8266 using timers
Copyright (c) 2015 Michael C. Miller. 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.
//
// This library uses time0 and timer1.
// Note that timer0 may be repurposed when the first servo is attached.
//
// Timers are seized as needed in groups of 12 servos - 24 servos use two
// timers, there are only two timers for the esp8266 so the support stops here
// 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 <Arduino.h>

// the following are in us (microseconds)
//
#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

// NOTE: to maintain a strict refresh interval the user needs to not exceede 8 servos
#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
#define MAX_SERVOS (ServoTimerSequence_COUNT * SERVOS_PER_TIMER)

#if defined(ESP8266)

#include "esp8266/ServoTimers.h"

#else

#error "This library only supports esp8266 boards."

#endif

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
uint16_t _minUs;
uint16_t _maxUs;
};

#endif
Loading