Continue to Site

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 ESC 8xSERVO CONTROL on PIC (Oshonsoft BASIC)

Status
Not open for further replies.
Hi M,
The 164 in the title, tells me it's since the 'shift register'
I've added the #number also,
so if you edit it, change the title, date time:
'18F4431 32MHz XTL REMOTE_SLAVE 164 371 020223 2330
C
 
Hi m,
After the initial LED flashes, then they stay ON.
i Loops 0-9
CNT loops 0-20
wordtemp loops 1xtime
servocount seems to stay at 0, but I did see a 4 once.

Off to bed
Cheers.
C
 
3rd BREAK
2005.12 us
ms =1
CNT = 1
SERVOPOS() 0-8 filled
i=9
Rest '0'
This is worrying as servoPos is being initiated after interrupts are enabled.

You need to move these two lines further down,
Enable High 'This is set for SERVOS
Enable Low 'This is set for GPS later

To after these two,
INTCON.PEIE = 1
INTCON.GIE = 1

1st BREAK
0.12us
all '0'
I don't see how this is possible. 0.12uS is 1 clock cycle.
Assuming the break point is in the ISR then the first thing it's doing is executing the ISR which it shouldn't be doing as nothing is setup. Or, is it mS?

One thing that's just occurred to me, there is no longer any interrupt priority used, should it still be "On High Interrupt"?

Mike.
 
This is worrying as servoPos is being initiated after interrupts are enabled.

You need to move these two lines further down,
Enable High 'This is set for SERVOS
Enable Low 'This is set for GPS later

To after these two,
INTCON.PEIE = 1
INTCON.GIE = 1


I don't see how this is possible. 0.12uS is 1 clock cycle.
Assuming the break point is in the ISR then the first thing it's doing is executing the ISR which it shouldn't be doing as nothing is setup. Or, is it mS?

One thing that's just occurred to me, there is no longer any interrupt priority used, should it still be "On High Interrupt"?

Mike.
G'day M,
As I understand it:
Enable High 'This is set for SERVOS
Enable Low 'This is set for GPS later
should be before MAIN.
They enable the priority of each section.
The SERVO section begins with
On High Interrupt
and the GPS section as it can miss a beat,starts with
On low Interrupt.

The last one CODE I posted was:
18F4431 32MHz XTL REMOTE_SLAVE 164 3 020223 1600.txt

If I posted todays, it woulld be (at the moment:
'18F4431 32MHz XTL REMOTE_SLAVE 164 371 030223 0800
If you edit any and post them, change the time and date,then I'll know it's changed, and me likewise. (Although I don't expect to be changing much as you're in the driiving seat) :)

1st Break:
Clock cycles =4
Real time duration = 0.12us

Earlier CODE seemed to give better results??
C
 
Edit, does the A.I. program get rid of all indenting?
Hi M,
How mistakes are made!
I put 'C' CODE into the AI, and it produces a BASIC shaped INDENTED program, that I can almost read.

I copy that into the OSH SIM, and try to compile.
It stops on the first incorrect line, with an error message, and I have to guess what's wrong.
Sometimes I read the D/S, sometimes the OSH manual, and try till it moces to the next incorrect line, until it all compiles.
Then I run the simulator, while watchin Flags etc, and try to figure out if it's working or not.
For another opinion, I post it on a forum.
If I post is as I did in #369, the INDENTS stay where I left them.
C
 
In #371:
CCPR1L = 0x13
CCPR2H = 0x07
Shouldn't it be CCPR1H
Hi J,
I was only 1 out :)
That made a difference, well spotted. Reading the SIM numbers still doesn't seem correct.

servocount counts to 3 then 0
i counts to 9 then stays 9
This could be sim speed, and me not seeing the changes. I change the SIM speed to suit, but it needs to be fast slow at the same time, which is impossible.
Thanks.
C
 
Hi,
Here is the program since #371 with updated title:
Now #389 This is to make sure that we're working on exactly the same CODE with no hidden edits.
C
 

Attachments

  • 18F4431 32MHz XTL REMOTE_SLAVE 164 389 030223 1200.txt
    3.5 KB · Views: 260
Last edited:
Hi M,
Do you have any objection to me posting your CODE on AAC? There are OSH experts there, and may help us.
C
 
No objection at all. Not being able to debug is a major stumbling block.

If someone can printout the timing of the CCP1 output that would be very useful.
Also, confirming that the timer2 interrupt is happening every millisecond.

I note that these two lines,
Enable High 'This is set for SERVOS
Enable Low 'This is set for GPS later
are still at the beginning of the code - lines 38 & 39.
Interrupts should not be enabled until after they are setup but in this case it shouldn't matter as no interrupts will occur until they are setup.

Mike.
 
No objection at all. Not being able to debug is a major stumbling block.

If someone can printout the timing of the CCP1 output that would be very useful.
Also, confirming that the timer2 interrupt is happening every millisecond.

I note that these two lines,
Enable High 'This is set for SERVOS
Enable Low 'This is set for GPS later
are still at the beginning of the code - lines 38 & 39.
Interrupts should not be enabled until after they are setup but in this case it shouldn't matter as no interrupts will occur until they are setup.

Mike.
Hi M,
Ok, good. I'll post #349, and if you could point ot the latest 'C' file, I can post that also.

The SIM can watch every cycle, but of course that would take a long time to watch, and it can run fast so that counts etc get missed. I wrote down a sheet of INTERRUPTs, which was interesting, but not fruitful. I can't find a log file, but there may be one, I'll ask.

I have tried removing and adding all of the ENABLES, to see what happens, I couldn't see much of a pattern.

Cheers, C.
 
Here is the latest C file,
Code:
#include <xc.h>
#include "config.c"
#include <stdint.h>
#define _XTAL_FREQ 32000000
#define NUM_SERVOS 10

uint16_t wordTemp;
uint32_t ms;
uint8_t count=0,servoCount;
uint16_t servoPos[NUM_SERVOS];


void main(void) {
    OSCCON=0b01110000;      //8MHz
    PLLEN=1;                //x4=32MHz
    //setup 1mS interrupt = 8,000,000/16 = 500,000/10 = 50,000 set PR2=49 = 50,000/50 = 1000 = 1mS 
    T2CON=0b01001110;       //pre=16 post=10
    PR2=49;
    TMR2IE=1;               //timer 2 interrupts enable
    T1CON=0;                //timer 1 stopped 
    for(uint8_t i=0;i<NUM_SERVOS;i++){
        servoPos[i]=i*1000+8000; //1ms(8000) to 1.875(7/8ths - 15000)ms in 1/8th mS steps
    }
    TRISC=0b11111100;           //CCP0 & 1 output
    PEIE=1;
    GIE=1;
    while(1){
            //adjust servo positions here
    }
}

void __interrupt() inter(void){
    if(TMR2IE && TMR2IF){
        ms++;
        count++;
        if(count>=20){          //start every 20mS
            TMR1=0;             //zero timer 1
            T1CON=1;            //start timer 1
            count=0;
            CCP1CON=0b1000;     //CCP1 pin low and high on match - will be first pulse
            CCPR1L=0x0d;
            CCPR1H=0x07;
            CCP1IE=1;           //enable CCP1 interrupts
            CCP1IF=0;           //ensure interrupt flag is clear
            servoCount=0;       //reset servoCount
            LATC0=1;            //connected to data in of shift register will clock in a high when CCP1 goes high
        }
        TMR2IF=0;
    }
    if(CCP1IE && CCP1IF){
        LATC0=0;                //clear the data in pin
        if(servoCount==9)       //have we done all servos?
            CCP1IE=0;           //yes so no more CCP1 interrupts     
        if(CCP1CON==0b1000){    //have we started the 4000 cycle pulse
            CCP1CON=0b1001;     //yes so end the pulse after 0.5mS
            wordTemp=CCPR1H*256+CCPR1L;
            wordTemp=wordTemp+4000;
            CCPR1L=wordTemp & 255;
            CCPR1H=wordTemp/256;
        }else{
            CCP1CON=0b1000;     //No so output the timed gap            
            wordTemp=CCPR1H*256+CCPR1L;
            wordTemp=wordTemp-4000+servoPos[servoCount];
            CCPR1L=wordTemp&255;
            CCPR1H=wordTemp/256;
            servoCount=servoCount+1;
        }
        CCP1IF=0;
    }
}
The above is untested as I don't have the hardware but I think it works.

Mike.
 
I took some timings from the C code using the MPLABX stopwatch and simulator,
This is what I found,
2024 (253 µs) start of process will start first pulse
3999 (499.875 µs) end of first pulse 0.5mS
4001 (500.125 µs) start of servo 2 pulse - servo 1 time 1mS
3999 (499.875 µs) finished after 0.5mS
5001 (625.125 µs) start of servo 3 pulse - servo 2 time 1.125mS
3999 (499.875 µs)
6001 (750.125 µs) start of servo 4 pulse - servo 3 time 1.25mS
3999 (499.875 µs)
6971 (871.375 µs) start of servo 5 pulse - servo 4 time 1.375mS
4029 (503.625 µs)
8001 (1.000125 ms) start of servo 6 pulse - servo 5 time 1.5mS
3969 (496.125 µs)
9031 (1.128875 ms) start of servo 7 pulse - servo 6 time 1.675mS
3999 (499.875 µs)
10001 (1.250125 ms) start of servo 8 pulse - servo 7 time 1.75mS
3999 (499.875 µs)
11001 (1.375125 ms) just filling in time 1.875mS
3999 (499.875 µs)
12001 (1.500125 ms) ditto 2mS
49969 (6.246125 ms) start of new 20mS frame

Total time appears to be 18mS - not sure why.

The times vary due to interrupt latency but are pretty consistent. The CCP1 output should be cycle accurate due to it being hardware timed.

Mike.
 
The above times agree with the times set in the for loop
Code:
    for(uint8_t i=0;i<NUM_SERVOS;i++){
        servoPos[i]=i*1000+8000; //1ms(8000) to 1.875(7/8ths - 15000)ms in 1/8th mS steps
    }
Looking at the first servo, the times are,
3999 (499.875 µs) end of first pulse 0.5mS
4001 (500.125 µs) start of servo 2 pulse - servo 1 time 1mS

and 4001+3999 is 8000 as is in servoPos[0] or 1mS at 32MHz.

Mike.
 
Hi M,
All fine, thanks.
I'll let you know.

Writing a description in AAC is an interesting exercise, as I have to understand it.

Trying again to understand the 1ms INTERRUPT.
1/ e,g, the GPS INTERRUPT fires externally and 'randomly', what happens if it fires at the same time a the 1ms SERVO INTERRUPT?

2/ The GPS INT fires and a BYTE starts to load into the PIC memory (behind the scenes in H/W?) 1/2 way loaded, the SERVO INT fires (In H/W and shifts the register) while the GPS is still loading. Next there's another GPS BYTE. Am I correct that the H/Ws works in parallel?
C
 
Last edited:
Hi M,
As the SPI MOSI is on RC2, the RC PIN will need changed to RC1 sometime.
Is this a matter of changing all of the CCPR1 to CCPR2 etc?
C
 
Am I correct that the H/Ws works in parallel?
Yes, everything will do it's thing and when it's complete it sets it's interrupt flag and generates an interrupt. If while a byte (from RS232) is being loaded into memory a timer 2 interrupt occurs then it'll interrupt once the current interrupt has finished. As all these things are happening at 8,000,000 instructions per second then nothing gets missed. An interrupt routine would have to be over 500uS (4000 instructions) long for an interrupt to be missed.

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top