Hallo

Ik moet voor een infrarood detector een signaal hebben van 38000 Mhz. Dat signaal moet tussen 10 t/m 70 cycles lopen en dan moet er 14 cycles pauze tussen zien (detector is TSOP 1738). Hoe krijg ik zo'n signaal op de PIC16F887 met programmeertaal C?

38000MHz ?
Mischien zonder de M?

Het is een tsop, dus 38KHz.

Maak een pwm met een duty van 50% en een freq van 38KHz (ccp module). Gebruik een timer om het aantal pulsen te bepalen.

Je kan ook berekenen hoeveel us delay er tussen de pulsen zit. En dan gewoon hoog wachten laag wachten etc.

Bij de 1e kan je nog dingen tussendoor doen. De 2e is ietsje makkelijker.

Op 24 januari 2009 15:35:45 schreef rbeckers:
38000MHz ?
Mischien zonder de M?

Hopelijk wel, onze BD135 uitdaging is al lastig genoeg ;-)

Bedankt voor het antwoorden.
Ik bedoelde inderdaad 38000 Hz:P

Kan iemand mij vertellen hoe ik precies zo'n signaal kan opzetten met programmeertaal C? Ik kom er namelijk helemaal niet uit met behulp van de datasheet.

je moet in de DS kijken naar de CCP module die kan je dan configureren als pwm generator met een duty van 50%

dat signaal sluit aan op de Tsop.
pulstrein maak je met ofwel een timer interupt ofwel met een delay in de code het laatste is makkelijker en waarschijnlijk heeft je compiler ingebouwde delay routine's

[Bericht gewijzigd door timmie op (37%)]

Ik werk met MicroC en daar vond ik deze formule: PWM1_Init();
Tussen de haakjes kun je een frequentie neerzetten. Als ik daar 38000 neerzet dan klopt dat toch? Dan moet hij een pwm signaal maken van 38000 Hz. Of werkt dat niet?

Nu zoeken naar die timer interupt.

Timer instellen met juiste compare value (afhankelijk van de klok frequentie), toggle output on compare match aanzetten als je die hebt, anders een interrupt laten genereren en softwarematig de pin togglen.

dat zou wel moeten lukken inderdaad ik heb ehcter de lib van Mikroe daar nooit voor gebruikt dus ik weet niet hoe nauwkeurig dat is.

anders toch in de DS scheiten en de post van Sparky volgen.

Ik heb nu twee paar codes gemaakt.


void InitMain() {
  ANSEL  = 0;                       
  ANSELH = 0;
  
  PORTC = 0;                          
  TRISC = 0;                        
  PWM1_Init(38000);                   
}

void main() {

Pwm_Change_Duty(128);
  
  while (1) {                         
  PWM1_start();
}
}

Hiermee krijg ik een signaal die rond de 38000 Hz zit. maar nu moet ik voor de IR-detector rusttijden ertussen zetten. Dus kwam ik op deze code uit.


void InitMain() {
  ANSEL  = 0;                       
  ANSELH = 0;
  
  PORTC = 0;                          
  TRISC = 0;                        
  PWM1_Init(38000);                   
}

void main() {

Pwm_Change_Duty(128);
  
  while (1) {                         
  PWM1_start();
  Delay_us(1667);
  PWM1_stop();
  Delay_us(342);
}
}

Alleen deze werkt niet want dan krijg ik opeens een signaal van rond de 20000 Hz. Klopt die code of moet ik het toch anders aanpakken?

Wat gaat er schuil achter de Delay code, sommige compilers of includes maken gebruik van een timer on de delays te creëren, misschien is dat nu ook het geval. De timer voor de PWM is (meestal) Timer2, het kan zijn dat je PWM freq. daardoor is aangetast.

Hoe meet je de frequentie, scoop?

De tijd voor Delay heb ik zo berekent dat hij 13 pulsen geen PWM signaal geeft en ik dacht 60 pulsen wel een PWM signaal. Ik heb de frequentie gemeten met een scoop. Hoe kan ik dan beter die pulsen doen? zodat de frequentie goed blijft en dat daarnaat nog wel andere functies kunnen draaien. Het is namelijk voor een robot.

Dit is misschien een oplossing:


void InitMain() {
    ANSEL  = 0;                       
    ANSELH = 0;
    
    PORTC = 0;                          
    TRISC = 0;                        
    PWM1_Init(38000);                   
}

char cnt_cycle;

void main() {
    Pwm_Change_Duty(128);       // LET OP: als dit de waarde is voor
                                // CCPR1L dan gaat er iets mis, er zal
                                // dan geen 50% duty cycle komen!!!
    cnt_cycle = 0;              // stel counter gelijk aan 0
    TMR2IF = 0;                 // wis Timer 2 Match flag
    
    while(1) {                  // main loop
        Pwm_Change_Duty(128);   // 50% DC (pulse aan)
        while(cnt_cycle < 60) { // Loop tot 60 PWM cycles zijn uitgevoerd
            if( TMR2IF == 1 ) { // Test of er een Timer 2 Match is geweest
                cnt_cycle++;    // Verhoog counter
                TMR2IF = 0;     // Wis Timer 2 Match flag
            }
        }
        cnt_cycle = 0;          // stel counter gelijk aan 0
        Pwm_Change_Duty(0);     // 0% DC (pulse uit)
        while(cnt_cycle < 14) { // Loop tot 14 PWM cycles zijn uitgevoerd
            if( TMR2IF == 1 ) { // Test of er een Timer 2 Match is geweest
                cnt_cycle++;    // Verhoog counter
                TMR2IF = 0;     // Wis Timer 2 Match flag
            }
        }
        cnt_cycle = 0;          // stel counter gelijk aan 0
    }
}

En als je er naast nog code wil runnen, dan kun je de wacht lussen vervangen door timer 2 interupt routines. Op die manier krijg je elke keer als een PWM puls is doorlopen een interupt op TMR2IF en kun je de counters ophogen en actie ondernemen.

Ik probeerde hem de compileren alleen geeft deze error "Assigning non-Ivalue [TMR2IF]". Wat moet ik veranderen?

Ik denk dat dat komt doordat treinfreak OF een andere compiler gebruikt OF een #define heeft waarin de juiste TMR2IF register gedefined wordt. (iets als: #define TMR2IF IF0bits.T2IF)

Is niet direct in compiler geschreven en is daarom niet 1:1 over te nemen. TMR2IF is de naam in de datasheed, de naam in de (meeste) compiler(s) is idd IF0bits.T2IF .

Ik heb nu dus deze code


void InitMain() {
    ANSEL  = 0;
    ANSELH = 0;

    PORTC = 0;
    TRISC = 0;
    PWM1_Init(38000);
}

char cnt_cycle;

void main() {
    Pwm_Change_Duty(128);       // LET OP: als dit de waarde is voor
                                // CCPR1L dan gaat er iets mis, er zal
                                // dan geen 50% duty cycle komen!!!
    cnt_cycle = 0;              // stel counter gelijk aan 0
    PIR1.TMR2IF  = 0;                 // wis Timer 2 Match flag

    while(1) {                  // main loop
        Pwm_Change_Duty(128);   // 50% DC (pulse aan)
        while(cnt_cycle < 60) { // Loop tot 60 PWM cycles zijn uitgevoerd
            if( PIR1.TMR2IF  == 1 ) { // Test of er een Timer 2 Match is geweest
                cnt_cycle++;    // Verhoog counter
                PIR1.TMR2IF = 0;     // Wis Timer 2 Match flag
            }
        }
        cnt_cycle = 0;          // stel counter gelijk aan 0
        Pwm_Change_Duty(0);     // 0% DC (pulse uit)
        while(cnt_cycle < 14) { // Loop tot 14 PWM cycles zijn uitgevoerd
            if( PIR1.TMR2IF == 1 ) { // Test of er een Timer 2 Match is geweest
                cnt_cycle++;    // Verhoog counter
                PIR1.TMR2IF = 0;     // Wis Timer 2 Match flag
            }
        }
        cnt_cycle = 0;          // stel counter gelijk aan 0
    }
}

Alleen krijg ik dus weer een frequentie van ongeveer 20000 Hz. Maar daartussen zitten wel ruimtes waar het signaal laag blijft. Doe ik nu nog steeds iets fout?

Welke manier genereer je de klok, en welke freq?

Ik denk dat daar iets mis gaat omdat de functie voor PWM niet weet wat de waarde van de klok is.

De klok kan ik via MikroC instellen. Ik heb deze ingesteld op HS en dan zit er een externe kristal van 20 Mhz aan de PIC. Moet ik deze anders instellen? Ik test de PIC op de
EasyPIC5 van mikroe.com met een scoop.

[Bericht gewijzigd door Karim op (17%)]

Ik heb nu geprobeerd om een 38000 Hz signaal op te wekken met een NE555. Het signaal komt in de buurt van 38000 Hz en de TSOP1738 reageert erop zonder dat ik rust momenten in het 38000 Hz signaal heb zitten. Want in de datasheet van de TSOP1738 staat dat je rustmomenten moet inbouwen. Dit is dus toch niet nodig. Hoe kan dat?

Vraagje,

waarvoor is het signaal, want normaal gesproken wordt deze sensor gebruikt om gemoduleerde data te ontvangen en wat jij doet is gewoon de draaggolf bulken.

Nu staan er een paar punten in de DS:

  • Carrier frequency should be close to center
    frequency of the bandpass (e.g. 38kHz).
  • Burst length should be 10 cycles/burst or longer.
  • After each burst which is between 10 cycles and 70
    cycles a gap time of at least 14 cycles is neccessary.
  • For each burst which is longer than 1.8ms a
    corresponding gap time is necessary at some time in the data stream. This gap time should have at least same length as the burst.
  • Up to 1400 short bursts per second can be received continuously.

Maar ook:

  • DC light (e.g. from tungsten bulb or sunlight)
  • Continuous signal at 38kHz or at any other
    frequency
  • Signals from fluorescent lamps with electronic ballast.

Vooral hier boven puntje 2 is vreemd in combo met wat jij noemt.

Maar daarom, wat is de applicatie?