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

support Servo Libraries #68

Closed
hathach opened this issue Jul 24, 2017 · 6 comments
Closed

support Servo Libraries #68

hathach opened this issue Jul 24, 2017 · 6 comments
Milestone

Comments

@hathach
Copy link
Member

hathach commented Jul 24, 2017

Standard Servo Libraries is already ported to work with nrf52 on Primo board
https://github.com/arduino-libraries/Servo/tree/master/src/nrf52

It is based on several Nordic peripheral driver in SDK which we lack ( due to restricted license).
https://github.com/arduino-org/arduino-core-nrf52/tree/master/cores/arduino/components

However since the latest sdk 13 open the license to BSD like. We could include those and get the Servo support

@hathach hathach added this to the 0.7.0 milestone Jul 24, 2017
@hathach hathach mentioned this issue Jul 24, 2017
@hathach
Copy link
Member Author

hathach commented Jul 24, 2017

to many differences, It is easier to implement Servo with our own HardwarePWM :(

@microbuilder
Copy link
Contributor

Anything that's compatible at the higher level API level is fine, I think.

@hathach
Copy link
Member Author

hathach commented Jul 24, 2017

the hardware PWM works fine, we just need to to wrap it up with the servo API and have some tests to make sure it works. I am finding those little servo to hook up :D

hathach added a commit that referenced this issue Jul 25, 2017
@hathach
Copy link
Member Author

hathach commented Jul 25, 2017

the update code should work, though more tests should be carried out.

@hathach hathach closed this as completed Jul 25, 2017
@ichbtm
Copy link
Contributor

ichbtm commented Mar 30, 2018

Don't know if I post at the right place.
Your implementation use hardcoded pulse limits and doesn't use user values given to the attach function.
More, input of writeMicroseconds is not a µs value.
Maybe the following modifications should be nice ?

Servo.h :

//---convert int8_t to int16_t to be able to store a pulse width
int16_t min;                       // minimum pulse µs
int16_t max;                       // maximum pulse µs

servoTimers.h :

//---suppress hardcoded duty cycle values
//#define MIN_PULSE 55
//#define MAX_PULSE 284

//---add some named constants for clarity
//PWM_PRESCALER_PRESCALER_DIV_128 -> NRF_PWM_CLK_125kHz -> resolution 8µs
//MaxValue = 2500 -> PWM period = 20ms
//20ms - 50Hz
#define RESOLUTION 8
#define MAXVALUE 2500
#define CLOCKDIV PWM_PRESCALER_PRESCALER_DIV_128

Servo.cpp :

//--- use Servo.h limits by default
uint8_t Servo::attach(int pin) {
    return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
}

//--- use Servo.h limits and store user ones in structure
uint8_t Servo::attach(int pin, int min, int max) {
    if (this->servoIndex < MAX_SERVOS) {
        pinMode(pin, OUTPUT);                                   // set servo pin to output
        servos[this->servoIndex].Pin.nbr = pin;

        if(min < MIN_PULSE_WIDTH) min = MIN_PULSE_WIDTH;
        if (max > MAX_PULSE_WIDTH) max = MAX_PULSE_WIDTH;
        this->min  = min;
        this->max  = max;
        servos[this->servoIndex].Pin.isActive = true;

        // Adafruit, add pin to 1 of available Hw PWM
        for(int i=0; i<HWPWM_MODULE_NUM; i++) {
            if ( HwPWMx[i]->addPin(pin) ) {
                HwPWMx[i]->setMaxValue(MAXVALUE);
                HwPWMx[i]->setClockDiv(CLOCKDIV);
                break;
            }
        }
    }
    return this->servoIndex;
}

//---use user limits in µs instead of hardcoded values
void Servo::write(int value) {
    if (value < 0)
    value = 0;
    else if (value > 180)
    value = 180;
    value = map(value, 0, 180, this->min, this->max);
    writeMicroseconds(value);
}

//---use µs as input value instead of duty cycle value
void Servo::writeMicroseconds(int value) {
    uint8_t pin = servos[this->servoIndex].Pin.nbr;
    for(int i=0; i<HWPWM_MODULE_NUM; i++) {
        if ( HwPWMx[i]->writePin(pin, value/RESOLUTION) ) break;
    }
}

Another problem I found is that sometimes the PWM signal is inverted. But I have no other solutions than chaining two attach, detach sequence...

@hathach
Copy link
Member Author

hathach commented Jul 11, 2018

@ichbtm thank you very much for your help, somehow this issue fall off our radar until recently :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants