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
 
Thread Tools Display Modes
Old 20th July 2006, 08:11 AM   (permalink)
Default

BTW Mike, you're posting your graphics as large, low quality, JPG's, if you use GIF or PNG they will be much smaller and perfect quality. You should only use JPG for photo's.
__________________
PIC programmer software, and PIC Tutorials at:
http://www.winpicprog.co.uk
Nigel Goodwin is offline  
Reply With Quote
Old 20th July 2006, 11:30 AM   (permalink)
Default

Quote:
Originally Posted by hjames
Okay, I see what you're getting at.

If we look at the last servo in a set and and we say that all the servo's are sitting at 1msec pulse widths, and on the next frame we suddenly increas all the pulse widths to 2msec, the last (say 8th one) will end up having a 20 + 7 msec gap between pulses. If we then decrease all the pulse widths back to 1msec, then the 8th servo will end up having a 20-7msec gap between pulses.

So yeah, there will be a pulse gap variation - but as long as the servo is happy with a worst-case 27msec update period, everything should still be okay. Plus this is definitely worst-case since suddenly railing servo's isn't exactly a useful thing to be doing a first place.
So it seems that 20-msec overall period isn't nearly as important or critical as the pulse width. Cool. Thanks for explaining.

Mike
Mike, K8LH is offline  
Reply With Quote
Old 20th July 2006, 01:48 PM   (permalink)
Default

I am very new to RC stuff as well, but I noticed on my sons nitro car servos that there is a throttle trim, this is added to the 1-2ms pulse

How are the registers than control the servos manipulated? This will need to be taken into consideration when calculating the timings if a non-interupt method of control is implimented.

As I understand it a servo window is defined as a 20MS time period (space) with the position information (nominally 1-2MS) (mark) contained within this time period, is this correct?

I have an idea, but a bit more info on how you want to control the servos, i.e. rs232 etc and the correct timings would be good.
__________________
Regards


MATT!
Matt(Pic progger) is offline  
Reply With Quote
Old 20th July 2006, 02:09 PM   (permalink)
Default

James,

Just got a chance to look at the 'HCT238 Data Sheet and you're right. It's a perfect match for modulating one of the eight output lines with a PWM signal driving E1.

Thank you for the tip. My Crazy-8 PWM Servo controller concept just got a whole lot smaller by dumping that clumsy EPROM in favor of an 'HCT238. Cool!

Regards, Mike

~~~~~~~~~~~~~

Nigel,

I apologize for wasting server space. I just figured out why my PNG graphics were larger than JPG graphics. I was saving them from JPG to PNG. When I load the original graphics and save them immediately as PNG they're half the size of the JPG files.

I suspect a 12F683 Servo controller with a bit-banged 1200 or 2400 baud serial interface might be somewhat limiting. An 'F628A or an 'F88 with built-in serial port is probably a better choice with the option of implementing the crystal oscillator if needed for stability.

Here's the ISR "engine" with comments to help you understand the concept. So, would this work guys? Is it worth the extra chip?

Code:
        org     h'0004'

ISR_Vector
;
;  save main program context
;
        movwf   W_ISR           ; save W-reg                      |B?
        swapf   STATUS,W        ; doesn't change STATUS bits      |B?
        movwf   S_ISR           ; save STATUS reg                 |B?
        clrf    STATUS          ; force bank 0                    |B0
        movf    FSR,W           ;                                 |B0
        movwf   F_ISR           ; save FSR                        |B0
        bcf     PIR1,TMR2IF     ; clear TMR2 interrupt flag       |B0
;
;  setup 74HCT238 address lines to select this periods active 
;  Servo (duty cycle was set in previous PWM interrupt cycle).
;
;  a minimum 96-usec window at the beginning of each interrupt
;  where PWM is high and the 74HCT238 outputs are low provides 
;  more than enough time to setup the address lines before the
;  PWM output goes active low.
;
        movf    PORTA,W         ; read PORTA                      |B0
        andlw   b'11111000'     ; preserve PORTA b7..b3 bits      |B0
        iorwf   Servo,W         ; Servo b2..b0 bits are used as   |B0
        movwf   PORTA           ; 74HCT238 a2..a0 address bits    |B0
;
;  increment Servo [0..7] for next PWM cycle
;
        incf    Servo,f         ; increment servo                 |B0
        bcf     Servo,3         ; mod(Servo/8), [0..7]            |B0
;
;  we use the PWM off-time to drive the 74HCT238 E1 gate so
;  we invert the PWM duty cycle by subtracting the servo duty
;  cycle value of 50..300 (8-usec ticks) from the PWM period
;  value of 312 (2496-usec PWM period / 8-usec).
;
;  calculate inverse duty cycle for next PWM cycle
;
        movf    Servo,W         ; servo number [0..7]             |B0
        addlw   SArray          ; add to array address            |B0
        movwf   FSR             ; setup indirect address          |B0
        clrf    DutyHi          ;                                 |B0
        movf    INDF,W          ; the Servo PWM value [000..250]  |B0
        addlw   d'50'           ; add 0.4-msec offset [050..300]  |B0
        skpnc                   ; carry? no, skip, else           |B0
        incf    DutyHi,f        ; increment duty cycle hi         |B0
        sublw   low  d'312'     ; subtract from PWM period        |B0
        movwf   DutyLo          ; save inverse duty cycle lo      |B0
        movf    DutyHi,W        ;                                 |B0
        skpc                    ; borrow?                         |B0
        incf    DutyHi,W        ;                                 |B0
        sublw   high d'312'     ;                                 |B0
        movwf   DutyHi          ; save inverse duty cycle hi      |B0
;
;  inverse duty cycle result is a value between 12 (PWM hi for
;  96-usecs and active low for 2400-usecs) and 262 (PWM hi for
;  2096-usecs and active low for 400-usecs).
;
;  setup duty cycle registers for next PWM cycle
;
        rrf     DutyHi,f        ; shift result                    |B0
        rrf     DutyLo,W        ;                                 |B0
        movwf   CCPR1L          ; set 006..131 (16-usec ticks)    |B0
        bcf     CCP1CON,CCP1X   ;                                 |B0
        skpnc                   ; odd 8-us tick? no, skip, else   |B0
        bsf     CCP1CON,CCP1X   ; set the odd 8-usec tick         |B0
;
;  restore main program context
;
        movf    F_ISR,W         ;                                 |B0
        movwf   FSR             ; restore FSR                     |B0
        swapf   S_ISR,W         ;                                 |B0
        movwf   STATUS          ; restore STATUS                  |B?
        swapf   W_ISR,f         ; don't screw up STATUS           |B?
        swapf   W_ISR,W         ; restore W-reg                   |B?
        retfie                  ; return from interrupt           |B?
Attached Images
File Type: png Crazy-8 Servo Controller v1.PNG (35.9 KB, 22 views)

Last edited by Mike, K8LH; 22nd July 2006 at 02:08 PM.
Mike, K8LH is offline  
Reply With Quote
Old 20th July 2006, 02:28 PM   (permalink)
Default

Quote:
Originally Posted by Mike, K8LH
Nigel,

I apologize for wasting server space. I just figured out why my PNG graphics were larger than JPG graphics. I was saving them from JPG to PNG. When I load the original graphics and save them immediately as PNG they're half the size of the JPG files.
You can't take an omelette and recover the eggs from it same as a graphic, once you've ruined it, it's gone for ever (unless you do a LOT of editting).
__________________
PIC programmer software, and PIC Tutorials at:
http://www.winpicprog.co.uk
Nigel Goodwin is offline  
Reply With Quote
Old 19th February 2008, 04:09 AM   (permalink)
Default

I am using a PIC18F252 to control 12 servos(for a 4 legged bot). I am using MCC-18 and thought that I would just share my method -

Code:
#include <p18f252.h>
#include <timers.h>
#include <delays.h>

unsigned int servo[12];
char count=0, count1=0;

void interruptVectorHigh (void);

void main(void)
{
	char i;

	TRISB = 0x00;
	TRISA = 0x00;
	TRISC = 0x00;
	
	PORTB = 0x00;
	PORTA = 0x00;
	PORTC = 0x00;
	
	RCON = 0b000000000; 
	INTCON = 0b10100000;

	OpenTimer0( TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_2 );
	OpenTimer1( TIMER_INT_ON & T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_2 & T1_OSC1EN_OFF & T1_SYNC_EXT_OFF );
	OpenTimer3( TIMER_INT_ON & T3_16BIT_RW & T3_SOURCE_INT & T3_PS_1_2 & T3_OSC1EN_OFF & T3_SYNC_EXT_OFF );

	for(i=0;i<12;i++)
		servo[i]=59400;
	
	WriteTimer0(15535);		//Trigger Interrupted after 20mS
	WriteTimer1(65534);		//This is just a small initial delay chosen at random.
	WriteTimer3(65534);

	while(1)
	{
	// centre - 59400
	// left(anticlockwise)   - 62770
	// right(clockwise)  - 56030



	//add any code to move the servos here by assigning a value between 56030 and 62770 to servo[0] to servo[11]. the code enables automatic holding



	}
}


#pragma code interruptVectorHigh = 0x08
void interruptVectorHigh (void)
{
	_asm
	goto interruptHandlerHigh
	_endasm
}

#pragma code
#pragma interrupt interruptHandlerHigh

void interruptHandlerHigh()
{
	if(INTCONbits.TMR0IF)
	{
		WriteTimer0(15535);
		WriteTimer1(65534);
		WriteTimer3(65534);
	
		count = 0;
		count1 = 0;
		INTCONbits.TMR0IF = 0;
	}
	if(PIR1bits.TMR1IF == 1 && PIE1bits.TMR1IE == 1)
	{
		switch(count)
		{		
			case 0:	PORTBbits.RB0=1;
					WriteTimer1(servo[0]);	
					break;
			case 1:	PORTBbits.RB0=0;
					PORTBbits.RB1=1;
					WriteTimer1(servo[1]);
					break;
			case 2:	PORTBbits.RB1=0;
					PORTBbits.RB2=1;
					WriteTimer1(servo[2]);
					break;
			case 3:	PORTBbits.RB2=0;
					PORTBbits.RB3=1;
					WriteTimer1(servo[3]);
					break;
			case 4:	PORTBbits.RB3=0;
					PORTBbits.RB4=1;
					WriteTimer1(servo[4]);
					break;
			case 5:	PORTBbits.RB4=0;
					PORTBbits.RB5=1;
					WriteTimer1(servo[5]);
					break;
			case 6:	PORTBbits.RB5=0;
					break;
		}
		count++;	
		PIR1bits.TMR1IF = 0;
		PIE1bits.TMR1IE = 1;
	}
	if(PIR2bits.TMR3IF == 1 && PIE2bits.TMR3IE == 1)    
	{
		switch(count1)
		{		
			case 0:	PORTAbits.RA5=1;
					WriteTimer3(servo[6]);
					break;
			case 1:	PORTAbits.RA5=0;
					PORTAbits.RA4=1;
					WriteTimer3(servo[7]);
					break;
			case 2:	PORTAbits.RA4=0;
					PORTAbits.RA3=1;
					WriteTimer3(servo[8]);
					break;
			case 3:	PORTAbits.RA3=0;
					PORTAbits.RA2=1;
					WriteTimer3(servo[9]);
					break;
			case 4:PORTAbits.RA2=0;
					PORTAbits.RA1=1;
					WriteTimer3(servo[10]);
					break;
			case 5:PORTAbits.RA1=0;
					PORTAbits.RA0=1;
					WriteTimer3(servo[11]);
					break;
			case 6:PORTAbits.RA0=0;
					break;
		}
		count1++;	
		PIR2bits.TMR3IF = 0;
		PIE2bits.TMR3IE = 1;
	}
	INTCONbits.GIE = 1;
}
SentinelsOfEvil is offline  
Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes




All times are GMT. The time now is 07:33 AM.


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