Styra ett RC-servo.
Re: Styra ett RC-servo.
Sannolikt får man helt enkelt "köra" en timer genom att hantera de rellevanta
registren direkt från Basic koden. D.v.s att det är i princip samma hantering
som från vilket annan språk som helst, inkl assembler. Om man inte har tur
och hittar något inbyggt i Basic'en som råkar passa behoven precis.
Sen så går det inte att skriva eller visa någon kod utan att veta vilka
begränsningar du vill ha. Vilken är den minsta resp den längsta
mätbara tiden ? Vilken upplösning ska tiden mätas i ? Detta styr
till stor del hur man sedan sätter upp det hela.
registren direkt från Basic koden. D.v.s att det är i princip samma hantering
som från vilket annan språk som helst, inkl assembler. Om man inte har tur
och hittar något inbyggt i Basic'en som råkar passa behoven precis.
Sen så går det inte att skriva eller visa någon kod utan att veta vilka
begränsningar du vill ha. Vilken är den minsta resp den längsta
mätbara tiden ? Vilken upplösning ska tiden mätas i ? Detta styr
till stor del hur man sedan sätter upp det hela.
Re: Styra ett RC-servo.
Nope, dom inbyggda kan man glömma. Det jag är ute efter är egentligen från en annan tråd här. En snubbe ville ta tiderna på deras RC-dragsters. Dom kör 2 och 2 och det sitter en fotocell i början av banan och en i slutet. För enkelhetens skull så testar jag med en tryckknapp för att starta tidtagningen och en för att stoppa den. Jag är bara intresserad av mellantiden mellan tryckningarna, och vill ha det i hundradelar.
Det mesta runt omkring kan jag nog fixa själv, men just start timer / stopp timer och få ut tiden däremellan vore bra att få lite hjälp med. Har försökt leta på nätet men inte hittat nåt jag förstår nåt av, än så länge iaf.
Troligen är det lätt som en plätt, men kan man det inte, så går det inget bra. Tacksam för all hjälp jag kan få.
Ja just det. Upp till en minut totaltid kan vara bra att ta till med.
Det mesta runt omkring kan jag nog fixa själv, men just start timer / stopp timer och få ut tiden däremellan vore bra att få lite hjälp med. Har försökt leta på nätet men inte hittat nåt jag förstår nåt av, än så länge iaf.

Troligen är det lätt som en plätt, men kan man det inte, så går det inget bra. Tacksam för all hjälp jag kan få.
Ja just det. Upp till en minut totaltid kan vara bra att ta till med.
Re: Styra ett RC-servo.
Om du använder PIC så läs i databladet om CCP-modulen (Capture/Compare/PWM). Det är Capture-funktionen du vill använda.
Re: Styra ett RC-servo.
OK, ett par snabba överslag...
Upp till 60 sekunder med en upplösning på 1/100 del ger att vi behöver
som mest räkna till ca 60.000. Alltså ska en 16-bitars räknare "räcka".
Sen får man se lite hur man fixar tidbasen på 1/100 sek. Det beror lite
på vilket hastighet man kör själva processorn i, vilket ju också i och för
sig är valbart via olika kristaller eller andra inställningar i processorn. Man
kan kanske ha en snabbare tidbas och sedan räknar men ett antal "tic" för
varje steg på räknaren. Man får kolla hur de olika timers kan ställas in och
räkna lite fram och tillbaka. Kanske man ska lägga själva mellantidsräknaren
utanför timers (via vanliga register och lite kod) och sedan bara låta en av de
inbyggda timers sköta tidbasen.
Avbrottshantering (interrupt) är sannolikt något som också kan underlätta här.
Det är svårt att säga exakt hur man ska göra utan att ta det aktuella databladet
och sätta sig ner med papper och penna och skissa på det hela. Det finns en "capture"
enhat som kanske kan användas, grejen är att få timern att gå med en hstighet som
passar det aktuella fallet. Eller så kan man räkna om det värde som man får från
timern i efterhand, det går ju ganska lätt i Basic koden. Problemet är att du redan
i princip vill ha 16-bitars upplösning på hela mätningen, och för att en omräkning
inte ska medföra extra fel så vill man sannolikt att capture enheten jobbar lite
snabbare än 1/100 sek, och då får man lite ytterligare problem med att räknaren
"slår runt". Det kan så klart hanteras, men...
> Troligen är det lätt som en plätt...
Nej, så långt skulle jag inte gå. Det är en del skissande och testande av olika
lösningar tills man hittar det som fungerar bäst i det aktuella fallet.
Upp till 60 sekunder med en upplösning på 1/100 del ger att vi behöver
som mest räkna till ca 60.000. Alltså ska en 16-bitars räknare "räcka".
Sen får man se lite hur man fixar tidbasen på 1/100 sek. Det beror lite
på vilket hastighet man kör själva processorn i, vilket ju också i och för
sig är valbart via olika kristaller eller andra inställningar i processorn. Man
kan kanske ha en snabbare tidbas och sedan räknar men ett antal "tic" för
varje steg på räknaren. Man får kolla hur de olika timers kan ställas in och
räkna lite fram och tillbaka. Kanske man ska lägga själva mellantidsräknaren
utanför timers (via vanliga register och lite kod) och sedan bara låta en av de
inbyggda timers sköta tidbasen.
Avbrottshantering (interrupt) är sannolikt något som också kan underlätta här.
Det är svårt att säga exakt hur man ska göra utan att ta det aktuella databladet
och sätta sig ner med papper och penna och skissa på det hela. Det finns en "capture"
enhat som kanske kan användas, grejen är att få timern att gå med en hstighet som
passar det aktuella fallet. Eller så kan man räkna om det värde som man får från
timern i efterhand, det går ju ganska lätt i Basic koden. Problemet är att du redan
i princip vill ha 16-bitars upplösning på hela mätningen, och för att en omräkning
inte ska medföra extra fel så vill man sannolikt att capture enheten jobbar lite
snabbare än 1/100 sek, och då får man lite ytterligare problem med att räknaren
"slår runt". Det kan så klart hanteras, men...

> Troligen är det lätt som en plätt...
Nej, så långt skulle jag inte gå. Det är en del skissande och testande av olika
lösningar tills man hittar det som fungerar bäst i det aktuella fallet.
Re: Styra ett RC-servo.
Det jag tänkte mig var att om någon visste hur man startade timern och sen stoppade den, pluss hur man kan se dom två värdena, så kanske jag kan klara mig en stund.
För massa år sen gjorde jag nåt liknande i TurboBasic. Då fanns det en sak som hette mtimer eller nåt liknande. Man kunde läsa av vad PC-klockan var för tillfället. Var väl i microsekunder. Sen tog man bara förstatiden minus andratiden och man fick hur långt det gått mellan dessa två tider. Kanske det går att göra på nåt liknande sätt, hmm...
För massa år sen gjorde jag nåt liknande i TurboBasic. Då fanns det en sak som hette mtimer eller nåt liknande. Man kunde läsa av vad PC-klockan var för tillfället. Var väl i microsekunder. Sen tog man bara förstatiden minus andratiden och man fick hur långt det gått mellan dessa två tider. Kanske det går att göra på nåt liknande sätt, hmm...
Re: Styra ett RC-servo.
Närmaste jag har kommit är nedanstående, men eftersom det är skrivet till PIC, så blir det massa fel som jag just nu inte har en aning om vad det ska vara till AVR. Som LATB = Not(LATB) t ex. Jag klistrar iaf in koden.
Det var väl inte helt som jag tänkt mig, men det funkar väl lika bra att starta en räknare med första tryckknappen, sen läsa av vad räknaren kommit upp i med den andra. Troligtvis var du (sodjan) inne på samma sak.
Det var det här den stannade på
Det var väl inte helt som jag tänkt mig, men det funkar väl lika bra att starta en räknare med första tryckknappen, sen läsa av vad räknaren kommit upp i med den andra. Troligtvis var du (sodjan) inne på samma sak.
Kod: Markera allt
program Extended_Timer
' ************************************************************************************
' *********** EXTENDED EVENT TIMER USING 18F4550 @ 48MHz and TIMER0 *************
' *********** ReWritten with mikroBASIC 5.0.2 by XOR November 23, 2006 *************
' *********** Tested Using EasyPIC4 and 16x2 LCD *************
' ************************************************************************************
'
' The object of this program is to create an event with accurate 100ms (0.01 second)
' resolution timing. In the example below we will invert PORTB every 19.8 seconds.
'
' To create 100ms divisions we will use a PIC timer that can provide a count to at
' least 100ms with a 48MHz oscillator. If we create an interrupt every 100ms we can
' use a second counter to accumulate the total time and further create an event when
' we've reached the desired total time. The code below will use this method and
' create extended timing events with the smallest timing errors possible.
'
' PIC Timers increment...that is, they count up to their maximum value and then
' rollover to 0. At this point the Timer sets an overflow flag which can be simply
' read for status or enabled in a way to create a program interrupt. We will
' implement the interrupt feature for our extended timer.
'
' We will choose Timer0 which can be set up as a 16-bit counter. It increments to a
' maximum of 65,535 counts before starting over at 0. Timer0 gives us the most
' timing flexibility due to it's broad range of prescaler settings, which can be set
' from 2 to 256 in steps of powers of 2. That means Timer0 can be set to increment/
' advance a single count every 256 machine cycles if we choose.
'
' So how do we get to 100ms interrupt cycles? The internal clock of a 48MHz PIC is
' actually 12MHz, or one machine cycle every 83ns, or 12 machine cycles is exactly 1us.
' Therefore, to get a 100ms timing cycle we must set up Timer0 to rollover every
' 1,200,000 machine cycles. Just using the 16-bit Timer0 count we can only achieve a
' maximum count of 65,636 machine cycles. So, we must use the prescaler. We need a
' prescaler value of at least 32, which will extend Timer0 to a possible full count
' 32 x 65,536 = 2,097,152 machine cycles.
'
' But...we want exactly 1,200,000 machine cycles (100ms) for accuracy. Now that we
' have a prescaler value, and know the timer will increment every 32 machine cycles,
' we can simply divide to find our counter setting: 1200000/32 = 37,500 exactly! So,
' set Timer0 to 37,500? No! Timer0 increments up to rollover, or 0. We need 37,500
' counts less than 0, or 0 - 37,500 = -37,500. You can use this negative number since
' the compiler translates it in 16-bit terms and will create the correct hex value.
'
' We are not done. We need to make some adjustments for the jump to the interrupt
' Service Routine (ISR). There is additional time that elapses from the moment the
' timer interrupt is triggered and when we can reload our timer to start counting
' for the next 100ms. When the Timer0 rollover interrupt occurs 2 machine cycles
' are necessary for the jump to the ISR, 11 cycles for saving important registers,
' and 4 cycles for reloading Timer0. These 17 machine cycles of overcount will
' result in a cumulative error of 1.4us every 100ms if not compensated for in some
' way. A way to compensate is by reducing the Timer0 count by 1, or -32 machine cycles,
' but that now leaves an undercount error of 15 machine cycles (32 - 17). Undercount
' is easier to compensate for than overcount. So we will reduce the timer count by 1
' (-37,499) and make up 15 machine cycles by adding a 1us delay (12 machine cycles) and
' also adding 3 NOP's (NOP = 1 machine cycle).
'
' "Tally" is the Word variable used to accumulate 100ms counts. This 16-bit variable
' helps create an extended timing range of 0.1 to 6,553.5 seconds (1.8 hours). A user
' can make Tally a Long Integer variable and extend 1.8 hours by a multiple of 32767,
' or 59,650.5 hours, or approximately 6.8 years. That should be enough for most users.
'
' The following program uses the LCD to help visualize the Timer changes in 0.1 second
' increments. It does not need to be implemented in an actual application.
'
' ***************************************************************************************
' ***************************************************************************************
dim Tally_Str as string[5] absolute $20
dim Tally_Dec_Str as string[6] absolute $20
dim Tally, Old_Tally as Word
sub procedure DoEvent
LATB = Not(LATB)
end sub
sub procedure Interrupt
delay_us(1) ' Jump to ISR timing compensation
NOP
NOP
NOP
TMR0H = Hi(-37499) ' load TIMER0 for 100ms cycle
TMR0L = -37499 ' with 1 count compensation for jump to ISR
If inc(Tally) = 198 Then ' if 19.8 seconds have passed
DoEvent ' do event
Tally = 0 ' reset Tally
End If
INTCON.TMR0IF = 0 ' clear Timer0 Interrupt Flag
end sub
sub procedure Init
TRISB = 0 ' PortB is used to demonstrate event
LATB = 15
ADCON1 = 15 ' all IO is digital
LCD_INIT(PORTD) ' LCD on PortD
LCD_CMD(LCD_CURSOR_OFF)
Tally = 0 ' initialize 0.1 second accumulator
Old_Tally = 0
end sub
sub procedure Timer0_Init
T0CON = %00000100 ' Timer0 prescaler = 32; Timer0 is OFF
INTCON = %10100000 ' GIE and TMR0IE enabled; TMR0IF is cleared
TMR0H = Hi(-37499) ' load TIMER0 for 100ms cycle
TMR0L = -37499 ' with 1 count compensation for jump to ISR
T0CON.TMR0ON = 1 ' start Timer0
end sub
main:
Init
Timer0_Init
While 1=1
If Tally xor Old_Tally <> 0 Then ' display the new value on the LCD
WordToStr(Tally, Tally_Str)
Tally_Dec_Str[5] = Tally_Dec_Str[4]
Tally_Dec_Str[4] = 46 ' add a decimal
LCD_OUT(1, 6, Tally_Dec_Str)
LCD_OUT(2, 7, "SECONDS")
End If
Wend
end.
Kod: Markera allt
LATB = Not(LATB)
TMR0H = Hi(-37499) ' load TIMER0 for 100ms cycle
TMR0L = -37499 ' with 1 count compensation for jump to ISR
INTCON.TMR0IF = 0 ' clear Timer0 Interrupt Flag
TRISB = 0 ' PortB is used to demonstrate event
LATB = 15
ADCON1 = 15 ' all IO is digital
LCD_INIT(PORTD) ' LCD on PortD
LCD_CMD(LCD_CURSOR_OFF)
T0CON = %00000100 ' Timer0 prescaler = 32; Timer0 is OFF
INTCON = %10100000 ' GIE and TMR0IE enabled; TMR0IF is cleared
TMR0H = Hi(-37499) ' load TIMER0 for 100ms cycle
TMR0L = -37499 ' with 1 count compensation for jump to ISR
T0CON.TMR0ON = 1 ' start Timer0
Re: Styra ett RC-servo.
Den här tutorialen verkar också intressant, men jag kan inte C, än så länge iaf, men man kan kanske låna lite därifrån.
http://www.avrfreaks.net/index.php?name ... ic&t=50106

http://www.avrfreaks.net/index.php?name ... ic&t=50106
Re: Styra ett RC-servo.
Eftersom du ju kan hantera alla register direkt från Basic koden precis
hur du vill så kan du ju hantera det ditrekt efter databladet. Du behöver
inga inbyggda funktioner. D.v.s skriva och läsa direkt i de rellevanta
registren (TMR0xx, TMR1xx o.s.v vad de nu heter).
hur du vill så kan du ju hantera det ditrekt efter databladet. Du behöver
inga inbyggda funktioner. D.v.s skriva och läsa direkt i de rellevanta
registren (TMR0xx, TMR1xx o.s.v vad de nu heter).