pic18f analog comparator problem


Closed Thread
Results 1 to 5 of 5
  1. #1

    Default pic18f analog comparator problem

    Hello
    I'm writing for the first time on this kind of a forum. I've read many posts that helped me, so I decided to ask something. I saw that people here have the know how

    I'm working at an interesting project, a data acquisition system, which acquires 32 analog lines when a trigger has been received, and calculates the time between the rising edge and falling edge of each analog line. So I decided to use PIC18F4550 because has built in analog comparators, 48MHz and USB communication (I'm using it to transmit acquired data to the PC).

    As a short description of my hardware implementation, I used 2 analog multiplexer's (ADG406) each with 16 analog inputs and 1 analog output. I'm addressing the mux via PIC18F4550 through PORTB (RB5 -> enable Mux2, RB4 -> enable Mux1, RB3 -> RB0 selecting each line of Mux1 and Mux2). The analog output of Mux1 is connected to analog comparator1 input of uC (PORTA.RA0) and the Mux2 analog output is connected to analog comparator2 input of uC (PORTA.RA1).
    I'm configuring the analog comparators to have a common internal reference.
    I have the trigger connected to the RD4 pin.


    I wrote the code for PIC18F4550 and in order to test it ( I don't have 32 analog lines) I build up another uC (PIC18F4620) to simulate the signals (but digital).
    A short description of my code:
    1. I'm waiting for the trigger (signal on PORTB.RB4, 200 ms duration)
    2. If the trigger received, start timer0 to count 94us
    3. I'm selecting each mux line
    4. If RA0>Vref or RA1>Vref or RA0<Vref or RA1<Vref (any change of either comparator) and interrupt is generated
    5. If comparator interrupt is generated, I'm checking all the comparators outputs to see any change and if so, I'm saving the current value of the tmr0Counter (one increment of tmr0Counter means 94us)
    6. If 94us time has past the program enters in the timer0 interrupt routine and increments the tmr0Counter
    7. The process starts all over again from step 3
    Here is my source code:

    #include<p18f4550.h>
    #include<timers.h>
    #include<stdio.h>
    #include<ancomp.h>
    /** V A R I A B L E S ************************************************** ******/
    #pragma udata

    unsigned int x;
    unsigned int var;
    char var1,var2;
    unsigned int tmr0Counter=0;
    unsigned char flag=0;
    unsigned int i=1;
    unsigned int tablouTimp [32][2];/*={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0};*/
    unsigned int time[32];

    /** P R I V A T E P R O T O T Y P E S ***************************************/
    //static void InitializeSystem(void);
    void BIOS(void); //function that initializes registers BAsic Input Ouput Settings
    void USBTasks(void);
    void _high_ISR(void);
    void init_Timer(void);
    void set_Timer(unsigned int);
    void muxLineSelect(void);
    void calculateTime(void);

    /** V E C T O R R E M A P P I N G *******************************************/

    extern void _startup (void); // See c018i.c in your C18 compiler dir
    #pragma code _RESET_INTERRUPT_VECTOR = 0x000800
    void _reset (void)
    {
    _asm goto _startup _endasm
    }
    #pragma code

    #pragma code _HIGH_INTERRUPT_VECTOR = 0x08
    void _HIGH_INTERRUPT_VECTOR (void)
    {
    _asm
    goto _high_ISR
    _endasm
    }

    #pragma code
    #pragma interrupt _high_ISR
    void _high_ISR(void) {

    if (INTCONbits.TMR0IF==1) { // timer 0 interrupt has been received
    INTCONbits.TMR0IE=0; // disable timer0 interrupts
    // INTCONbits.PEIE=0; //disable peripheral interrupts
    PIE2bits.CMIE=0; //disable analog comparators interrupts
    INTCONbits.TMR0IF=0; //reset timer0 interrupt flag

    flag=1;
    tmr0Counter++;

    INTCONbits.TMR0IE=1; //enable timer0 interrupts
    PIE2bits.CMIE=1; //enable analog comparators interrupts
    INTCONbits.PEIE=1; //enable peripheral interrupts
    init_Timer(); //start timer0

    }

    if (PIR2bits.CMIF==1) { //comparator interrupt has been received

    PIE2bits.CMIE=0; //disable analog comparators interrupts
    PIR2bits.CMIF=0; //reset comparator interrupt flag


    if (CMCONbits.C1OUT==1) { //comparator1's input (RA0)> Vref

    tablouTimp[i][0]=tmr0Counter; //save the value in a array
    }
    if (CMCONbits.C1OUT==0) { //comparator1's input (RA0) <Vref


    tablouTimp[i][1]=varx; //save the value in a array

    }

    if (CMCONbits.C2OUT==1) { //RA1 (comp2 input) > Vref

    tablouTimp[i+16][0]=varx; //save the value in a array
    }
    if (CMCONbits.C2OUT==0) { //RA1<Vref
    PORTCbits.RC1=1; //toggle this pin to see the behaviour on the osciloscope
    tablouTimp[i+16][1]=varx; //save value in a array
    PORTCbits.RC1=0; //toggle this pin to see the behaviour on the osciloscope
    }

    PIE2bits.CMIE=1; //enable comparator interrupts

    }//end if interrupt comparator


    }

    #pragma code _LOW_INTERRUPT_VECTOR = 0x000818
    void _low_ISR (void)
    {
    ;
    }
    #pragma code

    /** D E C L A R A T I O N S **************************************************/
    #pragma code


    /************************************************** ****************************
    * Function: void main(void)
    *
    * PreCondition: None
    *
    * Input: None
    *
    * Output: None
    *
    * Side Effects: None
    *
    * Overview: Main program entry point.
    *
    * Note: None
    ************************************************** ***************************/
    void main(void) {

    BIOS(); //initializing uC
    set_Timer(94);//setting timer to 94us
    flag=1;

    init_Timer(); //starting timer0
    if (PORTDbits.RD4==1){ // if the trigger received via this pin
    tmr0Counter=0; //reset the tmr0 counter
    while(1){



    muxLineSelect(); //selecting the mux lines
    while(flag==0); //waiting for timer0 to finish

    if (tmr0Counter==4000) { //forced stop of the acquisition

    CloseTimer0(); //stoping timer0
    // Close_ancomp();
    calculateTime(); //calculating the time
    }



    }//end while 1

    }

    }
    void init_Timer(void) { //setting timer0 with interrupt enable, 16 bit resolution, with the prescaler 1:64
    OpenTimer0(TIMER_INT_ON&T0_16BIT & T0_SOURCE_INT & T0_PS_1_64);
    WriteTimer0(var); //writing var value in the TMR0 register

    }
    void set_Timer(unsigned int micro_sec){ //calculating the value for TMR0 register


    x=micro_sec/6;
    var=65536-x;


    //var1=var>>8;
    //var2=var;

    }
    void muxLineSelect(void) { //this function selects the mux lines by adressing each line of the mux via pins RD3->RD0
    char mask;

    mask=0b00110000; //enable both muxes (RD5 en mux2, RD4 en mux 1)
    PORTB=mask;

    /*for (i=0;i<16;i++){
    PORTB=PORTB|i; //selecting lines from 0-15
    }*/

    //************test code -> only 2 lines selected *************//
    i=15; //line 15 select
    PORTB=mask|15;
    i=16; // line 16 select
    PORTB=mask|16

    flag=0;


    }

    void BIOS(void) { //Basic Input Output Settings
    int i;

    INTCON = 0xE0; //init interrupt vector
    TRISB=0; //setting port B as output
    TRISC=0; //setting port C as output
    TRISD=0b00010000;
    TRISA=0b00000011; //setting RA0 and RA1 as inputs
    //setting analog comparator register with 2 analog comparators, output inverted, comparator's have the same internal reference, and comp interrupt enable
    Open_ancomp(COMP_1_2_OP_INV& COMP_INT_REF_SAME_IP & COMP_INT_EN);
    CVRCON=0b11001000; //setting up comparator refference voltage 2.8125V

    for (i=0;i<32;i++) { //initializing array with 0
    tablouTimp[i][0]=0;
    tablouTimp[i][1]=0;
    }

    }

    void calculateTime(void) {
    char k;

    for (k=0;k<32;k++){ // calculates time
    time[k]=(tablouTimp[k][1]-tablouTimp[k][0])*0.094;
    }
    varx=0;

    }
    So, my big problem is : if I have more than one line selected at the from the multiplexor, the program saves the tmr0Counter value inapropriate. To debug this, I used only mux1 (clearing RB5 bit) which is connected to Comparator1 and selecting only 2 mux lines. I put a bit to toggle in comparator2 interrupt case (CMCONbits.C2OUT==0) and surprise, my bit is toggleing even if I don't have any significant signal to comparator2 input ( I checked with the osciloscope and I saw only a small noise). And even strange, the program enters the comparator2 interrupt routine every time I have a change in comparator1 output (on rising and on falling edge). And even more strange, if I use only 1 line from the Mux1, the program works very well, the signal comming to the comparator1 is sensed very precise and the tmr0Counter value is saved as expected.

    Please help me with this problem.

    David

  2. #2
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    947


    Did you find this post helpful? Yes | No

    Default

    David

    Since you're new here, welcome. However, if you noticed, this forum only does PicBasicPro. You have here Microchip PIC-C18 code. It's not really the right place to post this. You could have posted it in 'off-topic' perhaps.

    Having said that, I suppose, you're having a problem when the mux lines switch. That could be triggering the comparator interrupt. If you're using a PICKIT2, I think you can debug the problem easily enough.

    I could suggest you
    momentarily disable the comparators
    do a mux select operation
    clear comparator flags
    enable the comparators

    I'm not really sure if this will fix your issues, but it's worth a try.

    Jerson

  3. #3
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default

    You will need to check your comparator setting, and also double check there's no conflict with any ADC channels multiplexed on the same pins as your comparator.

    On 18F, you want to write to LAT register and read from PORT register.

    Bad news, here it's Melabs PicBasic Pro forum. Your question qill be better aswered on MicroChip forum.
    http://www.microchip.com/forums/Default.aspx?
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  4. #4


    Did you find this post helpful? Yes | No

    Default Thanks

    Thank you, I will check on that tomorrow. I'll get back, I hope, with a positive response
    David

  5. #5


    Did you find this post helpful? Yes | No

    Default re:analog comp

    Hello again.
    I've tried what you said. Isn't working. I run my system with only 2 input signals and I detect the rising and the falling edge of the second signal correctly, but for the first signal, I detect only the rising edge in the comparator interrupt routine. I also checked the signal entering my analog comparator with the osciloscope, and it's ok.
    So, I'm a little stuck

    David

Similar Threads

  1. Pic getting part power from Analog Port
    By ShaneMichael in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 22nd April 2009, 11:34
  2. analog and digital
    By lerameur in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 10th June 2008, 03:40
  3. Selection of analog ports
    By enauman in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 24th December 2006, 04:56
  4. Many Analog Inputs
    By Ioannis in forum mel PIC BASIC Pro
    Replies: 11
    Last Post: - 10th July 2006, 09:15
  5. analog inputs on 16F716
    By schwinn_rider in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 6th October 2005, 05:07

Members who have read this thread : 1

You do not have permission to view the list of names.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts