Göra Nexa mottagare med PIC, hur mäta pulslängd?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Pajn
Inlägg: 1160
Blev medlem: 6 juni 2008, 19:14:29
Ort: Nyköping
Kontakt:

Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av Pajn »

Jag vill göra en mottagare för nexa men har fastnat direkt.

Efter lite googlande tycker jag det verkar som CCP i capture läge är bra eftersom en etta skickas som:
Hög i 320µS och Låg i 200µS
och en nolla som:
Hög i 320µS och Låg i 1210µS

Vad jag förstått ska man med Capture kunna mäta pulslängden men jag fattar inte hur.
Databladet ger inte tillräckligt med information (16F648A).
Hittills har jag bara initierat TIMER1 med 1:8 prescaler och INTOSC samt CCP som capture on rising edge

Kod: Markera allt

void main () {
    CMCON  = 7;      // Turn off the comparators
    PORTA = 0;       // Define states of processor pins ...
    TRISA = 0;       // Define in (1) or out (0) of processor pins ...
    PORTB = 0;       // Define states of processor pins ...
    TRISB = 0;       // Define in (1) or out (0) of processor pins ...
    TRISB.F3 = 1;    // Define in (1) or out (0) of processor pins ...
    
    T1CON = 0b00111001;
    CCP1M = 0b00000101;
}
Någons som vill förklara lite snabbt hur jag gör för att nå önskat syfte?

Ibland undrar man varför man inte kör AVR. Att googla på AVR+capture ger inte många träffar som har med microcontroller att göra ;)
Gustav180
Inlägg: 560
Blev medlem: 5 januari 2011, 22:17:11
Skype: anders_gust
Ort: Jönköping

Re: Göra nexa motagare med pic, hur mäta pulslängd?

Inlägg av Gustav180 »

Kanske jag kan hjälpa dig...

För att mäta pulslängden skall TMR1 startas samtidigt med pulsflanken går H. Det görs genom att sätta TMR1ON = 1.
TMR1 räknar upp från 0000 med vald och synkroniserad klocka. (T1SYNC=0). Starten kan göras med polling eller interrupt.

När pulstiden skall mätas skall det detekteras på RB3/CCP1 som skall vara ställd som ingång, prescaler :1 och flankdetetektorn på falling. (CCP1M = 0100 ) Flanken "öppnar förbindelse" till CCPR1 som läser av TMR1 och sparar värdet. Värdet i CCPR1 blir ett mått på pulstiden. Det är denna operation som kallas för Capture.

Jag tror att du lika gärna skulle kunna sätta TMR1ON till 0 på neråtgående flank och läsa av TMR1.

Använder du 4 MHz CPU-klocka, så får du pulslängden direkt i µs. Du kan också använda egen klocka på RB6 och RB7.
Pajn
Inlägg: 1160
Blev medlem: 6 juni 2008, 19:14:29
Ort: Nyköping
Kontakt:

Re: Göra nexa motagare med pic, hur mäta pulslängd?

Inlägg av Pajn »

Nu uttryckte jag mig fel. Vill läsa hela "periodtiden" eller vad man ska kalla det (320 + 200 eller 320 + 1210).
Men om jag gör:

Kod: Markera allt

char code[8];
char code2[8];

void interrupt(){
    if (CCPR1 < 600 && CCPR1  > 450) {
        code = code << 1 | 1;
    } else if (CCPR1 < 600 && CCPR1  > 500) {
        code = code << 0 | 1;
    } else if (CCPR1  > 9500) {
        code2 = code;
    }
    CCCP1IF = 0;
}

void main () {
    CMCON  = 7;      // Turn off the comparators
    PORTA = 0;       // Define states of processor pins ...
    TRISA = 0;       // Define in (1) or out (0) of processor pins ...
    PORTB = 0;       // Define states of processor pins ...
    TRISB = 0;       // Define in (1) or out (0) of processor pins ...
    TRISB.F3 = 1;    // Define in (1) or out (0) of processor pins ...
   
    T1CON = 0b00001001;
    CCP1M = 0b00000101;

    while(1) {
        if (code == code2) {
            //wohoo!
        }
    }
}
Borde jag alltså code och code2 hålla strängen som sändaren skickar ut?
Visst, lite mer error checking behövs.

Kan inte testa nu, men om det funkar så är jag skyldig dig ett stort tack!
krille356
Inlägg: 354
Blev medlem: 5 oktober 2008, 08:33:37
Ort: Skåne

Re: Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av krille356 »

Jag gjorde något liknande för 4-5 år sedan.

http://www.minhembio.com/forum/index.ph ... =krille356

All mjukvara har varit klar i många år nu men tyvärr gjorde jag aldrig hela projektet färdigt :vissla:
Pajn
Inlägg: 1160
Blev medlem: 6 juni 2008, 19:14:29
Ort: Nyköping
Kontakt:

Re: Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av Pajn »

Jag har lekt lite med din kod och har äntligen fått fram rätt resultat (dock bara i en av de åtta sändningar min sändare skickar)

Här är tre "skick"
014 100 000 000 250 003 100 000 001 250 000 008 000 000 008 002 000 003 100 004 011 100 010 006 008 002 001 002 013 000 002 002 100 000 006 000 004 000 000 000 100 000 000

000 100 012 000 250 003 100 000 001 250 008 100 001 003 012 100 010 000 008 100 012 009 004 000 000 001 010 001 000 000 000

000 100 012 000 250 003 100 000 001 250 002 000 000 012 000 012 002 000 002 100 008 009 003 000 100 001 004 008 100 000 000 000 100 001 000 000 000 000 000 000 000 000

000 100 000 000 250 003 100 000 000 250 002 100 009 008 000 000 011 003 100 010 004 008 100 001 009 000 004 100 000 000 100

Jag har fetmarkerat det som är rätt. Det konstiga är att det "varje gång" är den andra omsändningen som ger rätt resultat. (3st D1ON 1st D1OFF)
Första siffran är huskod, andra är att han mottagit halva sändarkoden, tredje är sändarkod, fjärde on/off och femte att han mottagit hela paketet (+ att den sista var en etta)
Pajn
Inlägg: 1160
Blev medlem: 6 juni 2008, 19:14:29
Ort: Nyköping
Kontakt:

Re: Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av Pajn »

Lyckades lösa det utifrån krilles kod (Tack!)
Än sålänge med många felande kommentarer, massor med oanvända variablar, utkommenterad kod och vissa saker som inte funkar (lätt att fixa men dock tråkigt så det får bli en annan dag)

Kod: Markera allt

bit ReciveDone,ReciveDone2,OldReciveRadio,ReciveRadioNew,OnOFFCode,Package,RadioBit,OldRadioBit,RadioBitValid,Alternate;
char RaidoBitCounter,ChannelCode,HouseCode,Change,TMR1L_TMP,TMR1H_TMP,sID;
unsigned long senderID;

//////////////////////////////////////////////////////////////////////////////////////////
// InterruptFunction
//
//////////////////////////////////////////////////////////////////////////////////////////

void interrupt () {
        ReciveRadioNew = PORTB.B0;
        
    if(INTCON.INTF) {

        // We handle all radio stuff from hear
        // We are only looking for new transmisions if the old one is handeled
        //if( ReciveDone == 0 ) {

            //We save the counter value then the interupt vas dicovered
            //The counter is still runing thats way we nead to save the value
            TMR1H_TMP = TMR1H;

            //We resets the counter so we can measure the next puls with
            TMR1L = 0x00;
            TMR1H = 0x00;

            //High, should be 230-320µS (+-50µS = 23-46)
                if (TMR1H_TMP > 1 && TMR1H_TMP < 6) {
                            RadioBitValid = 1;
                        RadioBit = 1;
                }
            //Low, should be 170-200µS (+-50µS = 15-31) for High or 920-1210µS (+-100µS = 103-164) for Low
            else if (TMR1H_TMP > 9 && TMR1H_TMP < 16) {
                RadioBitValid = 1;
                RadioBit = 0;
            } else {
                    UART1_Write_Text("\r");
                    UART1_Write(TMR1H_TMP);
                    Change = 0;
                    Package = 0;
                    RaidoBitCounter = 0;
                    RadioBitValid = 0;
            }
            
            if (RadioBitValid) {
                    //UART1_Write(RadioBit);

                // Bit 0-51 is Sender ID
                if (RaidoBitCounter < 52) {
                    if (Alternate) {
                        senderID |= RadioBit << sID;
                        Alternate = 0;
                        sID++;
                    } else {
                        Alternate = 1;
                    }
                }
                // Bit 52-53 is Group
                else if (RaidoBitCounter == 53) {
                    //OnOFFCode = RadioBit;
                }
                // Bit 54-55 is On/Off
                else if (RaidoBitCounter == 55) {
                    OnOFFCode = RadioBit;
                }
                // Bit 56-59 is Channel
                else if (RaidoBitCounter == 56) {
                    ChannelCode |= RadioBit << 0;
                }
                else if (RaidoBitCounter == 57) {
                    ChannelCode |= RadioBit << 1;
                }
                else if (RaidoBitCounter == 58) {
                    ChannelCode |= RadioBit << 2;
                }
                else if (RaidoBitCounter == 59) {
                    ChannelCode |= RadioBit << 3;
                }
                // Bit 60-63 is Button
                else if (RaidoBitCounter == 60) {
                    HouseCode |= RadioBit << 0;
                }
                else if (RaidoBitCounter == 61) {
                    HouseCode |= RadioBit << 1;
                }
                else if (RaidoBitCounter == 62) {
                    HouseCode |= RadioBit << 2;
                }
                else if (RaidoBitCounter == 63) {
                    HouseCode |= RadioBit << 3;
                    UART1_Write_Text("5");
                    UART1_Write_Text(senderID);
                    UART1_Write_Text("6");
                    UART1_Write(OnOFFCode);
                    UART1_Write(ChannelCode);
                    UART1_Write(HouseCode);
                    UART1_Write_Text("7");
                }
                
                RaidoBitCounter++;
            }
        INTCON.INTF = 0;
            
            //Save The bit status for next time
            //OldReciveRadio = ReciveRadioNew;
            //OldRadioBit = RadioBit;
        //}
    }
}

void main () {
    //
    // Some setup commands goes here ..
    // ex. ...
    CMCON  = 7;        // Turn off the comparators
    PORTA = 0;         // Define states of processor pins ...
    TRISA = 0;         // Define in (1) or out (0) of processor pins ...
    PORTB = 255;         // Define states of processor pins ...
    TRISB = 0;         // Define in (1) or out (0) of processor pins ...
    TRISB.B0 = 1;      // Define in (1) or out (0) of processor pins ...
    PORTB = 255;         // Define states of processor pins ...
    UART1_Init(19200); // Initialize UART module at 19200 bps
    Delay_ms(100);     // Wait for UART module to stabilize

    T1CON = 0b00011001;// Enable timer1 with a prescaler of 1:8

    //option.INTEDG = 1;   // Enable RB interrupt.
    INTCON.INTE=1;     // Pheripheral enable interrupt.
    INTCON.GIE=1;      // Global enable interrupt
    
    //Clear some variables to be shure of their state
    ReciveDone = 0;
    OldReciveRadio = 0;
    Change = 0;
    Alternate = 1;
    sID = 0;
    senderID = 0;
    ChannelCode = 0;
    HouseCode = 0;

    while(1) {
        if(ReciveDone == 1) {
            ReciveDone = 0;
        }
    }
}
Gnäll inte på utseendet. Först ska det funka (vilket det nästan gör, måste bara splitta sender idt så att det flyter bättre över serieporten) och sen ska det bli snabbt och vackert :)

Ska lägga in gamla nexa oxå men 2000 var intressantast för stunden.
bos
Inlägg: 2314
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

Re: Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av bos »

Ett generellt tips: Du har alldeles för mycket kod i din interrupt.

Det kanske råkar fungera i just detta fall, men om din körning är inne i din ISR och en eller fler nya interrupts kommer, så missar du dessa. En ISR ska vara så kort och koncis som möjligt. Lite if-kod, några bit-sättningar och sen en return. Definitivt inte sju funktionsanrop. Dessa gör du helst utanför (i main()) efter att en relevant flagga satts inuti ISR.
Pajn
Inlägg: 1160
Blev medlem: 6 juni 2008, 19:14:29
Ort: Nyköping
Kontakt:

Re: Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av Pajn »

Jag vet. Men det är bara RF mottagaren som gör interrupt och jag hinner med utan problem (Körde först i 4MHz vilket funkade men har nu gått upp i 20 och kommer troligtvis öka till 32 eller 48 när jag byter till en 2550).
Jag kommer dock ta bort allt vad UART i interruptrutinen heter när jag är mer klar med koden (debuging är nice).

Detta får ses som ett fulhack för detta specifika fall.

Men jag skulle kunna flytta ut lite mer, bara för att. Får se hur det blir med det.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av sodjan »

En annan liten sak...

> ...många felande kommentarer, ...oanvända variablar, utkommenterad kod och vissa saker som inte funkar...

Men varför posta koden alls i så fall ?
Du hade ju inte heller några frågor eller andra problem kring det hela.
Koden är ju knappast till glädje för någon annan med alla dessa fel/problem.
Pajn
Inlägg: 1160
Blev medlem: 6 juni 2008, 19:14:29
Ort: Nyköping
Kontakt:

Re: Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av Pajn »

Sant. Av vana antar jag :doh:
Användarvisningsbild
lond
Inlägg: 3548
Blev medlem: 23 september 2009, 11:52:45
Ort: Hyssna

Re: Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av lond »

Tjena!

Annars kan du slänga ett öga på mitt lilla bygge: viewtopic.php?f=3&t=37556
Mottagaren klara av både NEXA och NEXA2000 sändare.

/// Marcus
Pajn
Inlägg: 1160
Blev medlem: 6 juni 2008, 19:14:29
Ort: Nyköping
Kontakt:

Re: Göra Nexa mottagare med PIC, hur mäta pulslängd?

Inlägg av Pajn »

Såg den innan men tyvärr förstod jag inte mycket av BASICen :oops:
Men tack ändå!

Jag löste det igår samt förminskade interruptrutinen. Men eftersom man är alldeles för klåfingrig så slutade Nexa2000 att fungera en timma senare, minns inte vad jag ändrade heller :vissla:
Skriv svar