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.
This is an example of the section added to the 1mS interrupt; this was for a Bluetooth link, but it's still incoming serial data, same as a GPS:

C:
    while(BT_RX_DATA) // If the UART has a character ready
    {
        char c;
                
        disable_interrupts(INTR_GLOBAL);
        c = fgetc(BT);        // Read the character
        buf_put(&bt_rx, c); // Put it in the buffer
                
        if(c == '\r')         // If the character was end-of-line,
        {
            buf_put(&bt_rx, '\0'); // Store a null
            bt_rx_ready = true;    // And set the variable for the main program
         }
         enable_interrupts(INTR_GLOBAL);
    }

In the main program:
Initialise a buffer at the start of the program:

rs232_buffer bt_rx;

C:
// In the main loop:

if(bt_rx_ready)
{
    process_bt();
}



// and somewhere else

void process_bt(void)
{
    // Last char read was a CR; get the buffer data.
    
    // Read until either a CR is found or the buffer is empty
    // (or 80 chars have been read, if garbage).
    // LF is ignored and dumped.
    
    int8 i;
    char c;   
    char *p;
    char *q;
    char parse[16];
    i = 0;
    c = '\0';
    p = bbuf;
      
    do
    {
        c = buf_get(&bt_rx);
        if(c > 0x20 && c < 0x7f)
        {
            if(c >= 0x41 && c <= 0x5A) // Upper case letters
            {
                c |= 0x20;
            }
            
            *p++ = c;
            i++;
        }
        
    } while(c && c != '\r' && i < 60);
    
    // String with all spaces removed & line feed omitted.
    // Ensure it's a terminated string to avoid overruns..
    *p++ = '\0';
    
    // Should now have a valid string in bbuf.
    // Check it's not junk or too short to be valid first:
    if(i < 2) return;
    
    // Have a command string.
    
    
    //
    // The do whatever you do with the GPS string once received..
    //

}
 
The GPS stuff is likely the cause of all the jitter! You cannot possibly control servos reliably whilst that long read cycle is happening.

What you can do is check for a received UART character at every 1mS interrupt and put it in a circular buffer if received.
Set a variable if the character was a line feed (0x0A) as that's the end of each GPS sentence.

In your main program, just look for the variable being set and when that happens, read all the characters from the buffer until you get to the line feed, then parse the line.

That means no delays at all in the critical interrupt routines.

This is my circular buffer library, in C. The buffer size should be at least 128, or 256 if the MCU has plenty of RAM.

It will take a bit of translating.....


Header file:

C:
/*
 * File:   rj_ringbuffer.h
 * Author: Robert Jenkins
 *
 * Created on 22 October 2018, 16:45
 */

#ifndef RJ_RINGBUFFER_H
#define    RJ_RINGBUFFER_H

#ifdef    __cplusplus
extern "C" {
#endif

// This must be a power-of-2 value
// The mask is the bit size of this value
// eg. 32 size, 0x1F mask; five bits set, 2^5 = 32.
// 256 size, mask 0xff
// 64 size, mask 0x3f
// 8 size, mask 0x07 etc.

#define RING_BUFFER_SIZE 256
#define RING_BUFFER_MASK 0xff


/* In the main program, declare each required buffer
 * with its own name, like

rs232_buffer serial_rx;
or
rs232_buffer terminal_tx;
 etc.

*/

// Limit value to prevent possible buffer wrap.
#define RING_BUFFER_LIMIT RING_BUFFER_SIZE - 2

typedef struct rs_bf
{
    unsigned int16  buf_inp;
    unsigned int16  buf_out;
    unsigned int8 * inp_ptr;
    unsigned int8 * out_ptr;
    unsigned int16  bcount;
    unsigned int8   buf_dat[RING_BUFFER_SIZE];
} rs232_buffer;

//
// In each of these, "rs232_buffer *" is replaced by the
// name of buffer as declared above, eg.
//
// buf_put(terminal_tx, c);
// i = buf_count(serial_rx);
//

void buf_clear(rs232_buffer *);
int buf_put(rs232_buffer *, char);
char buf_get(rs232_buffer *);
int buf_count(rs232_buffer *);
int buf_put_string(rs232_buffer *, char *);

#ifdef    __cplusplus
}
#endif

#endif    /* RJ_RINGBUFFER_H */

And the actual C program:

C:
#include "rj_ringbuffer.h"

    /* For reference:
    typedef struct rs_bf
{
    unsigned int16  buf_inp;
    unsigned int16  buf_out;
    unsigned int8 * inp_ptr;
    unsigned int8 * out_ptr;
    unsigned int16  bcount;
    unsigned int8   buf_dat[RING_BUFFER_SIZE];
} rs232_buffer;

     */

void buf_clear(rs232_buffer *b)
{
    b->buf_inp = b->buf_out = b->bcount = 0;
    b->inp_ptr = b->out_ptr = &(b->buf_dat[0]);
}

int buf_put(rs232_buffer *b, char c)
{
    if(b->bcount < RING_BUFFER_LIMIT)
    {
        b->buf_dat[b->buf_inp++] = c;
        b->bcount++;
      
        b->buf_inp &= RING_BUFFER_MASK;
    }
  
    return b->bcount;
}

char buf_get(rs232_buffer *b)
{
    char c;
    if(b->bcount > 0)
    {
        c = b->buf_dat[b->buf_out++];
        b->bcount--;

        b->buf_out &= RING_BUFFER_MASK;
      
        if(b->buf_inp == b->buf_out)
            b->bcount = 0;
  
        return c;
    }
    else
        return '\0';
  
}

int buf_count(rs232_buffer *b)
{
    return b->bcount;
}

int buf_put_string(rs232_buffer *b, char *c)
{
    char *p;
    char l;
    int i = 0;
  
    p = c;
  
    while(*p)
    {
        l = *p++;
        buf_put(b, l);
        i++;
    }
    return i;
}
Hi R,
So far, I've been testing before adding them into the full program with GPS, so this hasn't been the cause of jitter.

As mentioned the GPS INTERRUPT is triggered by the $ at the begining of the sentence, and must read all of the sentence in one go, for accuracy. I tried to read the GPS buffer via SPI, but wasn't able to, so moved to the above method. (When I have time, I'll re-check)

Thanks for your CODE, I'll see what M has to say, then if his CODE can't work, then I'll move to yours. Let me know if the above comments change anything please.
C
 
edit3, can you post your current code that you're currently working with - preferably as a text file.
Hi M,
Previously, I said that I make mistakes, and to check my CODE.

I was thinking about how SERVOS work, and wondered why there is any mention of the 20ms, so I looked again at the FRAME time = [frame = 0x07d0 '2000] It should be 20000.
C.
 
Rather than add anything to the 1mS interrupt and risk frame errors, simply have a UART interrupt. I'll have a go later as it's 7am here and coffee time.

Mike.
 
Rather than add anything to the 1mS interrupt and risk frame errors, simply have a UART interrupt. I'll have a go later as it's 7am here and coffee time.

Mike.
Hi M,
Morning.
I added FRAME back in as the time has to be entered in 2x BYTES: Is this correct?
==============================================
CCPR1L = frame.LB '2000 'start pulse in 0.25mS (2000 clock cycles)
CCPR1H = frame.HB (Should this be 2000 or 20000?)
============================================
Would you be good enough to explain in detail what your CODE actually does, so that I know what you're aiming for. This may seem over the top, but I think it will shorten the thread in the long run.
C
 
Would you be good enough to explain in detail what your CODE actually does
Here is a fully commented version,
Code:
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;                 //this is timer 2 period register. I.E. reset after 50 clocks (0 to 49 = 50 counts)
    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;                 //enable peripheral interrupts
    GIE=1;                  //enable global interrupts
    while(1){               //loop forever because everything is done on interripts
            //adjust servo positions here
    }
}


void __interrupt() inter(void){
    if(TMR2IE && TMR2IF){       //is it a timer 2 interrupt
        ms++;                   //yes, so increment ms variable
        count++;                //and count
        if(count>=20){          //has 20mS passed
            TMR1=0;             //yes, so zero timer 1
            T1CON=1;            //and start timer 1
            count=0;            //reset count
            CCP1CON=0b1000;     //CCP1 pin low and high on match - will be first pulse
            CCPR1=2000;         //start pulse in 0.25mS (2000 clock cycles)
            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;               //clear timer 2 interrupt flag
    }
    if(CCP1IE && CCP1IF){       //is it a CCP1 interrupt
        LATC0=0;                //yes, so clear the data in pin as the high has already been clocked in
        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
            CCPR1=CCPR1+4000;   //4000 cycles=0.5mS
        }else{
            CCP1CON=0b1000;     //No so output the timed gap            
            CCPR1=CCPR1+servoPos[servoCount++]-4000;   //will generate an interrupt when servo time is up
        }
        CCP1IF=0;               //clear CCP1 interrupt flag
    }
}
If you tell me which bits you don't understand then I'll try and explain them better.
E.G. do you understand how the pulses are generated?

Mike.
 
Here is a fully commented version,
Code:
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;                 //this is timer 2 period register. I.E. reset after 50 clocks (0 to 49 = 50 counts)
    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;                 //enable peripheral interrupts
    GIE=1;                  //enable global interrupts
    while(1){               //loop forever because everything is done on interripts
            //adjust servo positions here
    }
}


void __interrupt() inter(void){
    if(TMR2IE && TMR2IF){       //is it a timer 2 interrupt
        ms++;                   //yes, so increment ms variable
        count++;                //and count
        if(count>=20){          //has 20mS passed
            TMR1=0;             //yes, so zero timer 1
            T1CON=1;            //and start timer 1
            count=0;            //reset count
            CCP1CON=0b1000;     //CCP1 pin low and high on match - will be first pulse
            CCPR1=2000;         //start pulse in 0.25mS (2000 clock cycles)
            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;               //clear timer 2 interrupt flag
    }
    if(CCP1IE && CCP1IF){       //is it a CCP1 interrupt
        LATC0=0;                //yes, so clear the data in pin as the high has already been clocked in
        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
            CCPR1=CCPR1+4000;   //4000 cycles=0.5mS
        }else{
            CCP1CON=0b1000;     //No so output the timed gap           
            CCPR1=CCPR1+servoPos[servoCount++]-4000;   //will generate an interrupt when servo time is up
        }
        CCP1IF=0;               //clear CCP1 interrupt flag
    }
}
If you tell me which bits you don't understand then I'll try and explain them better.
E.G. do you understand how the pulses are generated?

Mike.
Hi M,
Thanks for the comments, I'll add them to the #290 CODE, then draw it as best as I can on to this image, then post it.

If you check the #290 CODE and search for FRAME and CYCLE, this is used as they have to be done in 2x BYTEs each.
C
 

Attachments

  • PWM.jpg
    PWM.jpg
    64.8 KB · Views: 211
All the references to CCPR1 will need to be double writes so,
CCPR1 = 2000

Will need to be,
CCPR1L=0xD0
CCPR1H=0x07
And the other write to CCPR1 changed as posted previously.
As shown above, you can write a 16 bit value by writing two 8 bit values. Storing in a word generates lots of unnecessary code. From #289 above.

Mike.
 
Here's a version that doesn't use CCPR1 as a word variable. It uses a union to mimic word.HB etc.
Code:
#include <xc.h>
#include "config.c"
#include <stdint.h>
#define _XTAL_FREQ 32000000
#define NUM_SERVOS 10

uint16_t servoPos[NUM_SERVOS];
typedef union{
    uint16_t w;
    struct{
        uint8_t lo;
        uint8_t hi;
    };
}Word;

Word  wordTemp;
uint32_t ms;
uint8_t count=0,servoCount;


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
            //CCPR1=2000;         //start pulse in 0.25mS (2000 clock cycles)
            CCPR1L=2000 & 255;
            CCPR2H=2000/256;
            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
            //CCPR1=CCPR1+4000;   //4000 cycles=0.5mS
            wordTemp.w=CCPR1H*256+CCPR1L;
            wordTemp.w=wordTemp.w+4000;
            CCPR1L=wordTemp.lo;
            CCPR1H=wordTemp.hi;
        }else{
            CCP1CON=0b1000;     //No so output the timed gap            
            //CCPR1=CCPR1+servoPos[servoCount++]-4000;   //will generate an interrupt when servo time is up
            wordTemp.w=CCPR1H*256+CCPR1L;
            wordTemp.w=wordTemp.w-4000+servoPos[servoCount];
            CCPR1L=wordTemp.lo;
            CCPR1H=wordTemp.hi;
            servoCount=servoCount+1;
        }
        CCP1IF=0;
    }
}

Mike.
 
For this bit,
Code:
            wordTemp.w=CCPR1H*256+CCPR1L;
            wordTemp.w=wordTemp.w+4000;
            CCPR1L=wordTemp.lo;
            CCPR1H=wordTemp.hi;
You can do,
Code:
    word.HB=CCPR1H
    word.LB=CCPR1L
    word=word+4000
    CCPR1L=word.LB
    CCPR2H=word.HB

You can not do the addition\subtraction on the bytes. It must be done as a word so any carries are dealt with.

Mike.
 
Here's a version that doesn't use CCPR1 as a word variable. It uses a union to mimic word.HB etc.
Code:
#include <xc.h>
#include "config.c"
#include <stdint.h>
#define _XTAL_FREQ 32000000
#define NUM_SERVOS 10

uint16_t servoPos[NUM_SERVOS];
typedef union{
    uint16_t w;
    struct{
        uint8_t lo;
        uint8_t hi;
    };
}Word;

Word  wordTemp;
uint32_t ms;
uint8_t count=0,servoCount;


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
            //CCPR1=2000;         //start pulse in 0.25mS (2000 clock cycles)
            CCPR1L=2000 & 255;
            CCPR2H=2000/256;
            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
            //CCPR1=CCPR1+4000;   //4000 cycles=0.5mS
            wordTemp.w=CCPR1H*256+CCPR1L;
            wordTemp.w=wordTemp.w+4000;
            CCPR1L=wordTemp.lo;
            CCPR1H=wordTemp.hi;
        }else{
            CCP1CON=0b1000;     //No so output the timed gap           
            //CCPR1=CCPR1+servoPos[servoCount++]-4000;   //will generate an interrupt when servo time is up
            wordTemp.w=CCPR1H*256+CCPR1L;
            wordTemp.w=wordTemp.w-4000+servoPos[servoCount];
            CCPR1L=wordTemp.lo;
            CCPR1H=wordTemp.hi;
            servoCount=servoCount+1;
        }
        CCP1IF=0;
    }
}

Mike.
Hi M,
Ok, thanks.
C
 
Hi All,
I've got to give my programming head a rest, so I've switched on my logic head instead. I'm trying to avoid difficult programming which arrives at a dead end.

In this case eventually we'll have a GPS input and an 8CH SERVO output, each have INTERRUPTS.

In M's case I can't see how they can live together if the SERVOS have a 1ms INTERRUPT.

I'm trying to tie up any program with the attached chart, to see how they work. On the chart can be seen a FREE time where the GPS could read. Let's all agree whether I'm correct or not before moving on, and if there's time in the FREE section for the GPS which has 45 characters at 9600.
C
 

Attachments

  • 8CH PWM.jpg
    8CH PWM.jpg
    98.8 KB · Views: 213
Let's all agree whether I'm correct or not before moving on, and if there's time in the FREE section for the GPS which has 45 characters at 9600.

If you look above that, it's what is left of the "frame repeat" period of 20mS.....

Eight servo times could be 16mS with 2mS maximum, or 20mS with 2.5mS maximum as used with some digital servos.

So 4mS "free" with older 1 - 2mS analog servos, or no free time with 0.5 - 2.5mS digital servos.

45 characters at 9600 baud is somewhat over 45 mS. Longer that two complete servo frames.

The GPS data reception MUST run via an interrupt driver routine so it does not block the servo routine.
 
If you look above that, it's what is left of the "frame repeat" period of 20mS.....

Eight servo times could be 16mS with 2mS maximum, or 20mS with 2.5mS maximum as used with some digital servos.

So 4mS "free" with older 1 - 2mS analog servos, or no free time with 0.5 - 2.5mS digital servos.

45 characters at 9600 baud is somewhat over 45 mS. Longer that two complete servo frames.

The GPS data reception MUST run via an interrupt driver routine so it does not block the servo routine.
Hi R,
Ok.
There are 2x threads ETO and AAC where I tried to get the M8Ns to read via SPI, but I didn't succeed. The GPS is a rabbit hole, with D/S galore, and errata too. I don't think these £30ish modules are cabable of SPI. If you want to try I can set-up again.
In the absense of SPI from the GPS, I have them set-up to send 5x/sec, and this is precise at 1sec and 250ms between each sentence.
Am I correct then, that M's 1ms INTERRUPT won't work with the GPS on this PIC?
C
 
The used time is a small percentage of the available time. The 1mS interrupt does not use 1mS, it uses a few cycles every mS. The servo stuff uses a few cycles when a servo pulse is generated. A usart should use a few cycles when a byte is received. This idea that the chip is being stretched processor wise is nonsense. It can easily do what it's doing and the GPS stuff as well. Where "So 4mS "free" with older 1 - 2mS analog servos, or no free time with 0.5 - 2.5mS digital servos."comes from I have no idea, it's complete nonsense. It's an interrupt - not blocking code!!!!!!!! The "free" time is very close to 100% - let's have a guess at greater than 95%.

Mike.
 
The used time is a small percentage of the available time. The 1mS interrupt does not use 1mS, it uses a few cycles every mS. The servo stuff uses a few cycles when a servo pulse is generated. A usart should use a few cycles when a byte is received. This idea that the chip is being stretched processor wise is nonsense. It can easily do what it's doing and the GPS stuff as well. Where "So 4mS "free" with older 1 - 2mS analog servos, or no free time with 0.5 - 2.5mS digital servos."comes from I have no idea, it's complete nonsense. It's an interrupt - not blocking code!!!!!!!! The "free" time is very close to 100% - let's have a guess at greater than 95%.

Mike.
Hi M,
Ok, but let's be clear about the GPS.
As far as I have understood, with working my GPS, I have to receive a full sentence from $ to W, for my PARSE BUFFER routine, I don't think it can work by receiving 1 BYTE at a time.
C
 
Last edited:
As far as I have understood, with working GPS, I have to receive a full sentence for $ to W, for my PARSE routine, I don't think it can work by receiving 1 BYTE at a time.
Then you don't understand. RS232 is sent 1 byte at a time. You receive that byte, save it, check if a whole sentence has been received and flag the main code if it has. You do not wait for the whole sentence - a byte takes ~1mS to be transmitted - it can be received in 1mS by the hardware which then tells you "I've got a byte for you", you then deal with the byte. The only waiting involved is waiting for the hand to go up saying "I've got a byte for you". With the RS232 receive code and servo/timer code it should still be using less than 10% of the available processing time.

Mike.
 
Then you don't understand. RS232 is sent 1 byte at a time. You receive that byte, save it, check if a whole sentence has been received and flag the main code if it has. You do not wait for the whole sentence - a byte takes ~1mS to be transmitted - it can be received in 1mS by the hardware which then tells you "I've got a byte for you", you then deal with the byte. The only waiting involved is waiting for the hand to go up saying "I've got a byte for you". With the RS232 receive code and servo/timer code it should still be using less than 10% of the available processing time.

Mike.
Hi M,
Not another thing I don't understand!! It's hard for me to visualise the speed of it all.

So in this case with SERVO and GPS do they both merge together, even though the GPS spits out each full NMEA sentence at 5/sec.
C
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top