Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronics Categories > Micro Controllers


Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc.

Reply
 
LinkBack Thread Tools Display Modes
Old 6th December 2007, 09:01 AM   (permalink)
Default

Each '4017 is driven directly by a seperate CCP module CCPx pin and so each '4017 maintains its own 20 msec period. Each '4017 will get 10 "compare" interrupts per 20 msec period. And servicing the interrupt is not critical with these hardware solutions compared to the 'soft' solutions. You could disable interrupts for a hundred microseconds or more at a time without affecting performance.

I modified the code to show one way that you might implement dual 74HC4017's. Please note the interrupt code outputs a pulse on the 74HC4017 Q1 through Q9 outputs that corresponds to the ChanA[0] through ChanA[8] pulse width array elements. The interrupt code uses the value in the ChanA[9] element for the Servo period "off time" (20 msecs minus the cumulative pulse on times).

Code:
static unsigned char Qa = 0;
static unsigned char Qb = 0;
static unsigned int ChanA [] = { 1500, 1500, 1500, 1500,
                                 1500, 1500, 1500, 1500,
                                 1500, 20000 };
static unsigned int ChanB [] = { 1500, 1500, 1500, 1500,
                                 1500, 1500, 1500, 1500,
                                 1500, 20000 };

void isr_hi ()
{
 /****************************************************************
  *  K8LH Crazy-18 Hi-Rez 18-chan Dual 74HC4017 Servo Algorithm  *
  ****************************************************************/
  if (PIR1bits.CCP1IF == 1)       // if CCP1 "compare" interrupt
  {
    CCPR1H++;                     // avoid false update "match"
    CCPR1 += ChanA[Qa];           // update "compare" int value
    CCPR1H--;                     // fix CCPR1H
    LATCbits.LATC2 = 0;           // clear CCP1 "CLK" line
    PIR1bits.CCP1IF = 0;          // clear CCP1 interrupt flag

    ChanA[9] -= ChanA[Qa++];      // adjust end-of-period off time

    if (Qa = 10)                  // if end-of-period
    { Qa = 0;                     // reset Qa array index
      ChanA[9] = 20000;           // reset 20.0-msec period and
      LATAbits.LATA0 = 1;         // toggle 74HC4017 "CLR" line
      LATAbits.LATA0 = 0;         // to force Q0 output sync'
    }
  }
  if (PIR2bits.CCP2IF == 1)       // if CCP2 "compare" interrupt
  {
    CCPR2H++;                     // avoid false update "match"
    CCPR2 += ChanB[Qb];           // update "compare" int value
    CCPR2H--;                     // fix CCPR2H
    LATCbits.LATC1 = 0;           // clear CCP2 "CLK" line
    PIR2bits.CCP2IF = 0;          // clear CCP2 interrupt flag

    ChanB[9] -= ChanB[Qb++];      // adjust end-of-period off time

    if (Qb = 10)                  // if end-of-period
    { Qb = 0;                     // reset Qb array index
      ChanB[9] = 20000;           // reset 20.0-msec period and
      LATAbits.LATA1 = 1;         // toggle 74HC4017 "CLR" line
      LATAbits.LATA1 = 0;         // to force Q0 output sync'
    }
  }
}

Last edited by Mike, K8LH; 7th December 2007 at 11:24 AM.
Mike, K8LH is offline  
Old 6th December 2007, 09:31 AM   (permalink)
Default

Quote:
So will a changing carrier frequency screw up the servos?
The '4017 Servo outputs do experience minor period "jitter" for one 20 msec cycle immediately after one of the Servo pulse width values has been changed. I too thought this might be a problem but Nigel and others have said that the Servos can tolerate a wide period margin. Maintaining a jitter free pulse is more important.

BTW, my 16-channel dual 74HC238 CCP 'PWM' hardware solution is the only one discussed so far with absoluty 0% pulse width jitter and 0% period jitter.

Mike

Last edited by Mike, K8LH; 6th December 2007 at 09:39 AM.
Mike, K8LH is offline  
Old 6th December 2007, 10:11 AM   (permalink)
Default

I will have to look over your code some more then. I just need to find a non-inverting 4-16 demux (two for 18 channel, using one for each robot side.), which is looking impossible. Maybe I will just have to get an inverter for it.

I have not programmed a PIC with C yet, so I am having a hard time with the code. I gotta start looking at some tutorials.

Thanks.
Ambient is online now  
Old 6th December 2007, 11:44 AM   (permalink)
Default

Quote:
Originally Posted by Ambient
I will have to look over your code some more then. I just need to find a non-inverting 4-16 demux (two for 18 channel, using one for each robot side.), which is looking impossible. Maybe I will just have to get an inverter for it.

I have not programmed a PIC with C yet, so I am having a hard time with the code. I gotta start looking at some tutorials.

Thanks.
What are the 4-16 demux' for?

In your opening post you said you'd be programming in C. Whould you like to see that code in Assembler or BASIC instead?
Mike, K8LH is offline  
Old 6th December 2007, 12:11 PM   (permalink)
Default

Mike,

I should have realised that you would use 2 CCP/PWM modules. I had it in my head that the interrupts would somehow collide no matter what you did, this of course doesn't matter when it's hardware. This would be Ambient's best solution at the moment. I also missed your 238 solution which, as you say, will give 16 jitter free outputs. My apologies, I got carried away with the other solution.

I assume the 2 x 4-16 demultiplexers would be to service 9 servos per PWM output. Wouldn't this give 18 jitter free outputs?

Mike.
Pommie is offline  
Old 6th December 2007, 04:00 PM   (permalink)
Default

Quote:
Originally Posted by Pommie
That almost works. If instead of deducting, you only read the UART if the timer has more than 20 cycles remaining. That is, you can tell if a interrupt is imminent and wait for it.
Since the USART has a 2.9 buffer simply checking TMR1H is sufficient. If TMR1H is at full count, 255, at most the program is 256 counts till interrupt. That's 103us if full count with prescaler=4. If running at 115Kbaud, a byte can show in the RXBuffer every 87us, leaving us with a possible 1 byte in the RXBuffer and another showing up while waiting for interrupt. By my calculations there is still enough time to jump to the ISR and finish up reading the RXBuffer in the ISR before creating a Buffer Overflow.

Here is my solution to the USART reading while running 30 servos:

Code:
     While FSR2ptr < lastservobufaddr      ' FSR2 is RX servobuffer
        Do
        Loop Until PIR1.RCIF = 1           ' wait for new RX byte
        While TMR1H = 255                  ' avoid trasfer if close to interrupt
        Wend
        If PIR1.RCIF = 1 Then POSTINC0 = RCREG End If ' load RX byte.. when 30 bytes move on
     Wend
     FSR2ptr = @servobuffer                ' reset RX buffer
     FSR1ptr = @servobuffer                ' setup tranfer of RX array to
     FSR0ptr = @servo                      ' servo work array
     While FSR1ptr < lastservobufaddr
        POSTINC0 = inc(POSTINC1)           ' transfer RX buffer to work values.. add 1
     Wend
This is the change I made to the ISR:

Code:
sub procedure interrupt
    LATA = Not(LATA)                       ' turn on all servos on PortA
    LATB = Not(LATB)                       ' turn on all servos on PortB
    LATC = Not(LATC)                       ' turn on all servos on PORTC
    LATD = Not(LATD)                       ' turn on all servos on PortD
    LATE = Not(LATE)                       ' turn on all servos on PORTE
    pos = 0                                ' 256 counts.. rollover to original value
          ASM
    initdelay:                             ' approx 500us delay using timer1 counts
             movlw     5                   ' prescaler=4, 2.5 counts / microsecond
    delayloop:
             btfsc     PIR1, 5,0           ' check USART RX buffer
             movff     RCREG, POSTINC2     ' move RX byte into servobuffer
             cpfseq    TMR1H, 0            ' timer1 = 1280?
             bra       delayloop
    servomask:                             ' VERY efficient PWM masking routine
             movlw     0
             decfsz    _servo+0, 1,0
             iorlw     1
             decfsz    _servo+1, 1,0
wschroeder is offline  
Old 6th December 2007, 06:51 PM   (permalink)
Default

I was planning on using an 18F and C for the AI and sensors, while using a 16F and assembly for the servo control. The 18F would have to just send the servo control PIC the 2d vector to move in, and pitch...etc data. Unless one PIC can handle all of it?

The two 4-16 demux would just be for sending the PWM signals to each servo, with each controlling 9. Just like with your 3-8 demux for your 16 servos. Could I actually get away with using a single 18F clocked at 20 MHz? I would probably have 10 or so sensors: IR body heat, ultrasonic distance sensor, 2-3 mics, current sensor (for stalled servo detection and touch detection), temp sensors. I want this robot to be able to navigate obstacles on its own using these sensors.

Last edited by Ambient; 6th December 2007 at 07:04 PM.
Ambient is online now  
Old 6th December 2007, 07:10 PM   (permalink)
Default

One option that I just thought of: Use 18F for "brain", and when it needs to update a servos position, it simply sends it to the servo control PIC. The servo control PIC would simply act as a latch of sorts. It would just keep telling the servos their position until it got an update on a certain servos position from the brain. This would really free up the 18F, as it wouldn't have to refresh the servos positions unless it was moving.
Ambient is online now  
Old 6th December 2007, 07:49 PM   (permalink)
Default

As this is for a hexapod (if I remember correctly?) you could have one slave PIC per leg!.
__________________
PIC programmer software, and PIC Tutorials at:
http://www.winpicprog.co.uk
Nigel Goodwin is offline  
Old 6th December 2007, 08:43 PM   (permalink)
Default

Well there is enough room for 1 PIC each leg, that's for sure. The chassis is huge! I just unpacked it, the usable area for electronics is around 8". Very spacious. But I would like to avoid using more PICs than I need to. One 16F690 would be plenty to handle each side, as well as the current sensors on each leg.
Ambient is online now  
Old 6th December 2007, 08:50 PM   (permalink)
Default

Can you post a few pics or a links to pics so we can have a gander at it.
3v0 is online now  
Old 6th December 2007, 09:04 PM   (permalink)
Default

this is the pic on the manufacturer website, they have vids also: http://lynxmotion.com/images/hi-res/ch3r01.jpg
I do not have it assembled at the moment, it is a Christmas present so I have to wait
Ambient is online now  
Old 6th December 2007, 10:31 PM   (permalink)
Default

One other question: If I use a 6V supply for the servos (5-cell NiMH) and a 5V regulator for the PIC, will the PWM servo signal still work properly? Does the PWM voltage need to match the supply voltage of the servo? I can run everything on a 5V buck-boost ad use a huge Lithium cell.
Ambient is online now  
Old 6th December 2007, 10:39 PM   (permalink)
Default

Quote:
Originally Posted by Ambient
One other question: If I use a 6V supply for the servos (5-cell NiMH) and a 5V regulator for the PIC, will the PWM servo signal still work properly? Does the PWM voltage need to match the supply voltage of the servo? I can run everything on a 5V buck-boost ad use a huge Lithium cell.
It will be fine, 6V to the servo's and 5V to the PIC isn't a problem.
__________________
PIC programmer software, and PIC Tutorials at:
http://www.winpicprog.co.uk
Nigel Goodwin is offline  
Old 6th December 2007, 11:46 PM   (permalink)
Default

I mean 5V on the servo input signal from the PIC, with 6V to the servo power.
Ambient is online now  
Reply

Bookmarks

Thread Tools
Display Modes



Similar Threads
Title Starter Forum Replies Latest
555 servo controller? can get them working lompa General Electronics Chat 9 31st May 2007 07:25 AM
Help required with servo motor controller mayhem Robotics Chat 3 26th May 2006 05:21 PM
Auto servo controller, need help with the 555 linuxglobal General Electronics Chat 2 20th April 2006 04:53 PM
looking for servo controller circuit diagram using switch ? calico Micro Controllers 49 27th February 2006 02:36 AM
Help me start, making a servo controller for motorcycle use. motoracer General Electronics Chat 4 11th November 2003 11:29 PM



All times are GMT. The time now is 01:10 AM.


Electronic Circuits  |  Learning Electronics
Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.

eXTReMe Tracker