This is my first post on this forum, so, good morning/afternoon/night to everyone.
After reading the post from Mike, K8LH on this thread https://www.electro-tech-online.com/threads/pwm-basics.22650/ , I figured that using Timer1 & Comparator instead of the PWM module on 16f628 is better cause of the resolution I can get using 16bit on Timer1 instead of just 8bit on Timer2.
I code the same solution on C and compiled it on SDCC, I'm running only Linux on my PC, so can't use MPLab.
Here's the code :
I'm using the internal oscillator, so at 4Mhz I should get 1000 instructions per 1 ms.
So using 20000 for the period and 1500 for the duty cycle I should end up with 20ms and 1,5ms.
The problem is that the servo, a Futaba 3003 (the most common one), doesn't respond correctly, it goes all the way to left and stays there trying to go further, drawing current from the board.
The servo works correctly, I have a 1:10 RC model and always test it on the original Futaba radio, it works perfectly.
I use a 12v AC connected to a 7805 voltage regulator with a couple of capacitors on both legs to get a stable 5 V.
The strange thing is that if I plug a led on RB3, it blinks fast, so it's obvious that some kind of waveform is being feed to RB3.
The only difference of my code and Mike's is that he keeps adding the value to the CCPR register, and I put the period/duty value straight, without adding anything to it. This is the only part of his code that I couldn't figure out.
Can you guys spot any obvious error on my code ? I'm confident that I'm close to get this servo working correctly.
EDITED:
I just noticed that the servo tilts a little bit to right then it goes all the way to left and stays on trying to go further the limit.
Couple of questions that came in mind :
1. Do I need to reset the values on Timer1 on every interruption ?
2. What about that other "Special Event" comparator mode ?
3. How can I debug interruptions ? I installed MPLab on my father's PC, but it also doesn't stop on any breakpoint inside the interrupt method.
Thank you, and great forum by the way.
After reading the post from Mike, K8LH on this thread https://www.electro-tech-online.com/threads/pwm-basics.22650/ , I figured that using Timer1 & Comparator instead of the PWM module on 16f628 is better cause of the resolution I can get using 16bit on Timer1 instead of just 8bit on Timer2.
I code the same solution on C and compiled it on SDCC, I'm running only Linux on my PC, so can't use MPLab.
Here's the code :
Code:
#define PERIOD_CYCLE 20000 // 20 ms
#define DUTY_CYCLE 1500 // 1,5 ms
void InterruptHandler(void) interrupt 0 {
// Disable global interrupts
GIE = 0;
if (CCP1IF == 1) { // Interrupt on comparator module
// Clear the interrupt bit
CCP1IF = 0;
// Reset Timer 1 values
//TMR1H = 0;
//TMR1L = 0;
/*
* + CCP1M3:CCP1M0: CCPx Mode Select bits
*
* 1000 = Compare mode, set output on match (CCP1IF bit is set)
* 1001 = Compare mode, clear output on match (CCP1IF bit is set)
*/
// It's set to go HIGH on CCPR1 and TMR1 match
if (CCP1M0 == 0) {
// We are on the duty cycle, the output on RB3 will go HIGH
// Change the setting to interrupt on LOW next time
CCP1M0 = 1;
// Setup next values for duty cycle
CCPR1H = (DUTY_CYCLE / 256); // Clear the lower part
CCPR1L = (DUTY_CYCLE % 256); // Clear the higher part
}
// It's set to go LOW on CCPR1 and TMR1 match
else {
// We are on the period cycle, the output on RB3 will go LOW
// Change the setting to interrupt on HIGH next time
CCP1M0 = 0;
// Setup next values for period cycle
CCPR1H = ((PERIOD_CYCLE - DUTY_CYCLE) / 256);
CCPR1L = ((PERIOD_CYCLE - DUTY_CYCLE) % 256);
}
}
// Enable global interrupts
//GIE = 1; // Not necessary since SDCC does that automatically
}
void init_servo(void) {
/*
* Duty cycles on Futaba servos (Controls the position)
* 1ms : 0 degrees
* 1.5ms : 45 degrees
* 2.0ms : 90 degrees
*
* Period on Futaba servos (Controls the rotation speed)
* 10ms - 20ms
*/
// Stop Timer 1
TMR1ON = 0;
// Set PWM port (RB03) as an output
TRISB3 = 0;
// Reset Timer 1 values
TMR1H = 0;
TMR1L = 0;
/*
* 1000 = Compare mode, set output on match
* 1001 = Compare mode, clear output on match
*/
// Enable compare mode on CCP1CON register
CCP1CON = 9;
// Clean the interrupt register
PIR1 = 0;
// Enable Peripheral module interrupt
PEIE = 1;
// Enable CCP module interrupt
CCP1IE = 1;
// Enable Global Interrupt Enable bit
GIE = 1;
// Reset Comparator values
// This will trigger the interrupt right away
CCPR1H = 0;
CCPR1L = 0;
// Start Timer 1
TMR1ON = 1;
}
I'm using the internal oscillator, so at 4Mhz I should get 1000 instructions per 1 ms.
So using 20000 for the period and 1500 for the duty cycle I should end up with 20ms and 1,5ms.
The problem is that the servo, a Futaba 3003 (the most common one), doesn't respond correctly, it goes all the way to left and stays there trying to go further, drawing current from the board.
The servo works correctly, I have a 1:10 RC model and always test it on the original Futaba radio, it works perfectly.
I use a 12v AC connected to a 7805 voltage regulator with a couple of capacitors on both legs to get a stable 5 V.
The strange thing is that if I plug a led on RB3, it blinks fast, so it's obvious that some kind of waveform is being feed to RB3.
The only difference of my code and Mike's is that he keeps adding the value to the CCPR register, and I put the period/duty value straight, without adding anything to it. This is the only part of his code that I couldn't figure out.
Code:
Mike, K8LH's -> CCPR1H [B][COLOR="Red"]+=[/COLOR][/B] ((Pulse*5/2)/256)
Mine -> CCPR1H [B][COLOR="Red"]=[/COLOR][/B] (DUTY_CYCLE / 256);
Can you guys spot any obvious error on my code ? I'm confident that I'm close to get this servo working correctly.
EDITED:
I just noticed that the servo tilts a little bit to right then it goes all the way to left and stays on trying to go further the limit.
Couple of questions that came in mind :
1. Do I need to reset the values on Timer1 on every interruption ?
2. What about that other "Special Event" comparator mode ?
3. How can I debug interruptions ? I installed MPLab on my father's PC, but it also doesn't stop on any breakpoint inside the interrupt method.
Thank you, and great forum by the way.
Last edited: