RC5 Decoder (avr)

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Carino
  • Registratie: Mei 2003
  • Laatst online: 15-09 21:30
Hoi Allen,

Ik ben voor een casemod bezig met een USB HID, dit kleine apparaatje moet ervoor zorgen dat ik de knoppen, displays, LEDjes en IR ontvanger die in de kast van m'n versterker zitten kan gebruiken op m'n computer. Tot nu toe heb ik alles werkend, op een ding na: de IR ontvanger.

Ik zal hieronder m'n probleem en bevindingen beschrijven. Even een kleine voetnoot: dit is mijn eerste elektronica project en tevens mijn eerste uC programmeer project. Ik heb wel behoorlijk wat ervaring met andere programmeertalen en systemen.

De basis van het apparaatje is een atmega328p microprocessor van Atmel. Via een MAX232 level shifter stuur ik een RS232 signaal naar een VFD display en via een MCP23016 port expander heb ik alle knoppen op het frontpanel van de versterker kast (Harman Kardon AVR255) verbonden. Het laatste opstakel is de infrarood ontvanger.

De IR module die ik gebruik is een Vishay TSOP2238. Op aanraden van Frank Zhau (de maker van de USnooBie: http://frank.circleofcurrent.com/usnoobie/) heb ik de data pin van de IR ontvanger aangesloten op de ICP poort van de atmega328p. Tevens heb ik een LEDje aangesloten op de data pin om het signaal te 'zien'. So far so good, wanneer ik een signaal verstuur vanaf een willekeurige afstandsbediening krijg ik netjes een knipperend LEDje. 'Spook' signalen die ik eerst had, toen ik de pull-up weerstand vergeten was, zijn er niet meer.

Het probleem wat ik heb is dat ik niet goed weet hoe ik moet beginnen met het programmeren van de ontvanger. Ik heb wel al uitgevonden dat ik gebruik moet maken van een 16bit timer en interrupts. Het uiteindelijke doel is dat ik een willekeurige afstandsbediening kan pakken en wanneer ik dan op een knop druk moet het binaire signaal naar de computer verstuurd worden via een HID report. Vervolgens kan ik op de computer in m'n in c# geschreven tooltje aangeven dat ik een functie wil programmeren. De computer ontvangt de binaire code en slaat dit op in een register. De volgende keer dat de computer diezelfde binaire code ontvangt moet er een actie uitgevoerd worden. Wat die actie is maakt in dit verhaal nog niet uit, maar kan varieren van een applicatie starten tot het besturen van Media Portal.

Ik hoop dat iemand hier ervaring heeft met het programmeren van de atmega328 of atmega168 in avr-gcc, niet in assembly omdat dit niet samen gaat met de al geschreven code.

in ieder geval alvast bedankt voor het meedenken!

p.s.
Ik ben op de hoogte van de al bestaande IR ontvanger topics maar omdat dit een meer specifiek item is, ben ik van mening dat het wel een eigen draadje verdient :-)

Acties:
  • 0 Henk 'm!

  • Guldan
  • Registratie: Juli 2002
  • Laatst online: 16-09 20:58

Guldan

Thee-Nerd

De 328 zit toch ook op een arduino. Voor arduino zijn er wel IR libraries beschikbaar. Mischien heb je daar wat aan

http://www.arcfn.com/2009...rared-remote-library.html

You know, I used to think it was awful that life was so unfair. Then I thought, wouldn't it be much worse if life were fair, and all the terrible things that happen to us come because we actually deserve them?


Acties:
  • 0 Henk 'm!

  • Carino
  • Registratie: Mei 2003
  • Laatst online: 15-09 21:30
Guldan schreef op dinsdag 22 februari 2011 @ 12:14:
De 328 zit toch ook op een arduino. Voor arduino zijn er wel IR libraries beschikbaar. Mischien heb je daar wat aan

http://www.arcfn.com/2009...rared-remote-library.html
Arduino werkt er inderdaad gewoon op, echter wil ik het zaakje juist zonder Arduino werkend krijgen. Dat komt voornamelijk omdat ik de rest van de code al in native code geschreven heb. Arduino wil ik een beetje als 'last-resort' houden ;-)

Acties:
  • 0 Henk 'm!

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 11-08 04:52

Sprite_tm

Semi-Chinees

Zo moeilijk is het toch niet? Je zorgt ervoor dat je input-capture-actie elke keer dat je IR-signaal verandert een interrupt geeft. Verder laat je de timer die erbij zit lopen. Op het moment dat je dan een ICP-interrupt krijgt kan je in het input-capture-register uitlezen wat de tijd is dat het signaal hoog of laag geweest is. Leg die tijd tegen wat je weet van rc5 (zie https://secure.wikimedia.org/wikipedia/en/wiki/RC-5), decodeer em en je bent klaar.

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


Acties:
  • 0 Henk 'm!

  • Carino
  • Registratie: Mei 2003
  • Laatst online: 15-09 21:30
Sprite_tm schreef op dinsdag 22 februari 2011 @ 13:23:
Zo moeilijk is het toch niet? Je zorgt ervoor dat je input-capture-actie elke keer dat je IR-signaal verandert een interrupt geeft. Verder laat je de timer die erbij zit lopen. Op het moment dat je dan een ICP-interrupt krijgt kan je in het input-capture-register uitlezen wat de tijd is dat het signaal hoog of laag geweest is. Leg die tijd tegen wat je weet van rc5 (zie https://secure.wikimedia.org/wikipedia/en/wiki/RC-5), decodeer em en je bent klaar.
als ik het zo lees is het inderdaad vrijwel kinderlijk eenvoudig. Echter, zoals ik in m'n topicstart aan gaf is dit m'n eerste elektronica project en ben ik ook nieuw op het gebied van uC programming.

bedankt in ieder geval voor je verhelderende antwoord, ik ga vanavond aan de slag!

Acties:
  • 0 Henk 'm!

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 11-08 04:52

Sprite_tm

Semi-Chinees

Prima :) Mocht je nog dingen niet begrijpen vraag gerust naar details.

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


Acties:
  • 0 Henk 'm!

  • Carino
  • Registratie: Mei 2003
  • Laatst online: 15-09 21:30
Sprite_tm schreef op dinsdag 22 februari 2011 @ 13:49:
Prima :) Mocht je nog dingen niet begrijpen vraag gerust naar details.
ik moet vooral even uitzoeken hoe de ICP interrupts precies werken. Ik heb een tutorial gevonden die in de basis hetzelfde werkt, maar wel een ander doel heeft (http://winavr.scienceprog.com/example-avr-projects/measuring-motor-speed-and-display-result-on-lcd.html). Daar wordt ook de ICP pin gebruikt en via timers wordt daar de RPM bepaald. Aangezien ik met een On- en Off-pulse moet werken is mijn uiteindelijke uitwerking wel anders, maar de basis (het triggeren van de ICP interrupt en het timen van de pulses) is ongeveer hetzelfde :-)


p.s.
ik zal voor geïnteresseerden wanneer ik klaar ben de schema's en broncode (van de microprocessor en het windows tooltje) posten.

[ Voor 14% gewijzigd door Carino op 22-02-2011 13:57 ]


Acties:
  • 0 Henk 'm!

  • Sissors
  • Registratie: Mei 2005
  • Niet online
Mijn google resultaat, kan denk ik ook wel helpen: http://homepage.hispeed.ch/peterfleury/avr-software.html
Wel een beetje overkill denk ik gezien dat hij zelf (volgens de beschrijving iig) synchroniseert met het RC5 signaal, terwijl als het signaal een beetje netjes gedefinieerd is dat denk ik niet nodig is.

Atmel heeft ook een application note erover maar die is in assembly gedaan (in principe kan je volgens mij wel assembly code in AVR-GCC includen): http://www.atmel.com/dyn/...rod_documents/doc1473.pdf

Acties:
  • 0 Henk 'm!

  • Carino
  • Registratie: Mei 2003
  • Laatst online: 15-09 21:30
furby-killer schreef op dinsdag 22 februari 2011 @ 14:19:
Mijn google resultaat, kan denk ik ook wel helpen: http://homepage.hispeed.ch/peterfleury/avr-software.html
Wel een beetje overkill denk ik gezien dat hij zelf (volgens de beschrijving iig) synchroniseert met het RC5 signaal, terwijl als het signaal een beetje netjes gedefinieerd is dat denk ik niet nodig is.
bedankt! ik zal thuis nog even goed in dat voorbeeld duiken, het is absoluut wenselijk dat het signaal gedecodeerd wordt en naar een byte omgezet wordt. Dat maakt de communicatie in m'n HID report vele malen makkelijker en efficiënter. ik zal die code alleen moeten omzetten naar een systeem wat gebruik maakt van ICP, voornamelijk omdat de timings van vusb (de library die ik gebruik voor USB communicatie) erg strict zijn.

het zou mooi zijn als ik ook niet van te voren afstandsbedieningspecifieke instellingen in de code hoef te plaatsen, dan kan ik namelijk ook een andere afstandsbediening gebruiken zonder dat ik de code hoef aan te passen. eventueel zou ik dat in de eeprom kunnen plaatsen en dat via de c# tool aanpassen, dat is nog het overwegen waard.
furby-killer schreef op dinsdag 22 februari 2011 @ 14:19:
Atmel heeft ook een application note erover maar die is in assembly gedaan (in principe kan je volgens mij wel assembly code in AVR-GCC includen): http://www.atmel.com/dyn/...rod_documents/doc1473.pdf
die was ik al tegen gekomen, maar omdat het in assembly geschreven is heb ik 't gelijk weer genegeerd ;-)

Acties:
  • 0 Henk 'm!

  • Carino
  • Registratie: Mei 2003
  • Laatst online: 15-09 21:30
Sprite_tm schreef op dinsdag 22 februari 2011 @ 13:23:
Zo moeilijk is het toch niet? Je zorgt ervoor dat je input-capture-actie elke keer dat je IR-signaal verandert een interrupt geeft. Verder laat je de timer die erbij zit lopen. Op het moment dat je dan een ICP-interrupt krijgt kan je in het input-capture-register uitlezen wat de tijd is dat het signaal hoog of laag geweest is. Leg die tijd tegen wat je weet van rc5 (zie https://secure.wikimedia.org/wikipedia/en/wiki/RC-5), decodeer em en je bent klaar.
Ik heb net geprobeerd om via een ICP interrupt een melding op m'n display te plaatsen. Puur om te testen of ik het interrupt ontvang. Helaas nog zonder resultaat.

Ik denk dat ik de timer of de interrupt niet goed initialiseer :(

Hieronder stukken uit m'n code:

code:
1
2
3
4
5
6
7
8
9
10
#define ICP PINB0

//define ovrflow counter
uint16_t ov_counter;

//define times for start and end of signal
uint16_t rising, falling;

//define overall counts
uint32_t counts;


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ISR(TIMER1_OVF_vect){
  ov_counter++;
}

ISR(TIMER1_CAPT_vect) {
    /*This subroutine checks was it start of pulse (rising edge)
    or was it end (fallingedge)and performs required operations*/
    if (ICP) //if high level
    {
        //save start time
        rising=ICR1;

        //set to trigger on falling edge
        TCCR1B=TCCR1B&0xBF;
        
        //reset overflow counter
        ov_counter=0;
        fprintf(&ser_stdout, "rising");
    }
    else
    {
        //save falling time
        falling=ICR1;
        
        //rising edge triggers next
        TCCR1B=TCCR1B|0x40;
        counts=(uint32_t)falling-(uint32_t)rising+(uint32_t)ov_counter; /*you can convert coutns to seconds and send to LCD*/
        //fprintf(&ser_stdout, "%d\r\n", counts);
        fprintf(&ser_stdout, "falling");
    }
}


deze code staat in m'n main functie
code:
1
2
3
4
5
6
PORTB|=1<<ICP;//pullup enable
DDRB&=~(1<<ICP);//ICR1 as input
TCNT1=0;// start counting from zero
TIMSK1|=(1<<TOIE0);//|(1<<TOIE1);//enable input capture interrupts
TCCR1A=0;
TCCR1B|=(1<<CS11);//start with prescaller 8, rising edge ICP1


Ik heb e.e.a. aan moeten passen, omdat het voorbeeld waar ik dit op gebaseerd heb gebruikt maakt van een atmega8 en ik gebruik een atmega328.

Ik hoop dat iemand zo 1.2.3 kan zien wat ik verkeerd doe

edit
ik ben een stapje verder... ik krijg inmiddels het interrupt goed binnen en ik wordt naar de juiste functie gestuurd. ik print op dit moment op m'n display hoe vaak ik in de functie gekomen ben. volgende stap: timings toevoegen :-)

[ Voor 5% gewijzigd door Carino op 22-02-2011 21:41 ]


Acties:
  • 0 Henk 'm!

  • Sissors
  • Registratie: Mei 2005
  • Niet online
Ook voor degene die dit topic later nog een keer googlen, wat ging er fout? Als ik zo kijk niet interrupts geenabled met sei()? (Uit mijn hoofd staat die standaard uit)

[ Voor 13% gewijzigd door Sissors op 23-02-2011 10:27 ]


Acties:
  • 0 Henk 'm!

  • Carino
  • Registratie: Mei 2003
  • Laatst online: 15-09 21:30
furby-killer schreef op woensdag 23 februari 2011 @ 10:25:
Ook voor degene die dit topic later nog een keer googlen, wat ging er fout? Als ik zo kijk niet interrupts geenabled met sei()? (Uit mijn hoofd staat die standaard uit)
Het probleem was dat ik de timer (TCCR1B) niet goed activeerde. Ik had sei() al in m'n main functie staan, maar omdat ik niet de volledige code van m'n main functie geplaatst had was dat niet zichtbaar.

Ik ben nu op het punt beland dat ik het verschil tussen de rising en falling edge moet zien te detecteren. Eerst maar eens uitzoeken hoe ik de timer zo kan instellen dat dit goed gebeurt.
Pagina: 1