Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Hardware PWM on PIC

tumbleweed

Active Member
...and the INTERRUPT doesn't fire.
I know nothing about this flavor of basic so I could be way off base here, but there are two things that stand out...

First, nothing appears to be enabling the peripheral interrupts
Code:
//And enable the interrupts for the hardware used
//the reference for CCP1, so no time interrupt required.
PIE1.CCP1IE = 1
INTCON1.PEIE = 1    // INTCON bit 6
INTCON1.GIE = 1        // INTCON bit 7

and in the ISR nothing appears to be clearing the CCP1 IF flag
Code:
//INT_CCP1
On High Interrupt
PIR1.CCP1IF = 0        // clear IF
 

camerart

Active Member
You completely missed the point. Back some time in the 80s (or 90s) I wrote a program to control a servo. It worked but the servo constantly "chattered". I eventually found that a 1uS difference in pulse width caused the "chatter". Repeatability is desired, accuracy irrelevant.

Mike.
Hi M,
I've seen SERVOs chatter, and wondered what caused it.
I suppose the amount of chatter where it should be stationary, are from varying inputs, that are the size of the movement.
C.
 

camerart

Active Member
Hi,
I've noticed that there is no [ INTCON1.PEIE ] on 18F4431, but it should be [ INTCON.PEIE ]
I tried 'T's suggestions.
The INTERRUPT isn't firing.
C.
 
Last edited:

Pommie

Well-Known Member
Most Helpful Member
I had a play and got it working in hardware but had to use a pointer to access the RBxPPS registers. Can your BASIC use pointers? It could be done with a select case type structure.

Mike.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
As I said previously.. It works on Proteus, so I will assume Oshonsoft has a bug.. Remeber this isn't using the dedicated PWM controller just the bog standard CCP so who knows whats going on.
 

Pommie

Well-Known Member
Most Helpful Member
The CCP hardware can be setup to set/clear the pin automatically in hardware (modes 8 & 9). The output pulses can then be "steered" to the desired pins with the peripheral pin select hardware. I have it working in XC8.

Mike.
 

camerart

Active Member
As I said previously.. It works on Proteus, so I will assume Oshonsoft has a bug.. Remeber this isn't using the dedicated PWM controller just the bog standard CCP so who knows whats going on.
Hi I,
Yes, 'Who knows'
That's fine, you and 'R' have done enough for me to eventually get it going, so thanks, it is very much appreciated, as up to this stage would have taken me a long time.
I have posted it on AAC, where there is an Oshosnoft section.
C
 

camerart

Active Member
The CCP hardware can be setup to set/clear the pin automatically in hardware (modes 8 & 9). The output pulses can then be "steered" to the desired pins with the peripheral pin select hardware. I have it working in XC8.

Mike.
Hi M,
I don't know XC8, or what language, but you have followed this thread, and know i'm no expert. I would like to see your program.
C
 

Pommie

Well-Known Member
Most Helpful Member
Here it is,
Code:
#include <xc.h>
#include "config.c"
#include <stdint.h>
#define _XTAL_FREQ 32000000
#define NUM_SERVOS 6
#define FRAME 20000L    //how long each frame is

uint16_t servoPos[NUM_SERVOS];
uint8_t servoCount=0;

void main(void) {
//setup timer 1 to count at 8MHz - the default
    TMR1ON=1;           //just turn it on
    TMR1CLK=0b0001;     //select Fosc/4
    CCP1CON=0b10001001; //clear CCP1 output on match
    CCP1IE=1;           //enable CCP1 interrupts
    for(uint8_t i=0;i<NUM_SERVOS;i++){
        servoPos[i]=1.5*8000;
    }
    TRISB=0;
    LATB=0;
    PEIE=1;
    GIE=1;
    while(1){
    }
}


void __interrupt() inter(void){
    if(CCP1IE && CCP1IF){
        if(CCP1OUT){    //which phase of the output are we in?
            //outputting the pulse
            CCPR1+=servoPos[servoCount];
            CCP1CON|=1;             //is high phase, so clear on match
        }else{
            //outputting the gap
            CCPR1+=FRAME-servoPos[servoCount];
            CCP1CON&=0b11111110;    //is low phase so set on match
            unsigned char *point=(unsigned char *)&RB0PPS;
            point[servoCount]=0;    //release the old CCP1 output
            if(++servoCount>=NUM_SERVOS){
                servoCount=0;
            }
            point[servoCount]=9;    //setup new CCP1 output
        }
        CCP1IF=0;
    }
}

The code does the following,
Sets up timer 1 to count at 8MHz.
Sets the mode of CCP1.
Enables interrupts.
The interrupt then does all the clever stuff.
ServoPos is a number between 8000(1mS) and 16000.
The tricky bit is the pointer stuff in the ISR.
Note, XC8 allows short cuts so CCP1OUT is this bit,
CCP.png

Hopefully, Ian might be able to help convert it.

Mike.
Edit, the code uses a Pic16F18854 as I had this handy.
 

camerart

Active Member
Here it is,


Hopefully, Ian might be able to help convert it.

Mike.
Edit, the code uses a Pic16F18854 as I had this handy.
Hi M,
Could you also post the INCLUDES please?

Sometimes 'things' happen when changing PICs, which I will bear in mind.

I won't ask 'I' yet, it would be rude :) I'll play with that one for a while. I would like to see a SERVO move first.

Meanwhile, I'll look at your program.

Most welcome, thanks. C
 

camerart

Active Member
I Know...... I read it...
Morning I,
There are a couple of people on AAC, that help me, and know Oshonsoft very well, sometimes they find bugs, where I have to write to Vlad of OSH. Most times things get fixed.
Meanwhile, I'm going through it line by line, and slowly getting used to it. Sometimes I can find blockages, although rarely :)
Cheers, C.
 

camerart

Active Member
Hi R and M,
'R', are you referring to 'M's CODE?

If there is a suitable PIC, with the same PINouts, I can change it.
I searched before, but that could have been for a different reason. I can check again.
It needs to have PPS!
C
 

tumbleweed

Active Member
I've noticed that there is no [ INTCON1.PEIE ] on 18F4431, but it should be [ INTCON.PEIE ]

I was just following your lead in the existing code you posted. There's no INTCON1 at all in the 18F4431 (it's just INTCON) so you'd also have to change 'INTCON1.GIE = 1'.

This isn't your problem, but since you're generating the outputs manually on PORTB, you might want to change the CCP1 compare mode to '1010= Compare mode; generate software interrupt on compare match' (CCP1CON = 0x0A).
Also, it might be a good idea to initialize CCPR1L:CCPR1H, but that shouldn't keep you from getting an output eventually.
 

camerart

Active Member
I was just following your lead in the existing code you posted. There's no INTCON1 at all in the 18F4431 (it's just INTCON) so you'd also have to change 'INTCON1.GIE = 1'.

This isn't your problem, but since you're generating the outputs manually on PORTB, you might want to change the CCP1 compare mode to '1010= Compare mode; generate software interrupt on compare match' (CCP1CON = 0x0A).
Also, it might be a good idea to initialize CCPR1L:CCPR1H, but that shouldn't keep you from getting an output eventually.
Hi T,
I'll try those suggestions thanks.
In the OSH simulator, as the INTERRUPT isn't firing, I can't see what's happening.
It will take me quite a while to get into this program, but normally, I'll try something that works.

EDIT: I have a friend, who's busy at the moment, but sometime, I can run it past him, with the SIM, and he may be able to help.
C
 

camerart

Active Member
Is there a reason you need a 40 pin chip?

Mike.
Hi M,
The project uses 2x PCBs 1xBASE and 1xREMOTE both have been made the same, but they are used in different ways.
The BASE senses the joysticks and controls, one of which is a QEI reader on the 4431.
After calculations etc, the DATA is sent via radio to the REMOTE, which after some calculation controls the Motors/servos,

The REMOTE 4431 could be changed, but it would be a lot of effort to change the PINouts and number of PINs, so any alternative should fit the same footprint.
C
 

Attachments

  • PCB8.jpg
    PCB8.jpg
    389.4 KB · Views: 7

Latest threads

New Articles From Engineer's Garage

Top