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

Period improperly calculated in Servo library for megaavr microcontrollers (Arduino Nano Every) #59

Open
tomalmy opened this issue Jul 14, 2020 · 0 comments
Labels
topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project

Comments

@tomalmy
Copy link

tomalmy commented Jul 14, 2020

This was submitted to the wrong area, so is being resubmitted here. Excuse me for lack of familiarity with GitHub.

The ServoHandler function in libraries/Servo/src/megaavr/Servo.cpp improperly calculates the wait time for the refresh period to expire. This certainly came about from the differences between ATmega328P and ATmega4809 Timer/Counters. The number of ticks into the period must be accumulated to calculate the new CCMP value necessary. This should have been done with the tcCounterValue variable, which I have done here. I'm providing my fix for consideration.

void ServoHandler(int timer)
{
	static uint16_t tcCounterValue = 0;
    if (currentServoIndex[timer] < 0) {
        // Write compare register
        _timer->CCMP = 0;
    } else {
        if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) {
            digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW);   // pulse this channel low if activated
        }
    }

    // Select the next servo controlled by this timer
    currentServoIndex[timer]++;

    if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
        if (SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) {   // check if activated
            digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH);   // it's an active channel so pulse it high
        }

        // Get the counter value
        tcCounterValue += (_timer->CCMP = (uint16_t) (SERVO(timer, currentServoIndex[timer]).ticks));
    }
    else {
        // finished all channels so wait for the refresh period to expire before starting over

        if (tcCounterValue + 4UL < usToTicks(REFRESH_INTERVAL)) {   // allow a few ticks to ensure the next OCR1A not missed
            _timer->CCMP = (uint16_t) usToTicks(REFRESH_INTERVAL) - tcCounterValue;
        }
        else {
            _timer->CCMP = (uint16_t) (4UL);   // at least REFRESH_INTERVAL has elapsed
        }
		tcCounterValue = 0;
        currentServoIndex[timer] = -1;   // this will get incremented at the end of the refresh period to start again at the first channel
    }

    /* Clear flag */
    _timer->INTFLAGS = TCB_CAPT_bm;
}
@per1234 per1234 added type: imperfection Perceived defect in any part of project topic: code Related to content of the project itself labels Jul 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project
Projects
None yet
Development

No branches or pull requests

2 participants