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.

Running two PICs in parallel sharing a common RX

Status
Not open for further replies.
3v0,

That timer method might be tricky. First you'd have to sort the duty cycle values. Then, what would happen if two of the duty cycles values are very close to each other? I suppose this kind of relates to duty cycle resolution too, maybe?

Mike
 
3v0,

That timer method might be tricky. First you'd have to sort the duty cycle values. Then, what would happen if two of the duty cycles values are very close to each other? I suppose this kind of relates to duty cycle resolution too, maybe?

Mike
I do not see it as tricky. Calculate the required times and which pin to turn off and store each pair of values in an array. Do the heavy lifting when you change the duty cycles. The ISR runs through the array once each period. You could look ahead to see if the next one was at the same time.

The more standard method compares each PWM duty cycle setting to the current 100 times per period. I would think that the overhead with what I proposed would be much less.
 
The more standard method compares each PWM duty cycle setting to the current 100 times per period. I would think that the overhead with what I proposed would be much less.
You're probably right. Those "more standard methods" probably would use more "overhead".

Here's alternative method to consider.

Use periodic interrupts at the pwm "step" rate.

Create a 32 element Toggle array for 32 pwm steps, or a 100 element Toggle array for 100 pwm steps, or a 256 element Toggle array for 256 pwm steps. You get the idea. One element for each pwm "step" interval.

At the end of each period, insert eight bits into the array, one bit for each output, at the correct interval, which also happens to be the array index.

During each periodic "step" interrupt, exclusive-or the output latch from the Toggle[] array and do some house-keeping. This takes about 9 cycles each interrupt.

You end up with very low interrupt overhead for all but the last interrupt in the period, and that interrupt doesn't really use very many cycles either.

One advantage of this method is that it takes the same amount of time to build a Toggle array with 32 steps as it does to build one for 200 steps. Disadvantages are using interrupt intervals at the "step" rate and using large RAM arrays which contain mostly '0' bytes.

Regards, Mike


Code:
;******************************************************************
;  K8LH Soft-8 PWM Method                                         *
;******************************************************************
;
; unsigned char Led[] = { 0,14,37,7,50,7,42,0 }; // 0..255 values
;
; unsigned char Interval = 0;   // 0..255
; unsigned char Toggle[256];    //
;
; void isr_hi ()
; { if (PIR1bits.CCP1IF == 1)   // if CCP1 "special event trigger"
;   { PIR1bits.CCP1IF = 0;      // clear CCP1 interrupt flag
;     LATB ^= Toggle[Interval]; // update PWM output channel
;     Toggle[Interval++] = 0;   // clear array for next period
;     if(Interval == 0)         // if end of period, refresh array
;     { Toggle[Led[0]] |= 1;    // insert b0 output toggle bit
;       Toggle[Led[1]] |= 2;    // insert b1 output toggle bit
;       Toggle[Led[2]] |= 4;    // insert b2 output toggle bit
;       Toggle[Led[3]] |= 8;    // insert b3 output toggle bit
;       Toggle[Led[4]] |= 16;   // insert b4 output toggle bit
;       Toggle[Led[5]] |= 32;   // insert b5 output toggle bit
;       Toggle[Led[6]] |= 64;   // insert b6 output toggle bit
;       Toggle[Led[7]] |= 128;  // insert b7 output toggle bit
;       Interval = 0;           // reset for new period
;       Toggle[0] ^= ~LATB;     // initialize 1st toggle element
;     }
;   }
; }
;
;   78.125 Hz, 256 steps = 50.0 usec interrupts
;
;   9 cycles during int 0..254 and 28 cycles during int 255
;
Led     equ     0x00            ; Led[8]  (8 bytes)
Toggle  equ     0x100           ; Toggle[256], 100..1FF

        org     0x0008
v_inthi
        bcf     PIR1,TMR2IF     ; clear timer 2 interrupt flag    |
        movf    INDF0,W         ;                                 |
        xorwf   LATB,F          ; LATB ^= Toggle[Interval]        |
        clrf    INDF0           ; Toggle[Interval] = 0            |
        incfsz  FSR0L,F         ; all 256 steps? yes, skip, else  |
        retfie  FAST            ; exit                            |

        movf    Led+0,W         ;                                 |
        bsf     PLUSW0,0        ; Toggle[Led[0]] |= 0b00000001    |
        movf    Led+1,W         ;                                 |
        bsf     PLUSW0,1        ; Toggle[Led[1]] |= 0b00000010    |
        movf    Led+2,W         ;                                 |
        bsf     PLUSW0,2        ; Toggle[Led[2]] |= 0b00000100    |
        movf    Led+3,W         ;                                 |
        bsf     PLUSW0,3        ; Toggle[Led[3]] |= 0b00001000    |
        movf    Led+4,W         ;                                 |
        bsf     PLUSW0,4        ; Toggle[Led[4]] |= 0b00010000    |
        movf    Led+5,W         ;                                 |
        bsf     PLUSW0,5        ; Toggle[Led[5]] |= 0b00100000    |
        movf    Led+6,W         ;                                 |
        bsf     PLUSW0,6        ; Toggle[Led[6]] |= 0b01000000    |
        movf    Led+7,W         ;                                 |
        bsf     PLUSW0,7        ; Toggle[Led[7]] |= 0b10000000    |
        comf    LATB,W          ;                                 |
        xorwf   Toggle,F        ; Toggle[0] ^= ~LATB              |
        retfie  FAST            ;                                 |
;
 
Last edited:
That works too. At this point we are getting into tradoffs.
I like the way you think.

For many applications we often use steps that are too close together. Fewer steps fewer interrupts.

Also when driving a motor the duty cycle has to be some minimum value for the
motor to turn or keep turning. One could omit these dead step from the table.
Have the ISR simply return for these early cycles. Or load up a timer and interrupt to skip them. Again tradeoffs.

On the motors I have played with I recall that a duty cycle of about 1/3 or less will not start the motor.
 
Last edited:
I would like to thank Nigel and 3v0 in particular for their great advice. I initially used the 1330 to get the PWM running and then decided to shift over to the 4331 (free samples are great!) since I needed the I/O.

Uploaded some vid clips of my final robot here:
**broken link removed**

**broken link removed**

Thanks again and all the best,
Mike
 
Congratulations. Do you intend to carry on developing it, it looks like it would make a very good chassis for something like RoboCup.

Mike.
 
Congratulations. Do you intend to carry on developing it, it looks like it would make a very good chassis for something like RoboCup.

Mike.

Thanks Pommie :)

I took the robot from basic chassis (base plate and motors mounted) to what it is right now in less than a week - bit of a rush due to several factors. Although I have developed CRC encoded communications between the MCU and a command application running in Linux I have not had time (or the budget) to implement PID control using the QEI interface of the 4331, let alone include sensors or visual odometry and localisation.

It's simply a demo for my thesis, but I wish I had more time to develop it. I may work on a personal project to take it further, including a novel method I have developed for trajectory generation etc. (part of the theoretical dev. of my thesis).

Cheers,
Mike
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top