Je moet zoals gezegd in rust blijven aansturen (middenstand of wat anders)
Special Member
Je moet zoals gezegd in rust blijven aansturen (middenstand of wat anders)
Golden Member
Dus dacht ik in mijn onschuld, dan doe ik het zo:
De interrupt komt iedere 20 ms (is dus 50Hz)
In de main laat ik dan de delay oplopen van 1 naar 2 ms in stappen van 10us. Zo lang blijft Portb.3 dan hoog.
Een puls dus van 1 ms tot 2 ms.
Het effect is dat de servo nu (schokkerig) 360 graden ronddraait...
pic basic code:
Program PWM_Test
Dim Direction as byte
i1 as word
z1 as word
Sub Procedure Wait(Dim pDelay as Word)
For z1 = 0 to pDelay
Delay_us(1)
Next z1
End sub
'-------------------------------------------------------------------------------
Sub procedure Interrupt() iv 0x0004 ics ICS_AUTO
'-------------------------------------------------------------------------------
If TMR2IF_bit Then 'See if timer2 irq
PORTB.3 = 1
PORTB.7 = 1
TMR2IF_bit = 0
End If
End sub
Main:
OSCCON = %01000000 '1 Mhz internal
T2CON = %00100101 'Post:5 - Pre:16
PR2 = 249 'Timer load value
GIE_bit = 1 'Enable timer2 irq
PEIE_bit = 1
TMR2IE_bit = 1
ANSEL = 0
ANSELH = 0
TRISA = %11111111
TRISB = %00000000
PORTA = %00000000
PORTB = %00000000
PORTB.7 = 1 'Measure Frequency
PORTB.6 = 1 'Test LED On
Delay_ms(2000) 'Wait befors start
PORTB.6 = 0 'Test LED Off
Direction = 1 'Default Mid Position
While True
For i1 = 1000 to 2000 step 10
Wait(i1)
PORTB.3 = 0
Next i1
For i1 = 2000 to 1000 step -10
Wait(i1)
PORTB.3 = 0
Next i1
Wend
end.
Op 25 juli 2020 22:04:34 schreef Bavelt:
Het effect is dat de servo nu (schokkerig) 360 graden ronddraait...
Lijkt me sterk. De meeste servo's komen niet verder dan iets meer dan 180 graden.
Golden Member
Lijkt me sterk. De meeste servo's komen niet verder dan iets meer dan 180 graden
Vond ik ook. maar deze draait echt vrolijk helemaal rond...
Ik had verwacht dat hij heen en weer zou gaan, maar het programma doet niet wat ik wil...
Special Member
Wat voor pic gebruik je? (aan de anselh en lage klok te zien een oud beestje?)
Dat 'ie 360 graden ronddraait is inderdaad onmogelijk (het kan mechanisch niet als het een SG-90 is)
De laatst geplaatste code doet volgens mij niets zinvols. Kan goed dat er 'random' dingen gebeuren...
[Bericht gewijzigd door Arco op zaterdag 25 juli 2020 23:35:01 (23%)
Golden Member
Een PIC16F887.
Ik weet niet of ik een filmpje als attachment kan meesturen bij een beriht?
Special Member
Een MP4 o.i.d. (mits bescheiden van formaat) moet je kunnen plaatsen.
Ik zal eens kijken of ik wat kan maken (ik doe nooit wat met servo's, maar het is vrij eenvoudig)
Golden Member
Golden Member
Golden Member
Kort filmpje, ik moet onder de 4MB blijven...
Je kunt er wel aan zien dat hij schokkerig draait met mijn programma.
[Bericht gewijzigd door Bavelt op zaterdag 25 juli 2020 23:56:37 (44%)
Special Member
Op 25 juli 2020 23:05:30 schreef Bavelt:
Vond ik ook. maar deze draait echt vrolijk helemaal rond...
Deze servo kan max maar 180 graden draaien, die is dus stuk als hij helemaal rond gaat.
Ding komt bij Alie vandaan zeker of zat hij bij zo'n doos voor de arduino?
Heb je mijn artikel nog doorgelezen, daar staat alles zo'n beetje in wat je moet weten.
Golden Member
Nee, dit keer geen 'tante Alie', maar de reguliere electronicahandel.
Tegen een normale prijs.
Het ding zat nieuw in de verpakking.
Ik had al wel gelezen (in o.a. het artikel van Lambiek) dat je zelf de (mechanische) blokkade er uit kan halen waardoor hij 360 Gr kan draaien.
Maar dat heb ik niet gedaan. Ik wilde gewoon eens 'spelen' met zo'n ding.
Links-midden-rechts en terug. Met de Arduino sketch werkt dat ook prima en traploos.
Het artikel van Lambik heb ik doorgenomen. Erg uitgebreid en verhelderend hoe het werkt.
Alleen zit er nog even een muurtje tussen theorie en praktijk.
(zoals vertaling van Picbasic maar MikroBasic voorbeelden).
Ik dacht zelf alles goed te hebben gedaan, frequentie 50 Hz, pulsduur 1 tot 2 ms.
Ik zie overigens wel dat de voeding een 'dipje' krijgt als de motor wordt ingeschakeld. (de voedingsled knippert dan even).
En omdat de microcontroller daar ook aan hangt, zou het wellicht aanbevelenswaardig zijn deze voedingen te scheiden (?).
Special Member
Zoals gezegd, de laatst geposte code kan niet werken (althans doet niks voorspelbaars... )
Er is geen synchronisatie tussen de timerinterrupt en de routine in main() : die hobbelen onafhankelijk van elkaar op verschillende snelheden...
Daardoor komen de pulsen op willekeurige momenten in de interruptcyclus.
Special Member
Op 26 juli 2020 12:04:56 schreef Bavelt:
Het ding zat nieuw in de verpakking.
Kan een foutje zijn. Je kunt eens kijken of de mechanische stop soms afgebroken is.
Ik zie overigens wel dat de voeding een 'dipje' krijgt als de motor wordt ingeschakeld. (de voedingsled knippert dan even).
En omdat de microcontroller daar ook aan hangt, zou het wellicht aanbevelenswaardig zijn deze voedingen te scheiden (?).
Voor zo'n kleine servo zou het moeten kunnen, ik doe het vaak op de zelfde voeding.
Als het echter een grotere servo is of de servo wordt zwaar belast, dan is een externe voeding aan te raden.
Maar voor nu denk ik dat het voornamelijk aan de software ligt.
Golden Member
Op 26 juli 2020 11:40:25 schreef Lambiek:
[...]
Deze servo kan max maar 180 graden draaien, die is dus stuk als hij helemaal rond gaat.
Dit is een Continuous Rotation Servo, volgens de site. Dus hij kan inderdaad ronddraaien.
https://www.hobbyelectronica.nl/product/sg90-digital-servo-360-graden/
Heeft MikroBasic geen eigen servo commando? PicBasic heeft deze wel.
Special Member
Op 26 juli 2020 15:04:40 schreef marcob:
Dit is een Continuous Rotation Servo, volgens de site. Dus hij kan inderdaad ronddraaien.
Dat is vreemd, ik kom deze tegen.
Zal er waarschijnlijk aan liggen of het een digitale is of niet.
Heeft MikroBasic geen eigen servo commando? PicBasic heeft deze wel.
Zover ik weet heeft micro basic dat commando niet. Anders had Arco dat wel gezegd.
Special Member
Misschien zijn er wel libraries voor, even op Libstock kijken...
Golden Member
Ik ben al weer een stuk verder.
Arco had gelijk dat er geen synchronisatie zat tussen de timer interrupt en de main:
Dat heb ik aangepast: in de main wordt gekeken of er een interrupt was (via een vlaggetje) zodat de statements onderling relaties hebben.
pic basic code:
Program PWM_Test
Dim Direction as byte
i1 as word
z1 as word
Ind as byte
Sub Procedure Wait(Dim pDelay as Word)
For z1 = 0 to pDelay
Delay_us(1)
Next z1
End sub
'-------------------------------------------------------------------------------
Sub procedure Interrupt() iv 0x0004 ics ICS_AUTO
'-------------------------------------------------------------------------------
If TMR2IF_bit Then 'See if timer2 irq
PORTB.3 = 1
Ind = 1
TMR2IF_bit = 0
End If
End sub
Main:
OSCCON = %01000000 '1 Mhz internal
T2CON = %00100101 'Post:5 - Pre:16
PR2 = 249 'Timer load value
GIE_bit = 1 'Enable timer2 irq
PEIE_bit = 1
TMR2IE_bit = 1
ANSEL = 0
ANSELH = 0
TRISA = %11111111
TRISB = %00000000
PORTA = %00000000
PORTB = %00000000
Direction = 1 'Default Mid Position
Ind = 0
While True
If Ind = 1 then
if z1 < 20 then
Delay_us(1500)
'Wait(1500)
else
if (z1 > 19) and (z1 < 30) then
Delay_ms(1)
else
if z1 > 39 then
Delay_ms(2)
end if
end if
end if
PORTB.3 = 0
Ind = 0
z1 = z1 + 1
if z1 > 40 then
z1 = 0
End if
End if
Wend
end.
Ik kan de servo nu heen en weer laten bewegen, zij het dat 1ms-1,5ms-2ms pulsduur niet gelijk is aan 0-90-180gr beweging.
De sprong van 1 naar 1,5 doet beduidend minder dan van 1,5-2 ms.
Dit kon ook wel eens te maken met het volgende: omdat ik de delay met een parameter wilde aansturen (de MikroBasic procedure Delay wil een literal en geen variabele) had ik de volgende procedure geschreven:
pic basic code:
Sub Procedure Wait(Dim pDelay as Word)
For z1 = 0 to pDelay
Delay_us(1)
Next z1
End sub
Maar: Delay_us(1500) en Wait(1500) geven een ander resultaat. Ik vermoed omdat de klokfrequentie op 1Mhz staat, de tijd die nodig is voor het uitvoeren van een instructie te groot wordt, waardoor mijn procedure niet werkt..
[Bericht gewijzigd door Bavelt op zondag 26 juli 2020 21:20:48 (43%)
Special Member
Delays zijn bij gebruik van interrupts al vrij onnauwkeurig (bij een heel veel aangeroepen interrupt kan de afwijking zelfs +50% zijn...)
De hele lage kloksnelheid is inderdaad ook niet echt bevorderlijk.
Een aparte subroutine voor de delay maakt 't nog onnauwkeuriger: iedere aanroep kost minstens 8 extra instructiecycles...
Delay_ms en Delay_us verwachten een constante inderdaad, omdat de compiler inline code genereert voor nauwkeurigheid.
(er is ook VDelay_ms waar je wel een variabele op kunt geven, maar dat is onnauwkeuriger)
[Bericht gewijzigd door Arco op zondag 26 juli 2020 22:10:19 (24%)
Golden Member
Dus de interrupt is voor deze toepassing eigenlijk niet zo geschikt (mede vanwege de lage frequentie van 50Hz. Daarom koos ik ook voor een lage klokfrequentie).
Wat zou dan een betere oplossing zijn voor deze toepassing?
Special Member
Je kunt toch gewoon een plus maken met een paar delays. Even met de scoop controleren of met een logic analyser.
Special Member
Hier heb je een voorbeeld, hoe simpel kan het zijn.
pic basic code:
Device 16F887 ; Processor type
Xtal 10 ; Cristal 10Mhz
Asm ; Config settings HS_OSC
CONFIG_REQ
__CONFIG _CONFIG1, HS_OSC & WDT_OFF & DEBUG_OFF & FCMEN_OFF & LVP_OFF & IESO_OFF & BOR_OFF & CPD_OFF & CP_OFF & MCLRE_OFF & PWRTE_ON
__CONFIG _CONFIG2, WRT_OFF & BOR40V
EndAsm
All_Digital true ; Alle poorten digitaal
Declare Adin_Res = 8 ; resolutie 8 bits
Declare Adin_Tad = frc ; set RC osc
Declare Adin_Stime = 50 ; sample tijd 5
Declare LCD_RSPin PORTD.2 ; Reset display poort D.2
Declare LCD_ENPin PORTD.3 ; Enable display poort D.3
Declare LCD_DTPin PORTD.4 ; Data display poort D.4 t/m D.7
Symbol SERVO_PULS = PORTE.0
Symbol S1 = PORTA.0
Symbol S2 = PORTA.1
Cls ; Wis display
DelayMS 500 ; Pauze 0.5 sec
Clear ; Wis geheugen
;------------------------------------------------------
; ALS TRISA - TRISB - TRISC - TRISD OF TRISE IS 0, DAN
; STAAT DE POORT ALS EEN UITGANG.
; ALS TRISA - TRISB - TRISC - TRISD OF TRISE IS 1, DAN
; STAAT DE POORT ALS EEN INGANG.
;------------------------------------------------------
;543210 ; Hulpregel poort A
PORTA = %000000 ; Maak poort A laag
TRISA = %111111 ; Poort_A I/O
;543210 ; Hulpregel poort B
PORTB = %000000 ; Maak poort B laag
TRISB = %000001 ; Poort_B I/O
;76543210 ; Hulpregel poort C
PORTC = %00000000 ; Maak poort C laag
TRISC = %00000011 ; Poort_C I/O
;76543210 ; Hulpregel poort D
PORTD = %00000000 ; Maak poort D laag
TRISD = %00000000 ; Poort_D I/O
;210 ; Hulpregel poort E
PORTE = %000 ; Maak poort E laag
TRISE = %000 ; Poort_E I/O
;76543210 ; Hulpregel analoog
ADCON0 = %00000001 ; ADCON0 register 8 bit analoog
;76543210 ; Hulpregel analoog
;ADCON1 = %10000000 ; ADCON1 register 10 bit analoog
;543210 ; Hulpregel analoog poort_B
;ANSELH = %000000 ; ANSEL register analoog poort_B
;-------------------------
; HIER KOMT HET PROGRAMMA
;-------------------------
RUN:
SERVO_PULS = 1
DelayUS 1650
SERVO_PULS = 0
DelayMS 20
If S1 = 1 Then
GoTo POS_1
EndIf
If S2 = 1 Then
GoTo POS_2
EndIf
GoTo RUN
POS_1:
SERVO_PULS = 1
DelayUS 2500
SERVO_PULS = 0
DelayMS 20
If S1 = 0 Then
GoTo RUN
EndIf
GoTo POS_1
POS_2:
SERVO_PULS = 1
DelayUS 850
SERVO_PULS = 0
DelayMS 20
If S2 = 0 Then
GoTo RUN
EndIf
GoTo POS_2
End
Golden Member
Op 26 juli 2020 22:51:42 schreef Lambiek:
Je kunt toch gewoon een plus maken met een paar delays. Even met de scoop controleren of met analyser.
OK, terug naar de basis:
Met een heel simpel programma, met een fatsoelijke klokfrequentie (8Mhz) en een paar delays, werkt het ook:
pic basic code:
Program PWM_Test
Dim z1 as word
Main:
OSCCON = %01110000 '8 Mhz internal
ANSELH = 0
TRISB = %00000000
PORTB = %00000000
portb.6 = 1
Delay_ms(2000)
While True
Portb.6 = 0 'Test Led
if z1 < 101 then
PORTB.3 = 1
Delay_ms(1)
PORTB.3 = 0
Delay_ms(1)
else
PORTB.3 = 1
Delay_ms(3)
PORTB.3 = 0
Delay_ms(2)
end if
z1 = z1 + 1
if z1 > 200 then
z1 = 0
end if
Delay_ms(19)
Wend
end.
Golden Member
Ah, berichten hebben elkaar gekruist..
Golden Member
Hier heb je een voorbeeld, hoe simpel kan het zijn.
Beide programmaatjes doen ongeveer hetzelfde. Ik laat de servo 180 gaden draaien, het voorbeeld van Lambiek werkt met schakelaartjes.
Principe is idd hetzelfe: als je zorgt dat je pulsen aanbiedt met een frequentie van 50 Hz (20ms delay) en de pulsduur ook aanpast via een delay, dan ben je er al.
[Bericht gewijzigd door Bavelt op maandag 27 juli 2020 11:40:53 (24%)