Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
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
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
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..
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
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)
Daan Timmer
Ik ben programmeur! geen electronicus! http://www.daantimmer.nl/ Er is een ontwerp! nu nog inhoud :-)
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 
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
Daan Timmer
Ik ben programmeur! geen electronicus! http://www.daantimmer.nl/ Er is een ontwerp! nu nog inhoud :-)
Anoniem
Gebruik digitale servo's. Meer mogelijkheden, via UART aansturen, terugkoppeling v/d status, instellen van max torque, enz. Wat wil je nog meer 
Zoek op Dynamixel (AX12).
[Bericht gewijzigd door Anoniem op (17%)]
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
@ 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
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
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
henri62
1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.
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....
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
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?
Daan Timmer
Ik ben programmeur! geen electronicus! http://www.daantimmer.nl/ Er is een ontwerp! nu nog inhoud :-)
Zie dit topic:
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
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?
Arjan Swets
cnc filmpjes op Http://www.arjan-swets.com
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?
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
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.