Servo Libraries - Arduino 0010

I am playing with the the Servo and ServoTimer1 libraries from the playground and using the sample code given and both libraries give the same error at compile time on Arduino 0010

: In function setup': undefined reference to ServoTimer1::attach(int)'o: In function loop': o: In function __static_initialization_and_destruction_0':

The IDE always highlights the last line before the first call to the 'attach' command as the error whether its a comment or code. I know its something simple that I am overlooking ... but I am just drawing a blank.

cheers ... BBR

//Example code for using ServoTimer1 library
// hardware control of up to two servos, on Arduino pins 9 & 10 

#include <ServoTimer1.h>

ServoTimer1 servo1;
ServoTimer1 servo2;

void setup()
{
  pinMode(1,OUTPUT);
  servo1.attach(9);
  servo2.attach(10);
  Serial.begin(19200);
  Serial.print("Ready");
}

void loop()
{
  static int v = 0;

  if ( Serial.available()) {
    char ch = Serial.read();

    switch(ch) {
      case '0'...'9':
        v = v * 10 + ch - '0';
        break;
      case 's':
        servo1.write(v);
        v = 0;
        break;
      case 'w':
        servo2.write(v);
        v = 0;
        break;
      case 'd':
        servo2.detach();
        break;
      case 'a':
        servo2.attach(10);
        break;
    }
  }
        // Notice that no ServoTimer1::refresh() is needed.
}

The library code is here

#include <ServoTimer1.h>
#include <avr/interrupt.h>

/*
  ServoTimer1.h - Hardware Servo Timer Library
  Author: Jim Studt, jim@federated.com
  Copyright (c) 2007 David A. Mellis.  All right reserved.

  --boiler plate removed--
*/

uint8_t ServoTimer1::attached9 = 0;
uint8_t ServoTimer1::attached10 = 0;

void ServoTimer1::seizeTimer1()
{
    uint8_t oldSREG = SREG;

    cli();
    TCCR1A = _BV(WGM11); /* Fast PWM, ICR1 is top */
    TCCR1B = _BV(WGM13) | _BV(WGM12) /* Fast PWM, ICR1 is top */
      | _BV(CS11) /* div 8 clock prescaler */
      ;
    OCR1A = 3000;
    OCR1B = 3000;
    ICR1 = clockCyclesPerMicrosecond()*(20000L/8);  // 20000 uS is a bit fast for the refresh, 20ms, but 
                                                    // it keeps us from overflowing ICR1 at 20MHz clocks
                                                    // That "/8" at the end is the prescaler.
#if defined(__AVR_ATmega168__)
    TIMSK0 &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
#else
    TIMSK &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
#endif
    SREG = oldSREG;  // undo cli()    
}

void ServoTimer1::releaseTimer1()
{;}


#define NO_ANGLE (0xff)

ServoTimer1::ServoTimer1() : pin(0),angle(NO_ANGLE),min16(34),max16(150)
{}

void ServoTimer1::setMinimumPulse(uint16_t t)
{
    min16 = t/16;
}

void ServoTimer1::setMaximumPulse(uint16_t t)
{
    max16 = t/16;
}

uint8_t ServoTimer1::attach(int pinArg)
{
    if ( pinArg != 9 && pinArg != 10) return 0;

    pin = pinArg;
    angle = NO_ANGLE;
    digitalWrite(pin,0);
    pinMode(pin,OUTPUT);

    if ( !attached9 && !attached10) seizeTimer1();

    // muck with timer flags
    if ( pin == 9) {
      attached9 = 1;
      TCCR1A = TCCR1A & ~_BV(COM1A0) | _BV(COM1A1);
    } else {
      attached10 = 1;
      TCCR1A = TCCR1A & ~_BV(COM1B0) | _BV(COM1B1);
    }
    return 1;
}

void ServoTimer1::detach()
{
    // muck with timer flags
    if ( pin == 9) {
      attached9 = 0;
      TCCR1A = TCCR1A & ~_BV(COM1A0) & ~_BV(COM1A1);
    } else {
      attached10 = 0;
      TCCR1A = TCCR1A & ~_BV(COM1B0) & ~_BV(COM1B1);
    }
    pinMode(pin,INPUT);

    if ( !attached9 && !attached10) releaseTimer1();
}

void ServoTimer1::write(int angleArg)
{
    uint16_t p;

    if ( angleArg < 0) angleArg = 0;
    if ( angleArg > 180) angleArg = 180;
    angle = angleArg;

    // bleh, have to use longs to prevent overflow, could be tricky if always a 16MHz clock, but not true
    // That 8L on the end is the TCNT1 prescaler, it will need to change if the clock's prescaler changes,
    // but then there will likely be an overflow problem, so it will have to be handled by a human.
    p = (min16*16L*clockCyclesPerMicrosecond() + (max16-min16)*(16L*clockCyclesPerMicrosecond())*angle/180L)/8L;
    if ( pin == 9) OCR1A = p;
    else OCR1B = p;
}

uint8_t ServoTimer1::read()
{
    return angle;
}

uint8_t ServoTimer1::attached()
{
    if ( pin == 9 && attached9) return 1;
    if ( pin == 10 && attached10) return 1;
    return 0;
}

void ServoTimer1::refresh()
{
    ;
}

Did youy get the "pached" library ?

http://www.ladyada.net/make/mshield/download.html

Or this one if Atmega168:
http://www.arduino.cc/playground/uploads/ComponentLib/servotimetimer1_168.zip

That Library also has the same problem ...

ServoTimer1.cpp: In static member function 'static void ServoTimer1::seizeTimer1()':
ServoTimer1.cpp:43: error: 'TICIE1' was not declared in this scope

I just tried the one in the playground and it compiles without error on version 0010 and 0011 :-?

Are you sure that you have the correct version in the ServoTimer1 library directory and you deleted ServoTimer1.o after you copied it in?

Just Add

#include <Servo.h>

below the

#include <ServoTimer1.h>

Of course you need to install the servo library as well before doing this !

At that's what I have in the example and without it it does not compile !

Mellis and I put our heads together on this at the Boston Arduino Users Group Meeting Saturday and pounded it out, the TICIE1 reference in the copy I had should have been deleted ... all is now well in Mudville! At this point I am not sure which library I had the patched one from Lady Ada or what ... but it now works and my test program compiles clean, now that I am back from Beantown (3.5 hours each way) and get some sleep ... tomorrow, I will dig my servos back out of the drawer and check them out. Thanks for the help ...

p.s The Boston Arduino meeting was fun ... Mellis, Paul Badger (Modern Devices, the BBB), and I (Wulfden Freeduino) and about 15-- others had several hours of playing with Arduino toys and software/hardware discussions and show and tell!

There's a great Burrito shop with its own free WiFi, two doors down from where they held the meeting, PB and I went and gorged for dinner!

cheers ... BBR