Skip to content

Commit 456cb4a

Browse files
committed
fix PWM max_value type cause incorrect servo behavior (640Hz instead of 50hz)
1 parent 4614264 commit 456cb4a

File tree

3 files changed

+16
-64
lines changed

3 files changed

+16
-64
lines changed

cores/nRF5/HardwarePWM.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class HardwarePWM
5050
uint8_t _count;
5151
uint16_t _seq0[MAX_CHANNELS];
5252

53-
uint8_t _max_value;
53+
uint16_t _max_value;
5454
uint8_t _clock_div;
5555

5656
void _start(void);

libraries/Servo/src/Servo.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@
7575

7676
#define Servo_VERSION 2 // software version of this library
7777

78-
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
79-
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
78+
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
79+
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
8080
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
8181
#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
8282

@@ -112,7 +112,9 @@ class Servo
112112
private:
113113
uint8_t servoIndex; // index into the channel data for this servo
114114
int16_t min; // minimum pulse in µs
115-
int16_t max; // maximum pulse in µs
115+
int16_t max; // maximum pulse in µs
116+
117+
HardwarePWM* pwm;
116118
};
117119

118120
#endif

libraries/Servo/src/nrf52/Servo.cpp

Lines changed: 10 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,8 @@
2222
#include <Servo.h>
2323

2424

25-
static servo_t servos[MAX_SERVOS]; // static array of servo structures
26-
27-
uint8_t ServoCount = 0; // the total number of attached servos
28-
29-
30-
31-
//uint32_t group_pins[3][NRF_PWM_CHANNEL_COUNT]={{NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}, {NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}, {NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}};
32-
//static uint16_t seq_values[3][NRF_PWM_CHANNEL_COUNT]={{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
25+
static servo_t servos[MAX_SERVOS]; // static array of servo structures
26+
uint8_t ServoCount = 0; // the total number of attached servos
3327

3428
Servo::Servo()
3529
{
@@ -39,15 +33,14 @@ Servo::Servo()
3933
this->servoIndex = INVALID_SERVO; // too many servos
4034
}
4135

36+
this->pwm = NULL;
4237
}
4338

4439
uint8_t Servo::attach(int pin)
4540
{
46-
4741
return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
4842
}
4943

50-
5144
uint8_t Servo::attach(int pin, int min, int max)
5245
{
5346
if (this->servoIndex < MAX_SERVOS) {
@@ -56,6 +49,7 @@ uint8_t Servo::attach(int pin, int min, int max)
5649

5750
if(min < MIN_PULSE_WIDTH) min = MIN_PULSE_WIDTH;
5851
if (max > MAX_PULSE_WIDTH) max = MAX_PULSE_WIDTH;
52+
5953
//fix min if conversion to pulse cycle value is too low
6054
if((min/DUTY_CYCLE_RESOLUTION)*DUTY_CYCLE_RESOLUTION<min) min+=DUTY_CYCLE_RESOLUTION;
6155

@@ -69,21 +63,21 @@ uint8_t Servo::attach(int pin, int min, int max)
6963
{
7064
if ( HwPWMx[i]->addPin(pin) )
7165
{
72-
HwPWMx[i]->setMaxValue(MAXVALUE);
73-
HwPWMx[i]->setClockDiv(CLOCKDIV);
74-
66+
this->pwm = HwPWMx[i];
7567
break;
7668
}
7769
}
7870

71+
this->pwm->setMaxValue(MAXVALUE);
72+
this->pwm->setClockDiv(CLOCKDIV);
73+
7974
}
8075
return this->servoIndex;
8176
}
8277

8378
void Servo::detach()
8479
{
8580
servos[this->servoIndex].Pin.isActive = false;
86-
8781
// TODO Adafruit remove pin from HW PWM
8882
}
8983

@@ -102,38 +96,9 @@ void Servo::write(int value)
10296

10397
void Servo::writeMicroseconds(int value)
10498
{
105-
#if 0
106-
uint8_t channel, instance;
107-
uint8_t pin = servos[this->servoIndex].Pin.nbr;
108-
//instance of pwm module is MSB - look at VWariant.h
109-
instance=(g_APinDescription[pin].ulPWMChannel & 0xF0)/16;
110-
//index of pwm channel is LSB - look at VWariant.h
111-
channel=g_APinDescription[pin].ulPWMChannel & 0x0F;
112-
group_pins[instance][channel]=g_APinDescription[pin].ulPin;
113-
NRF_PWM_Type * PWMInstance = instance == 0 ? NRF_PWM0 : (instance == 1 ? NRF_PWM1 : NRF_PWM2);
114-
//configure pwm instance and enable it
115-
seq_values[instance][channel]= value | 0x8000;
116-
nrf_pwm_sequence_t const seq={
117-
seq_values[instance],
118-
NRF_PWM_VALUES_LENGTH(seq_values),
119-
0,
120-
0
121-
};
122-
nrf_pwm_pins_set(PWMInstance, group_pins[instance]);
123-
nrf_pwm_enable(PWMInstance);
124-
nrf_pwm_configure(PWMInstance, NRF_PWM_CLK_125kHz, NRF_PWM_MODE_UP, 2500); // 20ms - 50Hz
125-
nrf_pwm_decoder_set(PWMInstance, NRF_PWM_LOAD_INDIVIDUAL, NRF_PWM_STEP_AUTO);
126-
nrf_pwm_sequence_set(PWMInstance, 0, &seq);
127-
nrf_pwm_loop_set(PWMInstance, 0UL);
128-
nrf_pwm_task_trigger(PWMInstance, NRF_PWM_TASK_SEQSTART0);
129-
#else
13099
uint8_t pin = servos[this->servoIndex].Pin.nbr;
131100

132-
for(int i=0; i<HWPWM_MODULE_NUM; i++)
133-
{
134-
if ( HwPWMx[i]->writePin(pin, value/DUTY_CYCLE_RESOLUTION) ) break;
135-
}
136-
#endif
101+
if ( this->pwm ) this->pwm->writePin(pin, value/DUTY_CYCLE_RESOLUTION);
137102
}
138103

139104
int Servo::read() // return the value as degrees
@@ -143,26 +108,11 @@ int Servo::read() // return the value as degrees
143108

144109
int Servo::readMicroseconds()
145110
{
146-
#if 0
147-
uint8_t channel, instance;
148-
uint8_t pin=servos[this->servoIndex].Pin.nbr;
149-
instance=(g_APinDescription[pin].ulPWMChannel & 0xF0)/16;
150-
channel=g_APinDescription[pin].ulPWMChannel & 0x0F;
151-
// remove the 16th bit we added before
152-
return seq_values[instance][channel] & 0x7FFF;
153-
#else
154111
uint8_t pin=servos[this->servoIndex].Pin.nbr;
155112

156-
for(int i=0; i<HWPWM_MODULE_NUM; i++)
157-
{
158-
if ( HwPWMx[i]->checkPin(pin) )
159-
{
160-
return HwPWMx[i]->readPin(pin)*DUTY_CYCLE_RESOLUTION;
161-
}
162-
}
113+
if ( this->pwm ) return this->pwm->readPin(pin)*DUTY_CYCLE_RESOLUTION;
163114

164115
return 0;
165-
#endif
166116
}
167117

168118
bool Servo::attached()

0 commit comments

Comments
 (0)