ATMega32 och massor med interuppt

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Virr3
Inlägg: 840
Blev medlem: 25 juli 2004, 23:05:59
Ort: Göteborg

Inlägg av Virr3 »

alltså, nee...

det funkar inte för mig, hur jag än skriver koden, vilken kod jag än tar så blir den inte rätt :(

de koder jag hittat har vart med prescalern, och den fattar jag inte ett jota av :(

och när jag själv ska skriva kommer jag halvägs och sen står de still och jag vet inte vad som ska göras sen :(

det bästa vore ifall jag kunde hitta en kod som vart enkelt skriven, alltså inte för avancerad, den ska bilda en enkel puls på 38khz

jo, förestern, jag har hittat lite bra info...
http://aoe.nerdlabs.org/ och om man scrollar ner till hälften så finns det en artikel om fjärkontroller som är ganska bra....

sen tipsade frejo mig om http://www.ustr.net/infrared/infrared1.shtml som också va trevlig att läsa, dock va kodexemplet i assambler, känns som att man måste lära sig det med snart :?

aja, vet inte riktigt vad jag ska ta mig till, projetkte står praktiskt taget helt still nu när jag inte får det att funka:( och det gör mig mer irriterad varje gång jag ser ledsnurra, att jag inte tar mig mer tid för att fatta, men likförbannat fattar jag inte...

ni har ju förklarat vilka register som ska ställas om å de, men när man kommer till det skedet att de ska skapas en puls, och hur lång den ska va, de fattar jag inte alls :(

aja, hade så gott allahopa
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg av Kaggen »

Är det inte bara att göra en delayloop? Vet inte vad Atmel har för bilblioteksfunktioner men nån typ av Delay()-funktion borde finnas.

I mitt exempel så används SetBit(PortX,0) för att sätta bit 0 på port X hög, och ClearBit(PortX,0) att sätta bit 0 på port X låg. Vet inte hur motsvarande ser ut för Atmel, men du förstår principipen. Det nedan är alltså psuedo-kod, ingenting du kan kopiera och kompilera.

Psuedonåntingkod:

Kod: Markera allt

SendPulses(antal_pulser)
{
 for(i=0; i < antal_pulser; i++)
 {
  SetBit(PortX,0);
  Delay(13); /* En period på 26 us = 38kHz, alltså 13us hög och 13us låg */
  ClearBit(PortX,0);
  Delay(13);
 }
}
Användarvisningsbild
vfr
EF Sponsor
Inlägg: 3515
Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka

Inlägg av vfr »

Virr3> Jag blir ärligt talat inte riktigt klok på vad det är du försöker göra. Innan pratade du om IR-mottagare och nu pratar du om att sända. Gör du båda ändarna på någon form av IR-länk, eller vad ?

Förklara gärna lite vad det är du vill åstadkomma om vi skall kunna hjälpa dig. Vill du inte tala om vad det skall bli eller användas till, så försök iallafall att beskriva vad just den IR-grejen skall göra.

Om det är så att du skall göra både sändande och mottagande änden på en IR-länk där ingen annan enhet är inblandad, så är du ju själv fri att välj ett lämpligt IR- protokoll. Bara det verkar kunna fungera med den mottagaren du använder vad gäller pulslängder etc.

Att skapa 38kHz för en sändardiod kan göras antingen med delayloopar eller med timerfunktioner och avbrott. Det beror lite på vad mer som den processorn behöver göra under tiden. Det enklaste är helt klart med delayloopar. Börja t.ex med att skicka ut skurar av pulser och titta på mottagaren när du får ut signal från den. Ett oscilloskåp underlättar helt klart!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Jag gjorde en enkel IR länk med en liknande mottagare för ett tag sedan. I och för sig var med en PIC i varje ände, men det bör väll inte spela någon större roll.

Bärvågen (36 Khz fyrkantssignal) genererades av PWM modulen. Bara att sätta upp "period" och "duty cycle" så går den av sig själv. PWM modulen har en bit i ett register för att stoppa/starta PWM modulen, så det var enkelt att skapa pulserna. Notera att jag inte vet hur PWM modulen fungerar i en AVR, men det borde väll vara ganska likt...

Sedan använde jag en (annan) timer för att generera de olika längderna på pulserna (och mellanrummen). Längderna var avpassade för att få en enkel avkodning i mottagaränden. Jag synkade också av/på stängningen av PWM modulen så att det alltid blev hela 36 Khz pulser för att få en så "ren" signal som möjligt.

I mottagaren startade jag en free-running timer när en puls startade, och stoppade den när pulsen var klar. Timerns klockfrekvens var anpassad så att det helt enkelt gick att kolla vissa bitar i timern för att se om det var en "start-", "stopp-", "ett-" eller en "noll-" bit som just hade kommit från IR-mottagaren.

Hoppas att det kan vara till nån hjälp...
Virr3
Inlägg: 840
Blev medlem: 25 juli 2004, 23:05:59
Ort: Göteborg

Inlägg av Virr3 »

det handlar om information som ska skickas mellan två stycken atmega32:or
det hela ska vara till en ledsnurra som det ska vara en display och ett tangentbord till..

tangentbordet och lcd:n ska vara kopplad till en µC och när allt är klart där så ska texten som man matat in på µC förflyttas till den andra µC via just ir...

jag hoppas du förstog...btw: hehe, jag letar faktiskt efter ett oscilloskop just nu, men det är ganska dyra saker och jag vet inte riktigt hur mycket jag kommer att använda det osv så jag håller på och tänkter på lite vilket jag ska köpa osv.

men, det är på g...

det med loopar låter helt klart mycket simplare än med timern, loopar kan jag iaf ;)
Användarvisningsbild
karlstedt
EF Sponsor
Inlägg: 966
Blev medlem: 14 oktober 2003, 16:55:23
Ort: Lund
Kontakt:

Inlägg av karlstedt »

Kör du avr-gcc kommer denna koden att kompilera. Precis som tidigare sagt kommer denna att skicka ett pulståg på PORTB.0 med 38 Khz. Testa denna för att öka förståelsen för det du vill åstadkomma.

Kod: Markera allt

#include <avr/io.h>
#include <avr/delay.h>

void ask(uint16_t antal_perioder);

int main(void)
{		
	DDRB = 0xFF;
	PORTB = 0xFF;
	
	while(1)
	{
		ask(65000);
	}
}


void ask(uint16_t antal_perioder)
{
	for(int i=0; i<antal_perioder; i++)
	{
		PORTB |= (1<<PB0);
		_delay_us(13);
		PORTB &= ~(1<<PB0);
		_delay_us(13);
	}
}
Min multimeter noterade 37.6 KHz. Vet ej om det beror på multimetern eller "segheten" med C-programmeringen. Antar att det läcker lite i allt hoppande som blir.
Virr3
Inlägg: 840
Blev medlem: 25 juli 2004, 23:05:59
Ort: Göteborg

Inlägg av Virr3 »

stort tack karlstedt, nu kanske jag kan komma lite frammåt i mitt lilla projekt:)

nu ska de "bara" knåpas ihop ett protocol så att jag kan skicka signaler som motsvarar att bokstäver i alfabetet :)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Virr3> det med loopar låter helt klart mycket simplare än med timern, loopar kan jag iaf...

Har inte en atmega32 någon PWM modul ? Den borde vara absolut enklast att använda. Set-and-forget. Sedan kan du koncentrera dig på att skapa pulserna, bärvågen skapar PWM modulen "under the hood".

Blir det inte lite onödigt knökigt att ligga i en "tight" loop som genererar bärvågen, samtidigt som man skall hålla koll på pulslängder och annat smått och gott (sköta LCD och tangentbord t.ex) ?
Användarvisningsbild
vfr
EF Sponsor
Inlägg: 3515
Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka

Inlägg av vfr »

Du kan alltid börja med loopvarianten för att "få igång" någonting på sändarsidan och senare göra om det till timer. Sodjans förslag är mycket bra! Det var fakstiskt samma lösning som jag använder till min IR-slav. Egentligen ganska enkelt om man läser databladen och får satt upp timern.

Det är alltid svårt att felsöka två delar i en länk samtidigt, så försök att förändra en sak i taget. Gör en enkel sändare med loopar först och försök sedan få igång någon form av mottagning. När mottagaren verkar funka så kan du börja göra sändaren mer avancerad med timer etc.

Vad du än gör, pilla _inte_ i båda ändarna samtidigt. Då vet man aldrig var felet ligger när det inte funkar.
Virr3
Inlägg: 840
Blev medlem: 25 juli 2004, 23:05:59
Ort: Göteborg

Inlägg av Virr3 »

okej:)
tack för tipset vfr:)

jag ska testa lite med ir:en och som vfr sa gå upp ett steg och köra pwm eller timern(vilket är smartast igentligen? alla säjer olika ;))
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Alltså, att generera en 38 Khz signal mjukvarumässigt innebär att processorn kommer att vara ganska upptagen med det (oavsett loop eller timer lösning).
Du kör ju C, pch då har man kanske inte 100% koll på timingen i alla lägen...

PWM modulen, å andra sidan, går helt av sig själv när man väl har konfigurerat den. Sedan är det bara att stänga av och på, men det sker ju med en mycket lägre frekvens än 38 Khz.
Dock vet jag fortfarande inte om atmega32 har en PWM modul.

PS: Jag kan inte AVR arkitekturen speciellt bra, och det är möjligt att det går att sätta up t.ex en timer så att den ger en kontinuerlig 38 Khz signal på en I/O pinne utan att använda något speciell pwm-modul, och sedan bara stoppa/starta timern för att generera pulserna. Även detta skulle i så fall sannolikt vara bättre/enklare än de andra lösningarna.

EDIT: Såg karlstedts inlägg om pwm kanaler. Jag skulle välja en av dom för bärvågen...
Senast redigerad av sodjan 26 oktober 2005, 22:54:47, redigerad totalt 1 gång.
Användarvisningsbild
karlstedt
EF Sponsor
Inlägg: 966
Blev medlem: 14 oktober 2003, 16:55:23
Ort: Lund
Kontakt:

Inlägg av karlstedt »

AVR använder sina timers till att generera PWM. ATMega32 har två PMW-kanaler om jag inte minns helt fel.
Virr3
Inlägg: 840
Blev medlem: 25 juli 2004, 23:05:59
Ort: Göteborg

Inlägg av Virr3 »

okej, då slutar jag läsa om timern och inriktar mig på pwm...

så ska ja se ifall jag kommer någonstans denhär gången;) men, de hoppas jag :)

aja, nu ska jag sova... sov så gott:)
frejo
Inlägg: 496
Blev medlem: 21 april 2004, 21:43:01
Ort: Linköping

Inlägg av frejo »

lite pwm-kod som jag skrev nån gång, vet inte om alla värden stämmer, räknat utifrån 16Mhz kristall om jag inte minns fel:

Kod: Markera allt

int main (void)
{
	
    // Using phase & freq correct pwm, TOP=ICR1, freq scaling = 8
    TCCR1A = _BV (COM1A1);
    TCCR1B = _BV (CS11) | _BV (WGM13);
  
    OCR = 600;		// ~10% dutycycle
    ICR1 = 100000; 	// 100Hz

    DDRD = _BV (OC1);   // enable OC1 as output

    timer_enable_int (_BV (TOIE1));

    /* enable interrupts */
    sei ();
Kolla registrena i koden mot databladet så kan du nog komma fram till vad du ska använda för värden i din kod.

edit:
ICR1 = 100000 ser ju helt galet ut med tanke på att registrena är 16-bitars, dvs max 65536, men men, kanske hjälper lite ändå
Användarvisningsbild
EagleSpirit
Inlägg: 1288
Blev medlem: 27 maj 2003, 23:15:48
Ort: Västerås
Kontakt:

Inlägg av EagleSpirit »

Ni pratar om att kretsen kommer vara upptaget att göra 38kHz pulsen. Den ska väl inte skicka IR-signalen hela tiden utan bara ibland när det behövs? Det handlar ju om ganska korta intervaller isf. Eller är det något jag har missat?

Fördelen med timer är ju att man är relativt säker på att man får 38khz. Om man kör med loop skulle det ju kunna finnas risk att ett interrupt tar över mitt i loopen och då blir det ju helt fel. Vet inte så mycket om AVR men de har väl precis som PIC en prioritetslista på interrupten? Alltså, om den håller på med ett lågprioritetsinterrupt så tar timerinterruptet över en liten stund och sen går tillbaka till lågprioritetsinterruptet.
Skriv svar