Sari la conținut
ELFORUM - Forumul electronistilor

Timer cu PIC12F675


Seppy

Postări Recomandate

Salut,

 

Proiectul atasat este facut in MPLABX 3.65, compilatorul XC8 1.43 Free Mode.

In arhiva atasata este si o simulare Proteus 8.3

 

Cod:

/*
 * File:   main.c
 * Author: mars01 on http://www.elforum.ro
 *
 * Created on August 20, 2017, 1:08 AM
 * Datasheet PIC12F675: http://ww1.microchip.com/downloads/en/devicedoc/41190c.pdf
 */

// PIC12F675 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = ON        // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF      // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#define _XTAL_FREQ  4000000

#define INPUT   1
#define OUTPUT  0

#define GOARNA          GP1         // pinul 6
#define GOARNA_DIR      TRISIO1     
#define FAR_AUTO        GP2         // pinul 5
#define FAR_AUTO_DIR    TRISIO2

// LDR-ul se conecteaza pe pinul 7 adica AN0
#define LDR_THRESHOLD   512     // jumatate din valoarea maxima a ADC

enum {
    OFF = 0,
    ON = 1
};

void HW_init(void) {
    
    
    // WDT init
    PSA = 1;    // Prescaler asigned to the watchdog
    PS2 = 1;    // Prescaler set to 1:16 so the WDT timeout period is 18ms * 16 = 288ms
    PS1 = 0;
    PS0 = 0;
    CLRWDT();   // reseteaza timer-ul watchdog
    
    ANSEL = 1;       // GP0 este pin analog/ADC, restul sunt digitali
    CMCON = 7;       // Comparator OFF
    GOARNA = OFF;   
    FAR_AUTO = OFF;

    GOARNA_DIR = OUTPUT;
    FAR_AUTO_DIR = OUTPUT;
    
    // ADC init
    CHS1 = 0;   // selectam canalul 0 al ADC adica AN0 adica pinul 7
    CHS0 = 0;
    
    ADFM = 1;   // rezultatul ADC este aliniat la dreapta
    VCFG = 0;   // referinta este VDD

    ADCS2 = 1;  // ADCS2 = 1; ADCS1 = 1; ADCS0 = 1; => se foloseste Frc 
    ADCS1 = 1;
    ADCS0 = 1;
    ADON = 1;   // Enable ADC
        
}

unsigned int ADC_read(void){
    
    unsigned int result;
    CLRWDT();
    
    // cat timp ADC-ul este ocupat, asteapta sa devina disponibil
    while (GO_DONE) {
        __nop();    // stai degeaba; este introdus pt ca sa nu optimizeze compilatorul  
    }
    
    // fa un delay de 50us (>> 20us - minimum acquisition time)
    __delay_us(50);
    
    GO_DONE = 1;    // start conversion
    
    // wait for the end of the conversion
    while (GO_DONE) {
        __nop();
    }
    result = ADRESH;
    result = ((result << 8) | ADRESL) & 0x3FF;
    return result;    
}

void main() {
    unsigned int i,j;    // counters
    
    HW_init();
    
    while (1) {
        if (ADC_read() >= LDR_THRESHOLD) {
        
            /* delay de 3secunde care sa actioneze ca protectie impotriva 
             * iluminarilor accidentale in timpul noptii cum ar fi lumina unei 
             * lanterne sau un fulger etc
            */
            for (i = 30; i > 0; i--){
                CLRWDT();
                __delay_ms(100);
            }
            
            // daca dupa 3 secunde senzorul tot indica ca este iluminat atunci
            if (ADC_read() >= LDR_THRESHOLD){
                while (ADC_read() >= LDR_THRESHOLD){
                    __nop();    // stai degeaba cat timp este lumina afara
                }
                
            }
        }
        
        
        CLRWDT();
        GOARNA = ON;
        FAR_AUTO = ON;

        i = 600;
        j = 0;
        while (i--){
            __delay_ms(100);
            CLRWDT();
            if (j > 40) {
                j = 0;
                FAR_AUTO = !FAR_AUTO;
            }
            else {
                j++;
            }
        }

        // opreste alarma audio-vizuala
        GOARNA = OFF;
        FAR_AUTO = OFF;

        // delay 3000 * 100ms = 300000ms = 300s = 5minute
        i = 3000;
        while (i--){
            CLRWDT();
            __delay_ms(100);
        }
    }
    
    
}

z8i78.jpg

 

 

Alarma_animale.X.rar

Link spre comentariu

Vă mulțumesc pentru răspuns!

Atașez mai jos un cablaj, așa cum îl văd eu. Moșii folosiți pentru comanda becului farului și pentru sirenă sunt IRL3102S, recuperați dintr-o placă de bază, cred că fac față.(sper să găsesc in Sprint Layout și forma acestora).

Bine, la sirenă, care are vreo 600 Ma consum, cred că nici nu ar fi necesar, dar pentru becul farului, care ia vreo 5A, trebuie.

 

Ceea ce nu știu cum să fac în acest moment, sunt următoarele:

1. Nu am nici cea mai vagă idee este cum folosesc fotorezistența, mai exact cum o pun în montaj și cum fac calibrarea. Bănuiesc că trebuie un semireglabil multitură.

2. Am nevoie de rezistente de pull down pentru grilele moșilor? Dacă da, de ce valoare?

3. Ce valori trebuie să folosesc pentru rezistențele din comanda grilelor moșilor?

Photoview_placuta.jpg
Sprint_layout.png
Editat de Marius84
Link spre comentariu

Atentie ca pe cablaj ai doua net-uri GND care nu sunt unite intre ele (asa cum trebuie).

Ai un net GND in partea de jos a PCB-ului si un net GND legat la regulator si la pinul 8 al uC-ului.

 

Rezistorii dintre pini uC si grile MOSFET sa nu fie mai mari de 10 ohmi. Ce obtii este ca switch - on al MOSFET cand iesirea uC trece din LOW in HIGH, este intarziat ceea ce face MOSFET-ul sa treaca mai lent prin zona lineara dar pe de alta parte elimini asa numit-ul "ringing".

 

Daca vrei sa fii sigur ca MOSFET-ii sunt OFF in caz de avarie a controller-ului atunci foloseste rezistori de pull-down in valoare de 100Ko. E suficient ca sa ii tina OFF.

 

LDR-ul eu l-am figurat in simulare ca o pseudo-sursa de tensiune care variaza intre 0V si 5V (potentiometrul RV1). Pragul de declansare este stabilit la jumatate adica la 2.5V dar il poti modifica incat sa lucreze cum vrei tu. Premiza de la care am plecat este ca in schema ta obtii o tensiune mai mare de 2.5V cand e lumina afara si o tensiune mai mica de 2.5V cand este intuneric.

 

Am definit un prag prin comanda:

#define LDR_THRESHOLD   512     // jumatate din valoarea maxima a ADC

astfel incat este usor de modificat ca sa corespunda necesarului tau si proiectul sa fie recompilat obinand un .HEX nou corespunzator modificarilor.

 

Daca logica ta este inversa, adica daca LDR-ul iti ofera o tensiune mai mare de 2.5V cand este intuneric si mai mica de 2.5V cand este lumina, trebuie modificat programul in urmatoarele linii, din:

if (ADC_read() >= LDR_THRESHOLD) {
        
            /* delay de 3secunde care sa actioneze ca protectie impotriva 
             * iluminarilor accidentale in timpul noptii cum ar fi lumina unei 
             * lanterne sau un fulger etc
            */
            for (i = 30; i > 0; i--){
                CLRWDT();
                __delay_ms(100);
            }
            
            // daca dupa 3 secunde senzorul tot indica ca este iluminat atunci
            if (ADC_read() >= LDR_THRESHOLD){
                while (ADC_read() >= LDR_THRESHOLD){
                    __nop();    // stai degeaba cat timp este lumina afara
                }
                
            }
        }

in ceva de genul:

if (ADC_read() <= LDR_THRESHOLD) {
        
            /* delay de 3secunde care sa actioneze ca protectie impotriva 
             * iluminarilor accidentale in timpul noptii cum ar fi lumina unei 
             * lanterne sau un fulger etc
            */
            for (i = 30; i > 0; i--){
                CLRWDT();
                __delay_ms(100);
            }
            
            // daca dupa 3 secunde senzorul tot indica ca este iluminat atunci
            if (ADC_read() <= LDR_THRESHOLD){
                while (ADC_read() <= LDR_THRESHOLD){
                    __nop();    // stai degeaba cat timp este lumina afara
                }
                
            }
        }

Te poti inspira de aici:

https://diyhacking.com/arduino-ldr-sensor/

 

Ce fac ei aici (si se poate folosi cu programul asa cum este, nemodificat) este: leaga un LDR cu un pin la 5V si cu pinul celalalt la pinul uC. Din acelasi pin uC leaga un rezistor de "pull down" catre GND, cu valoarea de 100K.

 

Dar in final depinde si de ce LDR folosesti...

 

LE: s-ar putea sa fie necesar ca rezistorul de pull-down din pinul 7 al 12F675 (pinul uC unde este conectat LDR-ul catre +5V) sa fie maxim 10K si nu 100K cum am scris mai sus. Aceasta pentru ca nu am tinut cont de recomandarea din datasheet ca impedanta la intrarea ADC sa nu fie mai mare de 10K pentru ca sa se permita condensatorului din circuitul de sample & hold sa se incarce suficient.

Editat de mars01
Link spre comentariu

Fotorezistența pe care o folosesc are într-o cameră iluminată cu un bec de 100w cam 5k. La o distanță de cca. 10 cm. de acel bec are vreo 300 de ohmi, iar în beznă totală are peste 60Mohmi, cât poate maxim aparatul meu.

Urmează să mă trezesc astăzi pe la ora 5 ca să văd cam ce rezistență va avea la lumina pe care o voi aprecia eu ochiometric drept prag.

Atașez mai jos plăcuța cred eu finalizată, dacă mai aveți bunăvoința de a o examina, poate s-a mai strecurat vreo eroare...

Photoview_placuta.jpg
Sprint_layout.jpg
Link spre comentariu

Layout-ul pare sa aiba integritate de data acesta.

 

As face totusi cateva mentiuni:

 

1. rezistorii aia de pull-up pentru mosfeti ar fi bine sa fie mai mari de 47K pt ca nu e nevoie de o valoare asa mica ca 10K. Cu cat e mai mic rezistorul acesta cu atat trage mai mult curent din pinul uC-ului care se traduce prin faptul ca ajunge mai putin curent care sa incarce condensatorul intrisec al MOSFET-ului, ceea ce inseamna ca MOSFET-ul, teoretic, sta mai mult in zona lineara. E drept insa ca nu face switching pe frecvente mari dar .... asa ca si chestie.

 

2. condensatorul de 100nF de decuplare pt uC este bine sa fie plasat cat mai aproape de pinul de alimentare VDD al uC-ului. Aceasta ca sa nu apara cine stie ce functionari voodoo. Desi am lasat activ brownout detection-ul si am activat watchdog-ul.

 

3. condensatorul de 10uF care este in paralel cu pot semireglabil este cam inutil avand in vedere ca am introdus in software un delay de 3 secunde pentru confirmarea faptului ca e lumina afara. Se poate lasa footprint-ul pe pozitie dar eu nu l-as popula intr-o prima faza.

 

4. eu as adauga un LED (cu un rezistor in serie, evident) pe alimentarea care intra in circuit. It's alive ... or not.

 

5. Pinul liber al semireglabilului l-as lega la pinul central. Asa cum e acum, sta ca un fel de .... antena. Cum circuitul trebuie sa stea nesupravegheat ... better safe than sorry.

 

6. LDR-ul e bine sa fie plasat intr-un cilindru de carton (preferabil negru - se poate colora cu marker-ul pe interior) rulat pe carcasa acestuia si cu o lungine de 3 ... 4 cm. Aceasta reduce posibilitatea de luminina incidenta aparuta accidental. Daca este plasat undeva distant fata de placuta, firele sa fie intr-un cablu ecranat cu ecranul legat la un GND.

Editat de mars01
Link spre comentariu

Multumesc pentru toate precizarile! Eu desi am terminat acum montajul, cand am cautat sa pun picul in soclu mi-am dat seama ca aveam de fapt 12f683. N-am decat sa fac astazi comanda, vad ca e la miva pe stoc. :39

IMG_20170821_030000.jpg

Editat de Marius84
Link spre comentariu

Varianta pentru 12F683, nu sunt modificari prea mari, doar numele unui registru:

/*
 * File:   main.c
 * Author: mars01 on http://www.elforum.ro
 *
 * Created on August 20, 2017, 1:08 AM
 * Datasheet PIC12F683: http://ww1.microchip.com/downloads/en/DeviceDoc/41211D_.pdf
 */


// PIC12F683 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = ON        // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#define _XTAL_FREQ  4000000

#define INPUT   1
#define OUTPUT  0

#define GOARNA          GP1         // pinul 6
#define GOARNA_DIR      TRISIO1     
#define FAR_AUTO        GP2         // pinul 5
#define FAR_AUTO_DIR    TRISIO2

// LDR-ul se conecteaza pe pinul 7 adica AN0
#define LDR_THRESHOLD   512     // jumatate din valoarea maxima a ADC

enum {
    OFF = 0,
    ON = 1
};

void HW_init(void) {
    
    
    // WDT init
    PSA = 1;    // Prescaler asigned to the watchdog
    PS2 = 1;    // Prescaler set to 1:16 so the WDT timeout period is 18ms * 16 = 288ms
    PS1 = 0;
    PS0 = 0;
    CLRWDT();   // reseteaza timer-ul watchdog
    
    ANSEL = 1;       // GP0 este pin analog/ADC, restul sunt digitali
    CMCON0 = 7;      // Comparator OFF
    GOARNA = OFF;   
    FAR_AUTO = OFF;

    GOARNA_DIR = OUTPUT;
    FAR_AUTO_DIR = OUTPUT;
    
    // ADC init
    CHS1 = 0;   // selectam canalul 0 al ADC adica AN0 adica pinul 7
    CHS0 = 0;
    
    ADFM = 1;   // rezultatul ADC este aliniat la dreapta
    VCFG = 0;   // referinta este VDD

    ADCS2 = 1;  // ADCS2 = 1; ADCS1 = 1; ADCS0 = 1; => se foloseste Frc 
    ADCS1 = 1;
    ADCS0 = 1;
    ADON = 1;   // Enable ADC
        
}

unsigned int ADC_read(void){
    
    unsigned int result;
    CLRWDT();
    
    // cat timp ADC-ul este ocupat, asteapta sa devina disponibil
    while (GO_DONE) {
        __nop();    // stai degeaba; este introdus pt ca sa nu optimizeze compilatorul  
    }
    
    // fa un delay de 50us (>> 20us - minimum acquisition time)
    __delay_us(50);
    
    GO_DONE = 1;    // start conversion
    
    // wait for the end of the conversion
    while (GO_DONE) {
        __nop();
    }
    result = ADRESH;
    result = ((result << 8) | ADRESL) & 0x3FF;
    return result;    
}

void main() {
    unsigned int i,j;    // counters
    
    HW_init();
    
    while (1) {
        if (ADC_read() >= LDR_THRESHOLD) {
        
            /* delay de 3secunde care sa actioneze ca protectie impotriva 
             * iluminarilor accidentale in timpul noptii cum ar fi lumina unei 
             * lanterne sau un fulger etc
            */
            for (i = 30; i > 0; i--){
                CLRWDT();
                __delay_ms(100);
            }
            
            // daca dupa 3 secunde senzorul tot indica ca este iluminat atunci
            if (ADC_read() >= LDR_THRESHOLD){
                while (ADC_read() >= LDR_THRESHOLD){
                    __nop();    // stai degeaba cat timp este lumina afara
                }
                
            }
        }
        
        
        CLRWDT();
        GOARNA = ON;
        FAR_AUTO = ON;

        i = 600;
        j = 0;
        while (i--){
            __delay_ms(100);
            CLRWDT();
            if (j > 50) {
                j = 0;
                FAR_AUTO = !FAR_AUTO;
            }
            else {
                j++;
            }
        }

        // opreste alarma audio-vizuala
        GOARNA = OFF;
        FAR_AUTO = OFF;

        // delay 3000 * 100ms = 300000ms = 300s = 5minute
        i = 3000;
        while (i--){
            CLRWDT();
            __delay_ms(100);
        }
    }
    
    
}

Alarma_animale_12F683.X.rar

Link spre comentariu

Mulțumesc pentru efortul suplimentar depus, cauzat de neatenția mea. Am făcut și comanda de 12F675, probabil joi vor veni și acelea.

În ceea ce privește pragul de declanșare a funcțiilor modulului la întuneric, am stat în seara aceasta și am măsurat rezistența fotorezistorului, iar la nivelul de lumină la care vreau eu să pornească are vreo 19k. Asta ar presupune să pun o rezistenţă de 19k spre masă, să o unesc cu fotorezistorul şi ideal ar trebui să fie 2.5v. Pe de altă parte, aţi spus să nu depășesc 10k spre masă pe pinul acela. Ce pot face în acest caz?

În momentul în care scriu, s-a făcut mult mai întuneric, iar fotorezistorul are 24,5k.

Link spre comentariu

In cazul in care rezistenta LDR-ului creste peste 19K, vreti ca montajul sa nu functioneze pentru ca este deja prea multa lumina afara.

In acest caz, se poate pune un rezistor de 5.6K catre GND.

Cu alte cuvinte pragul se calculeaza asa:

5.6K / (5.6K + 19k) = 5.6K / 24.6K = 0.2276

 

Tensiunea vazuta de intrarea ADC este de 5V * 0.2276 = 1.138V

1.138V corespunde unei valori digitale citite de ADC de: (1.138V * 1023) / 5V =~ 233

 

Prin urmare se poate modifica LDR_THRESHOLD din 512 in 233, se recompileaza proiectul si s-a rezolvat situatia.

 

O alta varianta ar fi ca pe pinul 3 al uC-ului sa punem un potentiometru semireglabil din care sa se poata regla valoarea LDR_THRESHOLD intre 0 si 1024, efectiv avand posibilitatea de a regla declansarea pentru oricare moment al zilei (cu o anume granularitate data de rezolutia limitata a ADC-ului).

 

Care controller il veti utiliza in continuare? Si care varianta este preferata: cea cu valoare prag fixa in program sau cea cu un prag reglabil cu potentiometru?

 

LE: O alta varianta ar fi sa lungesc timpul (cele 50us) de achizitie al ADC-ului permitand folosirea si a unui rezistor de 19K catre GND...

 

LLE: Ai atasata o varianta de proiect care se foloseste de 12F675, pe pinul 3 ai un potentiometru din care reglezi pragul de pornire. Practic, cand vine momentul din zi cand vrei sa mearga montajul, rotesti de pot-ul de pe pinul 3 pana cand incepe sa functioneze.

/*
 * File:   main.c
 * Author: mars01 on http://www.elforum.ro
 *
 * Created on August 20, 2017, 1:08 AM
 * Datasheet PIC12F675: http://ww1.microchip.com/downloads/en/devicedoc/41190c.pdf
 */

// PIC12F675 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = ON        // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF      // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#define _XTAL_FREQ  4000000

#define INPUT   1
#define OUTPUT  0

#define GOARNA          GP1         // pinul 6
#define GOARNA_DIR      TRISIO1     
#define FAR_AUTO        GP2         // pinul 5
#define FAR_AUTO_DIR    TRISIO2

// LDR-ul se conecteaza pe pinul 7 adica AN0
#define LDR_DIR         TRISIO0
#define PRAG_DIR        TRISIO4

enum {
    OFF = 0,
    ON = 1
};

void HW_init(void) {
    
    
    // WDT init
    PSA = 1;    // Prescaler asigned to the watchdog
    PS2 = 1;    // Prescaler set to 1:16 so the WDT timeout period is 18ms * 16 = 288ms
    PS1 = 0;
    PS0 = 0;
    CLRWDT();   // reseteaza timer-ul watchdog
    
    LDR_DIR = INPUT;
    PRAG_DIR = INPUT;
    
    ANS0 = 1;       // GP0 este pin analog/ADC
    ANS1 = 0;       // GP1 este pin digital
    ANS2 = 0;       // GP2 este pin digital
    ANS3 = 1;       // GP3 este pin analog/ADC
    
    CMCON = 7;       // Comparator OFF
    GOARNA = OFF;   
    FAR_AUTO = OFF;

    GOARNA_DIR = OUTPUT;
    FAR_AUTO_DIR = OUTPUT;
    
    // ADC init     
    ADFM = 1;   // rezultatul ADC este aliniat la dreapta
    VCFG = 0;   // referinta este VDD

    ADCS2 = 1;  // ADCS2 = 1; ADCS1 = 1; ADCS0 = 1; => se foloseste Frc 
    ADCS1 = 1;
    ADCS0 = 1;
    ADON = 1;   // Enable ADC
        
}

unsigned int ADC_read(unsigned int channel){
    
    unsigned int result;
    CLRWDT();
    
    switch (channel) {
        case 0:
            CHS1 = 0;   // selectam canalul 0 al ADC adica AN0 adica pinul 7
            CHS0 = 0;
            break;
        case 1:
            CHS1 = 0;   // selectam canalul 1 al ADC adica AN1 adica pinul 6
            CHS0 = 1;
            break;
        case 2:
            CHS1 = 1;   // selectam canalul 2 al ADC adica AN2 adica pinul 5
            CHS0 = 0;
            break;
        case 3:
            CHS1 = 1;   // selectam canalul 3 al ADC adica AN3 adica pinul 3
            CHS0 = 1;
            break;
            
    }
    
    // cat timp ADC-ul este ocupat, asteapta sa devina disponibil
    while (GO_DONE) {
        __nop();    // stai degeaba; este introdus pt ca sa nu optimizeze compilatorul  
    }
    
    // fa un delay de 50us (>> 20us - minimum acquisition time)
    __delay_us(50);
    
    GO_DONE = 1;    // start conversion
    
    // wait for the end of the conversion
    while (GO_DONE) {
        __nop();
    }
    result = ADRESH;
    result = ((result << 8) | ADRESL) & 0x3FF;
    return result;    
}

void main() {
    unsigned int i,j;    // counters
    unsigned int LDR_threshold;
      
    HW_init();
    
    LDR_threshold = ADC_read(3);
    
    while (1) {
        if (ADC_read(0) >= LDR_threshold) {
        
            /* delay de 3secunde care sa actioneze ca protectie impotriva 
             * iluminarilor accidentale in timpul noptii cum ar fi lumina unei 
             * lanterne sau un fulger etc
            */
            for (i = 30; i > 0; i--){
                CLRWDT();
                __delay_ms(100);
            }
            
            // daca dupa 3 secunde senzorul tot indica ca este iluminat atunci
            if (ADC_read(0) >= LDR_threshold){
                while (ADC_read(0) >= LDR_threshold){
                    __nop();    // stai degeaba cat timp este lumina afara
                }
                
            }
        }
        
        
        CLRWDT();
        GOARNA = ON;
        FAR_AUTO = ON;

        i = 600;
        j = 0;
        while (i--){
            __delay_ms(100);
            CLRWDT();
            if (j > 50) {
                j = 0;
                FAR_AUTO = !FAR_AUTO;
            }
            else {
                j++;
            }
        }

        // opreste alarma audio-vizuala
        GOARNA = OFF;
        FAR_AUTO = OFF;

        // delay 3000 * 100ms = 300000ms = 300s = 5minute
        i = 3000;
        while (i--){
            CLRWDT();
            __delay_ms(100);
        }
    }
    
    
}

Alarma_animale.X.rar

Editat de mars01
Link spre comentariu

De fapt, rezistenta fotorezistorului creste la intuneric si scade la lumina.

Dar partea de detectie a luminii o rezolvasem cat de cat cu acel semireglabil. Oricum solutia dvs e mai ok si o voi adopta. Am incarcat in 12F683 programul, dar se comporta putin ciudat.

Descriere: Alimentez dispozitivul, iar daca tensiunea pe pinul de detectie este peste 2,5v nu se activeaza nimic. Pana aici e bine. Cum scade sub 2,5v, nu cred ca dureaza 3 secunde, cum este scris in soft, activeaza ambele iesiri. Si asta e bine. Cea cu 5 secunde on 5 secunde off timp de un minut merge ok, face si pauza mare (6 minute in loc ds 5, dar nu-i bai). In schimb cealalta, care trebuie sa stea 1 minut on si 5 minute off, odata activata nu se mai dezactiveaza decat daca tai alimentarea montajului.

Nu inteleg de ce, am zis ca nu scriu pana nu probez si pe 675, dar inca nu mi-a ajuns coletul. Voi reface oricum cablajul pentru varianta cu semireglabil propusa de dvs.

Si inca o nelamurire: Cum a fost gandita intarzaierea cu cele 3 secunde? De exemplu sa zicem ca modulul este cu cele doua iesiri in secventa on. Se face lumina, tensiunea creste peste 2,5v mai mult de 3 secunde. Ce trebuie sa faca modulul? Sa intrerupa imediat rularea programului la implinirea celor 3 secunde, adica sa faca off cele doua iesiri, sau sa duca secventa de un minut la capat si atunci stie el ca s-a facut lumina si nu mai porneste alta pana nu se face intuneric? La modulul meu daca simulez lumina, tensiunea pe pinul de lumina la 5v de exemplu nu opreste programul, ci il face pe tot pana la capat. Daca mentin lumina peste 2,5v mult timp, poate minute, programul odata oprit nu se mai porneste. Decat iesirea pentru un minut nu se opreste niciodata.

L.E. Softul pus in microcontroler este penultimul, pana sa implementati imbunatatirea cu semireglabilul.

Editat de Marius84
Link spre comentariu

Functionarea programului are loc in modul urmator.

 

Cum nu ati mentionat ce se intampla dupa secventa de 1minut ON urmata de 5minute OFF am tras concluzia ca aceasta secventa se repeta la infinit, cat timp controllerul este pornit si este intuneric afara. Asa ca uC-ul aceasta face, pentru ca aceasta am programat.

 

Intotdeauna, verificarea daca este zi sau noapte se face inainte de inceputul secventei 1min ON / 5min OFF. Daca se face lumina in timpul acestei secvente, se executa secventa curenta pana la capat si abia apoi se sisteaza functionarea pana cand se va face noapte din nou.

 

Acele 3 secunde de care am vorbit sunt doar pentru a ne asigura ca starea de zi este o stare ferma, constanta, si nu este o pacaleala generata de un fulger sau farul unei masini care trece, etc. Cu alte cuvinte, cele 3secunde sunt active doar cand se face decizia daca este zi sau noapte. Altfel spus, daca pe timpul noptii apare o lumina brusca cu durata mai mica de 3secunde, efectul va fi ca cele 5minute de OFF din secventa iesirilor, vor fi de fapt 5minute si 3secunde de OFF.

 

Daca apare o lumina brusca cu durata mai mare de 3secunde, programul intra intr-o bucla in care nu face nimic, doar asteapta sa se faca noapte din nou, iesirile (goarna si far) fiind ambele OFF pe tot timpul acestei asteptari.

 

Nu inteleg insa ce vreti sa spuneti cu:

Decat iesirea pentru un minut nu se opreste niciodata.

Editat de mars01
Link spre comentariu

Este super bine cum ati inteles, sa se repete totul pana cand se face lumina afara. Eu nu pricepusem fineturile. Iesirea pentru goarna, care ar trebui sa fie un minut on si 5 minute off, odata ce se porneste ramane tot timpul on. Nu face secventele de off, cele de 5 minute. As exclude probleme hardware...

Editat de Marius84
Link spre comentariu

Incercati cu fisierul .HEX atasat.

Am inversat GP2 cu GP1 astfel incat sa ne dam seama daca este o problema de configurare a pinilor (desi nu vad unde) sau prb HW.

Ar trebui acum ca goarna sa isi schimbe starea la fiecare 5 secunde iar farul odata pornit sa ramana pornit conform comportamentului raportat.

Stergeti extensia .TXT a fisierului, forumul nu permite atasarea directa a fisierelor .HEX asa ca am adaugat extensia .TXT la fisier.

Alarma_animale_12F683.X.production.hex.txt

Link spre comentariu

Am pus noul hex, cu acesta goarna isi schimba starea la fiecare 5 secunde, dar cealalta iesire nu se mai activeaza deloc, ramane tot timpul off, fata de celalalt hex unde ramane tot timpul on...

Link spre comentariu

Ciudat, nu am facut decat sa schimb pinii intre ei, in rest softul a ramas la fel.

Verific, poate a mai ramas vreun periferic ceva pe acel pin, care interfereaza si pinul nu este pur digital asa cum trebuie sa fie.

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări