![]() | ![]() | ![]() |
| | |||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
| | LinkBack | Thread Tools | Display Modes |
| | (permalink) |
| 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 http://www.electro-tech-online.com/m...-basics-3.html , 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;
} 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 += ((Pulse*5/2)/256) Mine -> CCPR1H = (DUTY_CYCLE / 256); 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 by bpmelo; 13th August 2008 at 09:09 PM. Reason: New findings. | |
| |
| | (permalink) | |
| Forum, I finally got my servo working on a 16f628 using the SDCC compiler. When reading an Application note from Microchip I came across, this : Quote:
After this I changed the mode to generate the PWM wave, using just Timer1 and it's overflow interruption, and for my surprise, it worked !! I found this solution easier to understand, specially in C. And it's full with comments also, so whoever wants to look at it, here are the project files. Thanks again, great forum to search for solutions. | ||
| |
| | (permalink) |
| Why is this a bug? I mean it makes sense that if you want the pin to go LOW after some time, that pin would be HIGH when you initiate the process. Why should you use CCP to take the pin LOW after some time if its initial state was LOW at the first place. (same applies to HIGH). Last edited by demestav; 17th August 2008 at 12:35 AM. | |
| |
| | (permalink) | |
| Quote:
| ||
| |
| | (permalink) |
| It may or may not change the pin state. I've never checked it. But does it really matter? After all, you only tell it to set the pin 'lo' next match when the pin is currently 'hi'. We don't care if the module tries to set the pin 'hi' because it's already 'hi'. Same thing when the pin is 'lo' and well tell the module to set the pin 'hi' on the next match. Who cares if the module tries to set the pin 'lo'? It's already 'lo'... Btw, if you haven't figured out why you add values to CCPR1 then you should have another read of the CCP module section in the Data Sheet... Mike | |
| |
| | (permalink) | |
| Quote:
I figured the CCPR1 += thing, thanks for explaining it btw. | ||
| |
| | (permalink) | |
| You're not taking into account the state of the pin when you change the CCP1M0 bit. When you change CCP1M0 to go 'hi' on the next match interrupt the CCP1 module may indeed force the pin 'lo' but it's already 'lo' so you shouldn't have a problem. Did you observe something different? Quote:
Mike Last edited by Mike, K8LH; 17th August 2008 at 02:31 AM. | ||
| |
| | (permalink) | |
| Quote:
Anyway, some more detailed info should be added to the datasheet, like the state of the Timer1 register after the interrupt, I couldn't find one single place where it says if the register gets cleared or not, only on that "special" mode. I was being sarcastic about the += thing Mike Now up to the next part on the project. Will keep you guys posted. | ||
| |
| | (permalink) |
| The timer keeps running and rolls-over and that's why you add the value to the CCPR1 register pair in those modes. The special event trigger mode is the only mode that resets the timer to 0000 but that modes doesn't set or clear the CCPx bit in hardware so then you have to worry about jitter. If you reset the timer in the ISR you may have a problem with pulse width jitter. Mike Last edited by Mike, K8LH; 17th August 2008 at 04:43 AM. | |
| |
| | (permalink) | |
| Quote:
I'm not getting any jitter using just the Timer1 interruption Mike, is there some way to test it ? | ||
| |
| | (permalink) |
| Your source files come up as jibberish in Notepad so I'm not sure how you're doing it now. Mike | |
| |
| | (permalink) |
| | |
| |
| | (permalink) |
| They work fine in MPLAB or Piklab too.
__________________ ========================= Futz's Microcontrollers & Robotics ========================= | |
| |
| Bookmarks |
| Tags |
| interrupt, pwm, sdcc, servo |
| Thread Tools | |
| Display Modes | |
| |
| | ||||
| Title | Starter | Forum | Replies | Latest |
| Timer1 | richb | Micro Controllers | 5 | 27th November 2006 11:44 PM |
| 16F628, get a fast pulse | patroclus | Micro Controllers | 10 | 22nd November 2005 02:53 PM |
| comparator as a pulse generator | xmat | Electronic Projects Design/Ideas/Reviews | 6 | 1st February 2005 08:02 PM |
| 16f628 datasheet - timer1 prescalar values | 2camjohn | Micro Controllers | 2 | 3rd June 2004 05:12 PM |
| 16F628 comparator inputs and PicBasic Pro | lavenatti | Micro Controllers | 0 | 16th May 2003 04:43 PM |