Ik wil een servo signaal inlezen in C.

Nu vind ik op internet genoeg voorbeelden voor basic maar niets voor C.

Ik moet een puls meten die tussen de 0,7ms en 2,3ms kan liggen.

ik wil dit met een resolutie doen van 256 stappen.

1,6 / 256 = 0,00625 ms = 6,25 us

dit signaal moet later weer een servo aansturen.

hoe kan ik dit doen?? Met timers of?

Het gaat om in totaal 6 servo kanalen die ingelezen dienen te worden. Dus het moet ook vrij efficient gebeuren.

[Bericht gewijzigd door veenie op (28%)]

Komt dit signaal toevallig van een 6kanaal servo ontvanger?
Want dan zou je beter de ontvanger "hacken" en daar een bepaald signaal uit halen, heb je ineens ook maar 1 pin nodig.

http://en.wikipedia.org/wiki/Pulse-position_modulation

Dat ontvangt de ontvanger en met dit kan je alle kanalen lezen en dus ook meten.

Misschien dat je hier iets aan hebt.
http://www.pabr.org/pxarc/doc/opwm_ppm.gif

[Bericht gewijzigd door chrome op (12%)]

komt uit een 8 kanaals ontvanger of meer.

Ontvanger hacken is geen optie... Moet zonder aanpassingen aan andere hardware mogelijk zijn...

Als ik het goed begijp wil je de signalen opnemen, om ze dan later weer af te spelen?

Wat je zou kunnen doen: de PWM frequentie voor servo's is iets van 50HZ ofzo? Je wil 8 signalen stockeren, da's goed, dat is net een byte. Hang alle signalen aan een poort van je (8-bit) microcontroller.

Je wil een resolutie van 256 stappen, dus je moet dat signaal tegen 12.5kHz (50Hz*256) bemonsteren. Dat kan op twee manieren:
1) als je snel in de ISR kan springen: maak een timer die tegen 12.5kHz de ISR aanroept, en in die ISR stockeer je de waarde van de 8bits poort.

2) als je niet snel genoeg in de ISR kan springen: genereer hardwarematig een blok van 12.5kHz, hang die aan een pin van je microcontroller, en poll die in een loop om te zien wanneer er een stijgende flank is, en stockeer dan de waarde van de poort.

Dit is niet de meest efficiente manier qua geheugengebruik, maar het zal wel werken :)

Weet je overigens al met wat voor soort controller je dit wilt oplossen?

Ikw eet dat een PIC een *Capture* module heeft. Die kan je instellen dat hij begint met tellen vanaf hoog, stopt met tellen vanaf laag en zodra hij weer hoog gaat geeft hij de *period*.

M.a.w. daarmee kan je PWM signalen automatisch inlezen. Maar als je er 8 nodig hebt, dan wordt het wel weer lastig denk ik >_> Zijn niet veel PIC's met 8 van dergelijke modules, volgens mij is het meeste 4.

Overigens kan je het dan nog steeds laten doen met een timer. 1timer loopt de gehele tijd en dan moet je even kijken of je 8interrupt pinnen hebt of dat je moet gaan pollen, maar die timer kan je dan gebruiken voor de tijd.

ik heb nu dit in samenwerking met iemand anders kunnen opzetten..


#include <system.h>
#pragma DATA 0x2007, 0x3F3A
#pragma CLOCK_FREQ           20000000

unsigned char pwm_in_buf[8] = {0,0,0,0,0,0,0,0};
unsigned char pwm_in_val[8] = {0,0,0,0,0,0,0,0};

char states = 0;
char timer_temp;
char timer1;

void main()
{
    char i = 0;

    // init 
    
    trisb = 11111111b;
    
    // timer 1 moet draaien en de snelheid hangt 
    // af van de in te lezen pwm signalen

    while(1)
    {

        for(i=0;i<8;i++)
        {	
            if ((portb ^ states) & (1 << i))
            {
                // set nieuwe staat in geheugen
                states = (states & ~(1 << i)) | (portb & (1 << i));

                // verandering
                if (portb & (1 << i))
                {
                    // rising edge
                    // zet startwaarde in buffer
                    pwm_in_buf[i] = TMR1;
                }
                else
                {
                    // falling edge
                    // bereken tijd in ticks
                    
                    timer_temp = timer1;
                    if(timer_temp < pwm_in_buf[i])
                    {
                        // overflow geweest - moet even creatief gerekend worden.....
                        timer_temp = pwm_in_buf[i] - timer_temp;
                        pwm_in_val[i] = 0 - timer_temp;
                        
                    }
                    else
                    {
                        // geen overflow geweest
                        pwm_in_val[i] = timer_temp - pwm_in_buf[i];
                    
                  }
                    
                }
                
            }
        }
    
    }

}

PIC = 16F877A.

als iemand hem nog wilt nalopen en / of tips heeft? of uiteraard voorbeeldcode is nog altijd zeer wenselijk.

nu alleen nog de timer instellen.. en zien hoe ik dingen uit kan meten ;)...

inmiddels alles in een hoedje gestopt.

maar het inlezen gaat nog niet zoals het hoort.. krijg rare signalen binnen...


#include <system.h>
#pragma DATA 0x2007, 0x3F3A
#pragma CLOCK_FREQ           20000000

unsigned char pwm_in_buf[8] = {0,0,0,0,0,0,0,0};
unsigned char pwm_in_val[8] = {0,0,0,0,0,0,0,0};

char states = 0;
char timer_temp;
char timer1;


void main()
{

		//      76543210
    trisa = 00000000b;
		trisb = 11111111b;
		trisc = 00000000b;
		trisd = 00000000b;
		trise = 00000000b;
		
		porta = 00000000b;
		portb = 00000000b;
		portc = 00000000b;
		portd = 00000000b;
		porte = 00000000b;
    
    char i = 0;
    char x = 0;
    char servo1 = 230;		//Waarde Servo 1
		char servo2 = 150;			//Waarde Servo 2
		char servo3 = 150;		//Waarde Servo 3
		char servo4 = 120;		//Waarde Servo 4
		char freq = 12;				//Waarde Frequentie PWM. (Standaard = 20 (50hz))

    
    //Timer2 instellen 
				set_bit( t2con, T2CKPS1 ); //prescaler rate 1:16 
				set_bit( t2con, T2CKPS0 ); //Set timer 2 postscaler rate 
				
				set_bit( t2con, TOUTPS3 ); //postscaler rate 1:16 
				set_bit( t2con, TOUTPS2 ); 
				set_bit( t2con, TOUTPS1 ); 
				set_bit( t2con, TOUTPS0 ); //Set timer 2 mode (enable or disable) 
				
				set_bit( t2con, TMR2ON ); //enable timer 2 


    // init 
    
    // timer 1 moet draaien en de snelheid hangt 
    // af van de in te lezen pwm signalen

    while(1)
    {
			{
					if (tmr2 < 128) 
						clear_bit(portb,7);
					
					else 
						set_bit(portb,7);
			}
	
				for(i=0;i<8;i++)
					{	
							if ((portb ^ states) & (1 << i))
							{
									// set nieuwe staat in geheugen
									states = (states & ~(1 << i)) | (portb & (1 << i));
	
									// verandering
									if (portb & (1 << i))
									{
											// rising edge
											// zet startwaarde in buffer
											pwm_in_buf[i] = tmr2;
									}
									else
									{
											// falling edge
											// bereken tijd in ticks
											timer_temp = tmr2;
											if(timer_temp < pwm_in_buf[i])
											{
													// overflow geweest - moet even creatief gerekend worden.....
													timer_temp = pwm_in_buf[i] - timer_temp;
													pwm_in_val[i] = 0 - timer_temp;
											}
											else
											{
													// geen overflow geweest
													pwm_in_val[i] = timer_temp - pwm_in_buf[i];
											}
											
									}
                
            }
        }

		for(x=0;x<30;x++)  //Start Pulstrein
			{
				set_bit(porta,0);						//Opgaande flank Servo 1
				delay_10us(pwm_in_val[0]);         //Signaal Servo 1 (70 - 230)
	 			clear_bit(porta,0);					//Neergaande flank Servo 1
	 			
	 			delay_ms(1);								//Vertraging nodig voor zuiver werken servo en PIC
	 			
	 			set_bit(porta,1);						//Opgaande flank Servo 2
				delay_10us(servo2);         //Signaal Servo 2 (70 - 230)
				clear_bit(porta,1);					//Neergaande flank Servo 2
				
	 			delay_ms(1);								//Vertraging nodig voor zuiver werken servo en PIC
	 			
	 			set_bit(porta,2);						//Opgaande flank Servo 3
				delay_10us(servo3);         //Signaal Servo 3 (70 - 230)
				clear_bit(porta,2);					//Neergaande flank Servo 3
				
	 			delay_ms(1);								//Vertraging nodig voor zuiver werken servo en PIC
	 				 			
				set_bit(porta,3);						//Opgaande flank Servo 4
				delay_10us(servo4);         //Signaal Servo 4 (70 - 230)
				clear_bit(porta,3);					//Neergaande flank Servo 4
									 			
				delay_ms(freq);       			//PWM Breedte bepalen tussen 45Hz en 62Hz
			}


  
    }
    }

het signaal veranderd steeds volgens de pic.. dus iets gaat fout in het inlezen.