![]() |
| | |||||||
| Registreer | Adverteerders | FAQ | Ledenlijst | Interessegroepen | Zoeken | Berichten van vandaag | Markeer forums als gelezen |
![]() |
| | Discussietools | Weergave |
| | #1 (permalink) |
| Lid sinds: 8 juli 2003 Locatie: Mijdrecht Leeftijd: 24
Berichten: 8.246
|
Aangezien op circuitsonline niet veel reactie komt op dit soort onderwerpen.. En er bar weinig over te vinden is misschien hier iemand die er meer ervaring in heeft. Ik wil 4 servo signalen inlezen. Nu heb ik al wel wat code maar deze is te traag... servos reageren niet soepel. en ik wil 4 servos aansturen. Dit gaat wel goed met picbasic maar niet goed met C.
__________________ Mvg. Alwin ►Trucks: Liebherr LTM1090/2 [Bouwfase], Scania VSB met stenentrailer, Scania Torpedo Bergingswagen ►De Asfalt Rockers Liever 8 plofjes, dan 6 die er klappen |
| | |
| | #3 (permalink) |
| Lid sinds: 8 juli 2003 Locatie: Mijdrecht Leeftijd: 24
Berichten: 8.246
| Code: #pragma DATA 0x2007, 0x3F3A //PIC16F877A op 20Mhz Externe klok
#pragma CLOCK_FREQ 20000000
#include <system.h>
char x;
char servo1 = 230;
char servo2 = 70;
char servo3 = 0;
char servo4 = 0;
char freq = 4;
void main()
{
trisa = 00000000b;
trisb = 00000000b;
trisc = 00000000b;
trisd = 00000000b;
trise = 00000000b;
porta = 00000000b;
portb = 00000000b;
portc = 00000000b;
portd = 00000000b;
porte = 00000000b;
while(1)
{
for(x=0;x<30;x++) // send a pulse train
{
set_bit(portb,0);
delay_10us(servo1); //1ms pulse width
clear_bit(portb,0);
delay_ms(freq); //at a periodicity of around 50hz
}
for(x=0;x<30;x++) // send a pulse train
{
set_bit(portb,1);
delay_10us(servo2); //1ms pulse width
clear_bit(portb,1);
delay_ms(freq); //at a periodicity of around 50hz
}
for(x=0;x<30;x++) // send a pulse train
{
set_bit(portb,2);
delay_10us(servo3); //1ms pulse width
clear_bit(portb,2);
delay_ms(freq); //at a periodicity of around 50hz
}
for(x=0;x<30;x++) // send a pulse train
{
set_bit(portb,3);
delay_10us(servo4); //1ms pulse width
clear_bit(portb,3);
delay_ms(freq); //at a periodicity of around 50hz
}
}
} ik zoek een efficientere servo code...
__________________ Mvg. Alwin ►Trucks: Liebherr LTM1090/2 [Bouwfase], Scania VSB met stenentrailer, Scania Torpedo Bergingswagen ►De Asfalt Rockers Liever 8 plofjes, dan 6 die er klappen |
| | |
| | #4 (permalink) |
| Guest
Berichten: n/a
|
Wat moet de code precies doen? Ik vermoed dat een deel van je probleem huist in het feit dat je 4 afzonderlijke pulstreinen maakt voor je servo's en daarmee je servo's eigenlijk op 1/4 snelheid draaien. Zet het geheel eens in 1 for-loop.. maar zonder een beschrijving van wat je precies wil, kan ik er niet zoveel mee.. Laatst gewijzigd door hezik; 2 mei 2009 om 02:51 |
|
| | #5 (permalink) |
| Lid sinds: 8 juli 2003 Locatie: Mijdrecht Leeftijd: 24
Berichten: 8.246
|
4 servos aansturen is target 1. ik heb al getracht om met maar 1 for loop te doen echter krijg je dan rare effecten.
__________________ Mvg. Alwin ►Trucks: Liebherr LTM1090/2 [Bouwfase], Scania VSB met stenentrailer, Scania Torpedo Bergingswagen ►De Asfalt Rockers Liever 8 plofjes, dan 6 die er klappen |
| | |
| | #6 (permalink) |
| Lid sinds: 2 december 2007 Locatie: Eindhoven Leeftijd: 41
Berichten: 1.266
|
Als je een degelijke aansturing wilt zul je niet met FOR loopjes moeten gaan werken. Bij iedere interrupt gaat je servo een andere positie aan nemen om dat je FOR loop gedelayed kan wordt. De 16F877 heeft twee comparators, je hebt er maar 1 nodig voor 4 servos. Het voordeel van deze manier is dat je de PIC vrij houdt voor andere dingen. En je het realtime stuk op interrupt basis doet. Kan je zo geen voorbeeld sturen, omdat ik alleen met 18F's en 30F's heb gewerkt. Maar hier twee links met meer info. PWM for the PIC Micro: PWM or Pulse width Modulation. How to create a PIC PWM using an Interrupt. Bart,
__________________ MVSB , PilotRC Sbach 107" Electro , EF Extra 88" Electro, Flyfly MIG 29 (3 kW) met 2D trust vectoring. |
| | |
| | #7 (permalink) |
| Lid sinds: 2 december 2007 Locatie: Eindhoven Leeftijd: 41
Berichten: 1.266
|
En probeer het hier eens in de robotica forum, die doen niks anders. http://www.circuitsonline.net/forum/search.php?query=PWM+C+PIC&mode=and&starter_user=& message_user=&topic_type=0§ions[]=21&sort=0 Bart
__________________ MVSB , PilotRC Sbach 107" Electro , EF Extra 88" Electro, Flyfly MIG 29 (3 kW) met 2D trust vectoring. |
| | |
| | #8 (permalink) |
| Lid sinds: 2 juni 2006 Locatie: Beverwijk Roepnaam: Jeroen Leeftijd: 42
Berichten: 22.187
Weblogartikelen: 2 |
Deze PICServo Controller 8 Servo Variant als voorbeeld. Met een beetje Google kom je er wel. Aansturen kun je op twee manieren doen: - Servo's synchroon Op zich de makkelijkste manier omdat je pulstrein op alle kanalen gelijk start en op basis van de counter het masker voor de desbetreffende poorten verandert - Servo's achter elkaar Lastiger omdat je timing tussen de twee pulsen gelijk moet blijven (frame rate) en je counter dus voor elke servo apart moet starten
__________________ Ik discussieer niet, ik probeer je uit te leggen waarom ik gelijk heb. |
| | |
| | #10 (permalink) |
| Lid sinds: 8 juli 2003 Locatie: Mijdrecht Leeftijd: 24
Berichten: 8.246
|
Ok deze code werkt inmiddels: Code: #pragma DATA 0x2007, 0x3F3A //PIC16F877A op 20Mhz Externe klok
#pragma CLOCK_FREQ 20000000
#include <system.h>
char x;
char servo1 = 230;
char servo2 = 70;
char servo3 = 150;
char servo4 = 120;
char freq = 12;
void main()
{
trisa = 00000000b;
trisb = 00000000b;
trisc = 00000000b;
trisd = 00000000b;
trise = 00000000b;
porta = 00000000b;
portb = 00000000b;
portc = 00000000b;
portd = 00000000b;
porte = 00000000b;
while(1)
{
for(x=0;x<30;x++) // send a pulse train
{
set_bit(portb,0);
delay_10us(servo1); //1ms pulse width
clear_bit(portb,0);
delay_ms(1);
set_bit(portb,1);
delay_10us(servo2); //1ms pulse width
clear_bit(portb,1);
delay_ms(1);
set_bit(portb,2);
delay_10us(servo3); //1ms pulse width
clear_bit(portb,2);
delay_ms(1);
set_bit(portb,3);
delay_10us(servo4); //1ms pulse width
clear_bit(portb,3);
delay_ms(freq); //at a periodicity of around 50hz
}
/* for(x=0;x<30;x++) // send a pulse train
{
set_bit(portb,1);
delay_10us(servo2); //1ms pulse width
clear_bit(portb,1);
delay_ms(freq); //at a periodicity of around 50hz
}
for(x=0;x<30;x++) // send a pulse train
{
set_bit(portb,2);
delay_10us(servo3); //1ms pulse width
clear_bit(portb,2);
delay_ms(freq); //at a periodicity of around 50hz
}
for(x=0;x<30;x++) // send a pulse train
{
set_bit(portb,3);
delay_10us(servo4); //1ms pulse width
clear_bit(portb,3);
delay_ms(freq); //at a periodicity of around 50hz
}
*/
}
}
__________________ Mvg. Alwin ►Trucks: Liebherr LTM1090/2 [Bouwfase], Scania VSB met stenentrailer, Scania Torpedo Bergingswagen ►De Asfalt Rockers Liever 8 plofjes, dan 6 die er klappen Laatst gewijzigd door Cheeta; 2 mei 2009 om 14:16 |
| | |
| | #11 (permalink) |
| Lid sinds: 2 juni 2006 Locatie: Beverwijk Roepnaam: Jeroen Leeftijd: 42
Berichten: 22.187
Weblogartikelen: 2 |
Ik zou de resterende vertragingstijd (delay_ms) gelijk maken aan de totale tijd min de pulsbreedte. Dus bij een totale puls-puls tijd van 20msec van die 20msec de tijd van de pulsbreedte van de servopositie halen. Je hebt kans dat een duurdere servo een failsafe heeft ingebouwd op basis van een PLL-systeem. Als de puls-pulstijd verloopt gaat de servo in failsafe mode om schade aan de servo te voorkomen. Misschien verstandig om eerst in de middenstand van de servo te beginnen, dus een pulsbreedte van 1,5msec. Het kan zijn dat de pulsbreedte voor het gebruikte type servo te weinig is (bijv. omdat deze tussen 1,2msec en 1,8msec zijn werk doet).
__________________ Ik discussieer niet, ik probeer je uit te leggen waarom ik gelijk heb. |
| | |
| | #12 (permalink) |
| Lid sinds: 8 juli 2003 Locatie: Mijdrecht Leeftijd: 24
Berichten: 8.246
|
Hoi sleurhutje je was sneller dan dat ik kon editen. Het zijn el cheapo servo's die ik nu gebruik. Het probleem zat hem in dat kennelijk de PIC even tijd nodig heeft om een poort weer laag te maken en de volgende gelijk weer hoog. Dat is nu opgelost. Hier een volledig overzicht van het programma + tekst / uitleg. Code: #pragma DATA 0x2007, 0x3F3A //PIC16F877A met externe klok
#pragma CLOCK_FREQ 20000000 //Snelheid klok = 20Mhz
#include <system.h> //Commando's Include *standaard sourceboost header file*
char x; //Teller PWM Loop
char servo1 = 230; //Waarde Servo 1
char servo2 = 70; //Waarde Servo 2
char servo3 = 150; //Waarde Servo 3
char servo4 = 120; //Waarde Servo 4
char freq = 12; //Waarde Frequentie PWM. (Standaard = 20 (50hz))
void main()
{
trisa = 00000000b; //PoortA Alles uitgang
trisb = 00000000b; //PoortB Alles uitgang
trisc = 00000000b; //PoortC Alles uitgang
trisd = 00000000b; //PoortD Alles uitgang
trise = 00000000b; //PoortE Alles uitgang
porta = 00000000b; //PoortA Alles = 0 (laag)
portb = 00000000b; //PoortB Alles = 0 (laag)
portc = 00000000b; //PoortC Alles = 0 (laag)
portd = 00000000b; //PoortD Alles = 0 (laag)
porte = 00000000b; //PoortE Alles = 0 (laag)
while(1)
{
for(x=0;x<30;x++) //Start Pulstrein
{
set_bit(portb,0); //Opgaande flank Servo 1
delay_10us(servo1); //Signaal Servo 1 (70 - 230)
clear_bit(portb,0); //Neergaande flank Servo 1
delay_ms(1); //Vertraging nodig voor zuiver werken servo en PIC
set_bit(portb,1); //Opgaande flank Servo 2
delay_10us(servo2); //Signaal Servo 2 (70 - 230)
clear_bit(portb,1); //Neergaande flank Servo 2
delay_ms(1); //Vertraging nodig voor zuiver werken servo en PIC
set_bit(portb,2); //Opgaande flank Servo 3
delay_10us(servo3); //Signaal Servo 3 (70 - 230)
clear_bit(portb,2); //Neergaande flank Servo 3
delay_ms(1); //Vertraging nodig voor zuiver werken servo en PIC
set_bit(portb,3); //Opgaande flank Servo 4
delay_10us(servo4); //Signaal Servo 4 (70 - 230)
clear_bit(portb,3); //Neergaande flank Servo 4
delay_ms(freq); //PWM Breedte bepalen tussen 45Hz en 62Hz
}
}
} http://pastebin.com/d16c30fea
__________________ Mvg. Alwin ►Trucks: Liebherr LTM1090/2 [Bouwfase], Scania VSB met stenentrailer, Scania Torpedo Bergingswagen ►De Asfalt Rockers Liever 8 plofjes, dan 6 die er klappen Laatst gewijzigd door Cheeta; 2 mei 2009 om 16:26 |
| | |
| | #13 (permalink) |
| Lid sinds: 8 juli 2003 Locatie: Mijdrecht Leeftijd: 24
Berichten: 8.246
|
Mocht iemand nog voorbeeld code hebben van hoe je bij C servo signalen kunt inlezen zijn deze altijd welkom. Ik vind alleen wat dingen in ASM. Maar daar ben ik niet mee bekend. *weet wel dat dit past binnen de C compiler.. maar ik kan het niet lezen...*
__________________ Mvg. Alwin ►Trucks: Liebherr LTM1090/2 [Bouwfase], Scania VSB met stenentrailer, Scania Torpedo Bergingswagen ►De Asfalt Rockers Liever 8 plofjes, dan 6 die er klappen |
| | |
| | #14 (permalink) |
| Lid sinds: 2 juni 2006 Locatie: Beverwijk Roepnaam: Jeroen Leeftijd: 42
Berichten: 22.187
Weblogartikelen: 2 |
Ik ben geen PIC expert, ik programmeer voor de hobby Philips 80C5xx derivaten en sinds kort Atmel AVR's. Ik programmer alleen direct in assembler. Dat is een ervenis uit een ver verleden. Met de Atmel controllers gebruik ik voornamelijk interrupts. Ik een timer die elke 10 microseconde een interrupt genereert. Binnen de interrupt-routine wordt de teller voor de puls opgehoogd. Mijn frame rate staat op 16,5 milliseconde dus in totaal wordt er per puls-puls tot 1650 (0x0672) geteld. Elke servopuls start met een opgaande flank (pin high) als de teller op nul staat. Tijdens het tellen wordt eerst de minimale pulsbreedte geteld, dat is een constante. Als deze waarde overschreden is, wordt in de waarde van de desbetreffende servo gekeken of de gewenste pulsbreedte gehaald is. Zodra de gewenste pulsbreedte voor de desbetreffende servo gehaald is, wordt de neergaande flank gemaakt (pin low). Daarna is het weer een kwestie van doortellen tot 1649 om vervolgens alles opnieuw te doen. Met deze methode heb je gelijk ervoor gezorgd dat je servo nooit onder de minimale waarde kan komen en je eventueel met meer programmeerwerk en minimum (en zelfs maximum) uitslag kan controleren. De positie van de ingaande kant, dus signaal van de ontvanger naar de controller, kan binnen precies dezelfde interrupt routine. Op de pin met het inkomende servo-signaal laat je een interrupt genereren bij een opgaande flank. Op dat moment zet je de teller voor de positiebepaling op 0. Vervolgens doe in binnen de hiervoor genoemde timer interrupt controleren of de input pin weer laag is geworden. Is dat niet het geval dan verhoog je de teller. Is dat wel het geval dan weet je het getal van de positie en kunt die opslaan (beetje bitneuken maar wat maakt het uit als je 300 bytes van 16 kbytes gebruikt Als je dit uitbreidt kun je ook de optie maken om de minimum en maximum uitslag "te leren" door de laagste en hoogste waarde te gebruiken als referentie. Vervolgens bereken je het middelpunt en de maximale uitslag voor je uitgaande servo's. Mogelijkheden te over Misschien dat dit je op nieuwe ideeën brengt.
__________________ Ik discussieer niet, ik probeer je uit te leggen waarom ik gelijk heb. Laatst gewijzigd door Sleurhutje; 2 mei 2009 om 16:45 |
| | |
| | #15 (permalink) |
| Lid sinds: 8 juli 2003 Locatie: Mijdrecht Leeftijd: 24
Berichten: 8.246
|
ik moet de tijd meten dat een signaal hoog is tussen de 0,7 - 2,3ms. Dit kan ik doen met interrupts maar kan dit ook met 6 kanalen tegelijk? zover ik weet heeft de 16F877A maar 2 ingangen voor interrupts van externe signalen.
__________________ Mvg. Alwin ►Trucks: Liebherr LTM1090/2 [Bouwfase], Scania VSB met stenentrailer, Scania Torpedo Bergingswagen ►De Asfalt Rockers Liever 8 plofjes, dan 6 die er klappen Laatst gewijzigd door Cheeta; 2 mei 2009 om 17:54 |
| | |
| ||||||
![]() |
| Discussietools | |
| Weergave | |
| |