Skip to content
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

Bugg in servo library with detach(), after can't use analogWrite on pin 9 or 10 #3860

Closed
JLP69 opened this issue Sep 24, 2015 · 7 comments
Closed
Assignees
Labels
Library: Servo The Servo Arduino library Type: Bug

Comments

@JLP69
Copy link

JLP69 commented Sep 24, 2015

I'm using the servo library, and I've finding that detach() method doesn't work as in the reference. I've reading some post about it. It seems that the timers aren't reseted by this method for using PWM output on the pins 9 and 10.
And I've found something in the library code to be changed.
In the Servo.cpp, in the finISR function (that is used for disable the timer) there is no code for doing that for Arduino board.
...

else

//For arduino - in future: call here to a currently undefined function to reset the timer
TCCR1B = 0;
TCCR1B=_BV(CS11);
TCCR1B=_BV(CS10);
TCCR1A=_BV(WGM10);
TIMSK1=0;

endif

After few trials, it seems working. I think it may be included in source code.

@cmaglie cmaglie added Type: Bug Library: Servo The Servo Arduino library labels Sep 28, 2015
@michaelmargolis
Copy link

The suggested code will not work as expected on boards that have more than one 16 bit timer, such as the mega.

When I submitted this library, I suggested functions added to the core to disable timers, similar to the way the wiring project handles this. That way, any library that needed to restore a timer to it default state would be able to call the same function used by the core when the runtime is initialized.
That would insulate the library from any future changes to the timer initialization in the core.

In the absence of that, you could add the timer init code into the if(timer== ... statements with the #if defined WIRING moved to surround each timerDetach call.

Michael Margolis

@JLP69
Copy link
Author

JLP69 commented Nov 9, 2015

Thanks for your answer,
But why couldn’t we use a code like this for applying this fix only for the Uno board :

static void finISR(timer16_Sequence_t timer)
{
  //disable use of the given timer
#if defined WIRING   // Wiring
  if (timer == _timer1) {
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
    TIMSK1 &=  ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
#else
    TIMSK &=  ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
#endif
    timerDetach(TIMER1OUTCOMPAREA_INT);
  }
  else if (timer == _timer3) {
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
    TIMSK3 &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
#else
    ETIMSK &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
#endif
    timerDetach(TIMER3OUTCOMPAREA_INT);
  }
#elif defined(__AVR_ATmega328P__)
  //For Arduino Uno
  TCCR1B = 0;
  TCCR1B = _BV(CS11);
  TCCR1B = _BV(CS10);
  TCCR1A = _BV(WGM10);
  TIMSK1 = 0;
#else
  //For other arduino - in future: call here to a currently undefined function to reset the timer
#endif
}

Jean-Luc PELLIGOTTI

@michaelmargolis
Copy link

The issue would still exist for users of other boards and would re-occur for all AVR boards if the timer init code in the core was changed without the library also be modified.

If restoring timers to the initial state is considered important then I would hope that that a clean solution would be implemented. In my view, that involves calling a function in the core to set a timer to the initial state. That way, the library code will not go out of sync if the core timer init code is changed.
But given that the library is over six years old and this issue has just come to the fore, perhaps it will be sufficient for now to modify the documentation until resources are available to do this propelry.

@Cration
Copy link

Cration commented Jan 15, 2016

It should be like this:
TCCR1B =_BV(CS11) | _BV(CS10);
TCCR1A =_BV(WGM10);
TIMSK1 = 0;

@michaelmargolis
Copy link

For reasons stated above, it is not good practice for the servo library to make assumptions about how the core initializes timers at startup. If the current core timer initialization code was moved into separate functions, the servo library could call the appropriate initialization function in its detach method.

If you think this needs addressing, perhaps you could raise an issue to modify wiring.c to add something similar to Wiring's timerAttach and timerDetach methods to handle the initialization of timers. Stubs are already in the servo detach code to call a method to reinitialize a timer if one was available in wiring.c.

@matthijskooijman
Copy link
Collaborator

FWIW, I agree with @michaelmargolis here. To fix this, a proper API should be added to the core, instead of hardcoding things in the servo library. Making this API portable might be tricky, though it does not need to be portable to other architectures, only boards, I think.

@agdl
Copy link
Member

agdl commented Jul 12, 2016

This issue was moved to arduino-libraries/Servo#1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Library: Servo The Servo Arduino library Type: Bug
Projects
None yet
Development

No branches or pull requests

6 participants