Heeft er misschien iemand schema/programma om zo veel mogelijk RC servo's te besturen met 1 pic microcontroller....

Of links naar pagina's

alvast bedankt...

Neem een 40pins PIC, moet je toch minstens 32 servo's aan kunnen sturen. Als je een paar pins opoffert voor communicatie kan het zelfs dynamisch...

Maar misschien is het handig als je verteld wat je wilt bereiken?

Als je gebruik maakt van PPM en een schuifregister kan je redelijk makkelijk grotere aantallen servo's sturen.
Met twee 595 en een 12f675 heb ik een tijdje terug 16 servo-kanalen getest; en heb atm een 595 aan een 18f4520 hangen om pinnen uit te sparen.

Dit systeem wordt veel in de RC wereld toegepast; zie hier voor meer info, punt 4.3 dan vooral

wat ik wil bereiken....

staat er toch... zoveel mogelijk servo's besturen via 1 PIC..

nou eigelijk hierom.... als ik internet afzoek vind ik eigenlijk allemaal voorbeelden niet groter als 8 servo....

terwijl ik op commerciele pagina's wel controllers ziet van bijvoor 32 servo's

dus ik vroeg me af of er mensen zijn met voorbeelden van bijvoorbeeld 16 met 1 pic..

Hangt ook af van de gewenste nauwkeurigheid. (aantal PWM stappen)

Uhm.. heb je mn reply wel gelezen?

Je wekt met de µcontroller een PPM signaal op, bijv. dmv een timermodule, en die laat je dan door een schuifregister "decoderen" naar PWM. Gebruik je een 16-bit timer, heb je 16-bit nauwkeurigheid.

Theoretisch gezien kan je hiermee (20ms/2ms)= 10 servo's aansturen, maar ik ken niet zo onmiddelijk 10-bits schuifregisters, dus ik stel 8 servo's per timer.
Een pic met 3 timers kan dus betrekkelijk makkelijk 24 servo's aansturen.

In pseudocode:


Interrupt:
 if(flag ==1)
   Output = Low
   Timer = Servo[x]
   X ++
   flag = 0
   Exit interrupt
 else
   Output = High
   Timer = 1ms
   flag = 1

Je moet wel nog x resetten na het aantal servo's die je aanstuurt om je pointer niet buiten range te halen, en een extra tijd instellen na het aflopen van je servo's om de 20ms te halen (20ms - (1ms x n + Som vd servowaardes)

Zie dit topic:

http://www.circuitsonline.net/forum/view/message/1165077#1165077

Hier stuur ik er nu 8 aan, maar er is nog zat ruimte om er 16 of misschien zelfs 32 van te kunnen maken :-)

(Hangt klein beetje van je nauwkeurigheid af natuurlijk :-))

Ik zou er dan wel voor kiezen om een main routine te laten loopen totdat de timer0 IF geset is en dan pas rekenwerk te doen en dan ook zelf die IF flag weer uit te zetten.

Denk dat dat wat netter is dan het ook via een echte inerrupt te doen in dit geval :-)

oke... ik ga het allemaal eens door lezen.... kijken of ik het snap...

bedankt!!

hoeveel servo's zo lukken in Picbasic?

Zoals gezegd, hangt af van nauwkeurigheid. Met 4 bits PWM doe je veel meer als met 10 bits PWM...

hmmm 8 stuks in pic basic.... met een een resolutie van 10 bits...

moet toch wel lukken...

10bits???

Ik betwijfel het, maar je kan het proberen.

Gebruik digitale servo's. Meer mogelijkheden, via UART aansturen, terugkoppeling v/d status, instellen van max torque, enz. Wat wil je nog meer :P

Zoek op Dynamixel (AX12).

[Bericht gewijzigd door Anoniem op (17%)]

@ m14: die vind ik een beetje duur....

hmmm... zit er even mee hoe ik nu eigenlijk beginnen moet....

kan iemand misschien een tip geven....

iets van 2 tellers.... eentje voor om de 20ms een puls te geven...

en ik denk iets op een timer interrupt voor de lengte van de pulzen?

help

Ik ben begonen voor 8 servo's
flink internet af gezocht.... dit heb ik nu, maar het doet nog niet veel...

oja het grootste deel is afgekeken van dit:
http://www.mikroe.com/forum/viewtopic.php?t=7287
(hier snap ik trouwens ook die AND 7 niet bij die INC instruktie?)

Ik snap wel dat ik een heel andere pic heb, die veel sneller is, dus de timing zal wel niet erg kloppen, maar verlopig doet het nix...

en wat ik echt niet snap, in een simulator (oshonsoft) gaat het programma na een bepaald moment in sleep... maar dit moet toch rond blijven gaan in:


WHILE 1=1
      WHILE intflag = FALSE                       ' WAIT until Timer1 Interrupt
       NOP                                        ' place USART Read routines in here
      WEND
      WHILE intflag = TRUE                        ' WAIT until Timer0 Interrupt
       NOP                                        ' place USART Read routines in here
      WEND
   WEND

kan iemand zien waar de fout kan zitten?


DEVICE = 18F4550
    XTAL =  20
    
    CONFIG_START
    PLLDIV = 12 ; Divide by 12 (48 MHz oscillator input)
    FOSC = HSPLL_HS ; HS oscillator, PLL enabled, HS used by USB
    CONFIG_END

	  OPTIMISER_LEVEL = 2
		 
		WARNINGS = ON       
    'DECLARE STAMP_COMPATIBLE_SIN = ON

    ALL_DIGITAL TRUE              ;Alle ingangen digitaal
  


SYMBOL FALSE        = 0
SYMBOL TRUE         = 1

SYMBOL PIR1_TMR1IF=PIR1.0
SYMBOL PIE1_TMR1IE=PIE1.0
SYMBOL T1CON_TMR1ON=T1CON.0

SYMBOL INTCON_RBIF=INTCON.0
SYMBOL INTCON_INT0IF=INTCON.1
SYMBOL INTCON_TMR0IF=INTCON.2
SYMBOL INTCON_RBIE=INTCON.3
SYMBOL INTCON_INT0IE=INTCON.4
SYMBOL INTCON_TMR0IE=INTCON.5
SYMBOL INTCON_PEIE=INTCON.6
SYMBOL INTCON_GIE=INTCON.7

SYMBOL T0CON_T0PS0 = T0CON.0      ' Prescaler ratio bit-0 
SYMBOL T0CON_T0PS1 = T0CON.1      ' Prescaler ratio bit-1 
SYMBOL T0CON_T0PS2 = T0CON.2      ' Prescaler ratio bit-2  
SYMBOL T0CON_T0PSA = T0CON.3      ' Prescaler Assignment (1=assigned to WDT 0=assigned to oscillator)  
SYMBOL T0CON_TMR0ON= T0CON.7
;        76543210


PORTB = %00000000             ;Maak alle 8 bits van poortregister PORTb laag
TRISB = %00000000             ;PORTB is uitgangen voor de servomotors

CLEAR                         ;Wis alle RAM geheugen

DIM intflag AS boolean
DIM huidige_SERVO AS BYTE
DIM T1 AS WORD 
DIM T0 AS BYTE
DIM pos[8] AS WORD
   
   T1=$0E
   T0=$01
   
   T0CON = $85                 ' Timer0 prescaler = 64 = 12.8us
   'T0CON_T0PS0=1
   'T0CON_T0PS1=0
   'T0CON_T0PS2=1
   'T0CON_T0PSA=0
   'T0CON_TMR0ON=TRUE
   
   INTCON = $E4                     ' GIE, PEIE, Timer0 Enabled; Timer0 Flag Set
   'INTCON_TMR0IF=TRUE
   'INTCON_TMR0IE
   'INTCON_PEIE
   'INTCON_GIE
   
   T1CON = 0                                      ' Timer1 Off; No prescaler
   
   FOR huidige_SERVO = 0 TO 7
      pos[huidige_SERVO] = 7500                   ' set for 1500us mid-point
   NEXT huidige_SERVO
   
   ON_INTERRUPT GOTO InterruptAfhandeling
   
   
   intflag = FALSE
   huidige_SERVO = 0
   
   T1 = 0 - 4500                                  ' load Timer1
   PIR1_TMR1IF = FALSE                            ' reset Timer1 Interrupt Flag
   PIE1_TMR1IE = TRUE                             ' Timer1 Interrupt Enabled
   T1CON_TMR1ON = TRUE                            ' Timer1 On
   T0 = -196                                      ' load TMR0 for 2500us Interrupt Cycle Count
   INTCON_TMR0IE = TRUE                           ' reset Timer0 Interrupt Flag
   SETBIT PORTB, 0                                ' turn on first servo

   WHILE 1=1
      WHILE intflag = FALSE                       ' WAIT until Timer1 Interrupt
       NOP                                        ' place USART Read routines in here
      WEND
      WHILE intflag = TRUE                        ' WAIT until Timer0 Interrupt
       NOP                                        ' place USART Read routines in here
      WEND
   WEND
   
END

;--------------------------------------------------------------------------------------------------------
InterruptAfhandeling:

   IF INTCON_TMR0IF = TRUE THEN                   ' if Timer0 interrupt
      T0 = -196                                   ' load Frame 196 x 12.8us = 2508us interrupt cycle
      CLEARBIT PORTB, huidige_SERVO               ' force servo off...in case value was wrong
      huidige_SERVO = (huidige_SERVO +1)AND 7     ' next servo
      
      SETBIT PORTB, huidige_SERVO                 ' turn on next servo
      T1 = 0 - pos[huidige_SERVO]                 ' load servo position...each count is 0.2us
      T1CON_TMR1ON = TRUE                         ' turn Timer1 On
      PIR1_TMR1IF = FALSE                         ' reset Timer1 Interrupt Flag
      INTCON_TMR0IF = FALSE                       ' reset Timer0 Interrupt Flag
   ELSE                                           ' if Timer1 interrupt
      CLEARBIT PORTB, huidige_SERVO               ' turn off servo
      T1CON_TMR1ON = FALSE                        ' turn Timer1 Off
   END IF
   intflag = FALSE                                ' interrupt flag status
END sub

Die AND 7 zorgt ervoor dat je telt van 0..7 en dan wrapped de counter weer naar 0, bespaard dus een compare met 8 en weer nul stellen van 'huidige_SERVO'.

Voor 32 servo's kun je er "AND 31" van maken.

P.S. Heb de rest van de code niet bekeken wat er verder mis kan zijn dus....

:-)

jammer dat je de rest ook niet ff bekijk.... ik kan het niet vinden...

hoe kan ik het nu het beste maken... de 18f4550 heeft 3 16bits timers...

als ik er nu eentje maakt die om de 20ms een interupt geeft?
dan alle outputjes op 1...

en dan dmv een tweede timer een getal tellen... en daar dan op een bepaald moment (aan de had van de verschillende servo waarde) de uitgang laag zetten?

heb ik al 3x door gelezen.... maar dan weet ik het eigenlijk nog niet.. :-)

wilde dit ook weer op pakken....

@ Daan Timmer...: kan je het nog een keer uitleggen....

laten we zeggen voor 8 of 16 servo's... en dan 8 0f 9 bits breed...

hoe ik dat het besten kan doen?

oke 8 servo's dan? :-)

jammer dat niemand het uitwil leggen hoe ik het beste kan doen...

Ik heb nu een timer0 interupt, en die heb ik zo dat hij elke 20mS portb.6 hoog zet....

en ik heb zodra portb.6 hoog is, ga ik tellen in een woord, en als dat woord 1000 is of 2000 zet ik portb.6 weer laag...en het woord op 0.... en dit werkt al een beetje...

zo zou ik bijvoorbeeld 8 servo's op poort B kunnen zetten....

en dan op die interrupt heel poortB hoog zetten...
dan zodra portb hoog gezet is, tellen in een woord... en dan dmv 8 vergelijkingen de uitgangen 1 voor 1 terug naar 0 zetten...

maar alleen vraag ik me af of ik dat tellen van dat woord ook niet aan een timer intrrupt moet hangen?

want als ik nog meer in die hoofdlus gaat doen, dan gaat het tellen niet elke keer hetzelfde?

Het PWM-men moet je in de interrupt doen als je het een beetje betrouwbaar wilt hebben.
Een PWM puls duurt 0...1mS, dus de interruptfrequentie is 1\256 = 3.906µS bij 8 bits resolutie.
Het zou makkelijker zijn om een wat lagere resolutie te nemen. (Is 8 bits echt wel nuttig danwel nodig?)

Laat een teller lopten in je interrupt.
Bij een bepaalde waarde reset je de teller en zet je de uitgangen op '1'. Dan kun je bij de verschillende andere waarden de diverse uitgangen weer op 0 zetten. Dit doe je gewoon in de interrupt zelf.

Dan blijft je hoofdprogramma vrij voor andere zaken.

Bereken de waarden zodanig dat je een puls van 1-2ms. krijgt.
Daarvoor moet je dus je timer0 op de juiste snelheid zetten, en je maximale tellerwaarde berekenen.

Verder hoef je natuurlijk niet alle servo's tegelijk een '1' te geven, het mag ook in de dode '0' tijd van de andere servo's.
Dat geeft je nog meer rekentijd om de waarden te berekenen aangezien er 20 milliseconden aan dode tijd is. Dat is een eeuwigheid voor een microcontroller.