ServoTimeTimer1.cpp does not compile

I didn't initially figure out how to use libraries in Arduino 0009 so I just added ServoTimeTimer1.cpp to my sketch, along with the .h file. The compiler does see it & tries to compile it, but I get this error message from the compiler:

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

Some searching found that TICIE1 is an ATMega8 register. However, my board type is correctly set to atmega168. I get this error with the .cpp file straight out of the zipped file--no edits.

I tried eliminating this error by inserting this in the ServoTimeTimer1 code, above the seizeTimer1() code:

#define TICIE1

And this did eliminate the error but I got a different one:

In static member function 'static void ServoTimeTimer1::seizeTimer1()':
error: expected primary-expression before ')' token.

Unzipping the object file ServoTimeTimer1.o and getting rid of the now-unneeded .cpp file eliminated the errors and my sketch compiled. But now I'm worried. It looks to me like the .o file was most likely compiled for the atmega8--and I can't get the cpp file to compile. So this library won't work on my Diecemilia...?

I haven't changed my Arduino 0009 environment. The 'blink' program compiles OK, along with a number of other sketches I've written, so the compiler doesn't appear to be broken.

Does anyone have any insight into what's going on here?

Thanks
Mark

remove the expression _BV(TICIE1)

doing #define TICIE1

changes:
TIMSK0 &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
to:
TIMSK0 &= ~(_BV() | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );

This expression will compile but I have no idea if it will work :wink:
TIMSK0 &= ~(_BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );

OK--if it had been a snake it would have bit me!

However, additional searching through the device-specific IO files has shown that the register addresses (and bit assignments) for the Mega8 and Mega168 are different. So it looks to me like that the precompiled library file is not compatible with the Diecemilia. I also believe that the TIMSK0 probably should be changed to TIMSK1. I will try out my modified code & report back when I have a chance.

This brings up another point. As written, the precompiled library file clearly is not platform-independent. Is there a runtime variable (maybe in libc?) that can be used to write code that will run on either a mega8 or mega168--maybe like the following:

if(__DEVICE == ATMEGA168)
{ device-specific code here }
else
{ device-specific code here or error message}

where __DEVICE is set accordingly.

I see in other threads that some folks are looking at porting the Arduino IDE to a Mega128, so this issue could become even more important--supporting multiple hardware platforms could become a nightmare otherwise!

Mark

Yea, check out the source code for the Arduino core for some examples, e.g. wiring.c.

you are definitely on the right track, the Timer1 interrupt mask for theATmega168 should be TIMSK1 as you deduced.

The method to produce code targeted for a platform is actually used in that servo library, its just using the wrong code in the #define:
#if defined(AVR_ATmega168)
// platform specific code here?.
#endif

Did you try changing TICIE1 by ICIE1?

Adilson, changing TICIE1 to ICIE1 should also work but is not necessary (if TICIE1 is removed). ICIE1 is the input capture interrupt and the original code was trying to turn it off. It is off by default on the Arduino so the expression to turn it off is not needed and can be removed.

Your suggestion would make sure it was off just in case something else had fiddled with that bit, so it's a good thing to do even though it shouldn't matter in this case.

mem pointed me to this thread,

I also could not get it to work :frowning:

The servo just starts to spin, but the loop was not executed anymore (debug Serial.print() did not print in the monitor).

I just discovered: any delay() will make the app not working anymore!

Why? And how to work around this?

Carsten

Carsten, are you running the example code from here?
http://www.arduino.cc/playground/ComponentLib/Servotimetimer1

If you have made any changes to that sketch or are runing something else, could you post the code you are running.

If you are running the original sketch, try reducing the pulse width range by changing the code to:
servo1.write( potVal1 + 1000);
The range used in the original sketch is a more than some servos can handle. The change limits the pulse width range from 1000 to just over 2000 microseconds.

Carsten, are you running the example code from here?
Arduino Playground - Servotimetimer1

If you have made any changes to that sketch or are runing something else, could you post the code you are running.
[...]

Its not about the pulse-length, the original code works (so does my little robot now, following a light) but as soon I added some delay() it fails.

I cant check right now, but as soon as I deleted the delay() lines it started to work.

Carsten

#include <ServoTimeTimer1.h>

#define servoPin1 9
#define servoPin2 10
#define potPin1 0
#define potPin2 1

ServoTimeTimer1 servo1;
ServoTimeTimer1 servo2;

int val = 0;
int dir = 0;
int pot;
int ster = 0;

void setup()
{
  servo1.attach(servoPin1);
  servo2.attach(servoPin2);
  Serial.begin(38400);
}

void setServos(int ldir , int rdir)
{
  Serial.print(1500+rdir*50);
  Serial.print(" | ");
  Serial.println(1500-rdir*50);
  // Linkes Servo (left servo)
  servo1.write(1500-ldir*50+35);
  // Rechtes Servo (right servo)
  servo2.write(1500+rdir*55+40); 
  }

void loop()
{
  val = 0;
  dir = 0;
  for (int i=0; i<11; i++){
    val = val + analogRead(potPin1);
    dir = dir + analogRead(potPin2);
    }
  pot = (val-5120)/512;
  Serial.print(pot);
  Serial.print(" | ");
  ster = (dir-5120)/512 ;
  Serial.print(ster);
  Serial.print(" | ");

setServos(pot+ster, pot-ster);
    
//delay(5);  // just enabling this line makes the servos not working anymore (random(?) initial velocity)
        
}

This is the actual (working) code of my little light following "robot" (a half-dead cockroach is much more intelligent ;-)).

Uncommenting the last line with "delay()" will make it fail.

Carsten

I can't see any reason why the code you posted would not work with the delay .
Have you tried running the example sketch that comes with that library with the delay added to see if that works?

Off the subject but I was curious looking at the code of your sketch. It seems that your pot value is biased toward the left (the max pot val is 1024 * 11 but you divide by 512 * 5, so when the pot is centered ster will not be zero. I was wondering if you did that on purpose and if so what the reason is.

Anyway, please do say if the example sketch has the same problem with the delay.

I can't see any reason why the code you posted would not work with the delay .
Have you tried running the example sketch that comes with that library with the delay added to see if that works?

Off the subject but I was curious looking at the code of your sketch. It seems that your pot value is biased toward the left (the max pot val is 1024 * 11 but you divide by 512 * 5, so when the pot is centered ster will not be zero. I was wondering if you did that on purpose and if so what the reason is.

Anyway, please do say if the example sketch has the same problem with the delay.

I also tried (not today) with the sample code (I had no pot, so I used fixed values or contious values) and it did not work either. It is not my code not working :wink: (I always wanted to say that...). Maybe the library mixes/intereferes something with the delay function? Or vice versa.

My pot value is biased because of the LDR sensors I used and the servos which need some "calibration".

Carsten

The servo library uses timer1 and delay uses timer0 so its not clear why they should affect each other. Perhaps someone that has more experience with the servoTimeTimer1 could shed some light on what is happening.

But here is a suggestion you may want to play around with. That library sets up timer1 so each count is half a microsecond. Timer1 is a 16 bit counter and the register holding the high byte of the count, TCNT1H, is incremented every 128 microseconds. You may want to try to write your own delay function that waits for a given number of ticks of TCNT1H. You will need to verify that the counter increments as expected in the PWM mode that the library sets it to and don't forget that your code needs to handle the register overflowing back to 0 every 32768 microseconds.

Based on suggestions by mem, tom and others, and light testing of a one servo configuration.

Using ICIE1 instead of TICIE1 allows the file to compile.
Changing TMSK0 to TMSK1 fixes a bad interaction with delay().
With those 2 simple changes the library is behaving well for me so far.

So, in the member function
ServoTimeTimer1::seizeTimer1()
the line

    TIMSK0 &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );

becomes

    TIMSK1 &= ~( _BV(ICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );

Maybe this is all that is needed to use the library.
Thanks for the help!

It would be great if someone could post the corrected version of the library back to the playground.

It looks like that has just been done, thanks tof