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...
stecj366
Sonar is meer dan Ping...
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 
Daan Timmer
Ik ben programmeur! geen electronicus! http://www.daantimmer.nl/ Er is een ontwerp! nu nog inhoud :-)
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.