Skapa PWM signal med timers och interrupt

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
martin5403
Inlägg: 9
Blev medlem: 14 april 2007, 13:46:02
Ort: Växjö

Skapa PWM signal med timers och interrupt

Inlägg av martin5403 »

Hej, Jag ska bygga mig en Robotbil och har lite problem då jag är rätt ny inom detta. Består just nu av PIC16F877A, tre IR-sensorer, ett servo och en ultraljudssensor och fyra motorer som styrs genom en dubbel H-brygga. Ska senare köras med en PIC18F4550 och även ha en AM-sändare så den går att styra från LabView.

Jag har fått igång allt som det ska förutom servot. Då jag inte har någon mer PWM signal kvar för båda går åt till motorena så behöver jag skapa en. Jag har testat lite med några delayfunktioner och det fungerar bra, men då kan inget annat köras under tiden.

Så det jag vill göra nu är att skapa en PWM signal med hjälp av Timer0 och interrupt. Men har inte använt mig av detta så mycket tidigare.

Är det någon här som har något exempel på något sådant eller har gjort det tidigare.

/Martin
Senast redigerad av martin5403 22 april 2007, 23:11:07, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Är det ett standard RC-servo med 1.5 +/- 0.5 ms puls med 20 ms intervall ?
Det skapar du rellativt enkelt m.h.a en timer och lite räknare.
Exakt hur beror lite på, t.ex vilken upplösning du behöver, d.v.s
antal distinga lägen mellan 1.0 och 2.0 ms. Detta kommer bl.a att
styra om det är just timer0 (med 8 bitar) eller någon 16-bitars timer
som är lämpligast...

Varför har du redan valt just timer0 till servot ?
martin5403
Inlägg: 9
Blev medlem: 14 april 2007, 13:46:02
Ort: Växjö

Inlägg av martin5403 »

Jo, det är ett standard servo med 14-20ms periodtid. Tror pulsen är mellan 0,5 och 2,3ms ungefär.

Varför jag tänkte använda mig av timer0 är för att timer1 använder jag till ultraljudet och timer2 används till PWM signalen. Är inte så insatt i det där med timers, men förmodar att de går att använda mer än en gång eller?

/Martin
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

Vilket/vilka språk programmerar du i?
martin5403
Inlägg: 9
Blev medlem: 14 april 2007, 13:46:02
Ort: Växjö

Inlägg av martin5403 »

Jag programmerar i C.
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

Du kan få kod till AVR skriven i C om det kan hjälpa dig. Tyvärr blir det då rätt mycket att skriva om eftersom allt nästan enbart handlar om att sätta upp timern rätt.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Jo, det är ett standard servo med 14-20ms periodtid. Tror pulsen är mellan 0,5 och 2,3ms ungefär.

Om det är ett *standard* RC-servo så ska det vara 1.5 +/- 0.5 ms puls med 20 ms intervall.
Intervallet är inte speciellt kritiskt med påverkar "responsen" i servot.
martin5403
Inlägg: 9
Blev medlem: 14 april 2007, 13:46:02
Ort: Växjö

Inlägg av martin5403 »

Problemet jag har är att jag inte lyckats få igång timer0 med interrupt.
Jag sitter och försöker få några lysdioders att blinka utan resultat. Om jag har förstått det rätt så skapas det ett interrupt varje gång timern slår över till 0. Jag har inte brytt mig om att räkna ut någon tid eller så ännu.
Tacksam för hjälp:-) En annan fråga skulle det fungera lika bra att använda RTCC tänkte då den var 16bitars.

/* timer.h
#include <16F877A.h>
#device adc=8
#use delay(clock=20000000)
#fuses NOWDT,HS, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, LVP, NOCPD, NOWRT
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
*/
#include "D:\Martin\test timer\timer.h"
#byte port_d = 8
int i=1000, j=10;
byte test=-1;
void init();


#int_timer0
void timer0interrupt(){ // #int_timer associates the following function with the
// interrupt service routine that should be called

if(i==0){
test=^test;
port_d=test; */ // Bitvis XOR(invers i detta fall)
i=1000;

}
else i--;

}
void main(){
init();
delay_ms(1000);
set_timer0(0);
while(1);
}
void init(){

setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_3);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
set_tris_d(0x00);
port_d=0x00;
}
Senast redigerad av martin5403 23 april 2007, 20:27:44, redigerad totalt 1 gång.
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

Du får nog räkna efter lite på hur fort timern snurrar runt. Om den gör det fortare än ~60 Hz så kommer du ju aldrig se att lysdioden blinkar (med 30 Hz).
martin5403
Inlägg: 9
Blev medlem: 14 april 2007, 13:46:02
Ort: Växjö

Inlägg av martin5403 »

Jag har försökt med detta också utan framgång, har även lagt in massa räknare för att fördröja tiden yttligare. men det vill ändå inte. Jag har fått igång timer1 och 2 men på dem så använder jag inte overflow funktionen för att skapa interrupt. Tror att det är där någon stanns det går fel.


/Martin
bearing
Inlägg: 11677
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Inlägg av bearing »

Det är svårt för oss som inte kan din kompilator att felsöka när det är sån där "hög nivå-C". Det jag menar är att man inte ser vilka register som påverkas av alla "setupfunktioner".

Att få igång interrupt på timer0 görs iaf såhär enkelt:
INTCON.T0IE=1;
INTCON.GIE=1;

Kolla om PORTD funkar som utgång.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Dessutom är det komplett omöjligt att säga något när man bara har
en massa löst prat att gå på...

Det behövs riktig kod att titta på!

Och självklart inte C kod, skriv att test-case i assembler så att du
vet vad du håller på med. Sedan, när grunderna fungerar, kan du
överföra det till din C-kod...
Skriv svar