• AVR Freaks

Hot!I'm not getting Timer 5 interrupt on PIC16F18346

Author
arabed
New Member
  • Total Posts : 13
  • Reward points : 0
  • Joined: 2009/01/31 14:30:46
  • Location: 0
  • Status: offline
2020/10/29 18:49:59 (permalink)
0

I'm not getting Timer 5 interrupt on PIC16F18346

I'm not getting Timer 5 interrupt on PIC16F18346
Timer 5 gate needs to be routed to input RA0 there are pulses coming in  T5GPPSbits.T5GPPS = 0x00;
Timer 5 gate is active when low T5GPOL = 0;
Timer 5 counters low and high are initialized to zero TMR5L=TMR5H=0;
Timer 5 config. T5CON = 0b11100100; Timer5 clock LFINTOSC, Prescale 1:4, Do not sync external clk input
Timer is turned on TMR5ON = 1;
Timer gate is on TMR5GE = 1;
Timer 5 overflow enabled TMR5IE = 1;

I expect to see an interrupt when timer5 overflows, but, it does not happen.
 
Any hints will help! Many thanks!
#1

18 Replies Related Threads

    ric
    Super Member
    • Total Posts : 28943
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/29 19:45:16 (permalink)
    +1 (3)
    It would help to make a standalone app that only tests this, so you could show us all the code. I assume you do not have the WDT enabled, which could cause a reset before the timer rolled over.
    Does it work on any other timer?

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    razmiggee
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2020/10/07 14:59:06
    • Location: 0
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 09:50:09 (permalink)
    0
    I have the same problem with the timer!
    #3
    razmiggee
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2020/10/07 14:59:06
    • Location: 0
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 10:16:46 (permalink)
    +1 (1)
    I have tried with timer 1 , as well. Still no interrupt. I will post the code momentarily.
    Thank you.
     
    Razmig
    #4
    razmiggee
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2020/10/07 14:59:06
    • Location: 0
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 10:34:25 (permalink)
    0 (2)
    timer 5 interrupt issue
    PORTION OF MAIN ROUTINE:
    void main(void)
    {
        IOCIE = OFF;
        sys_init();
        putsUART ((char *)"READY\n\r");              // Send message.
        putsUART ((char *)"Hybrid Systems\n\r");     //Send message.
        delay_ctr = 700;
        while(delay_ctr!=0);
    //---------------------------two circuit detection----------------------------//
        IOCAN   = 0b00000000;       //disable RA0 and RA1 negative zero crossing
        if (two_circuit() != 0)
        {
            putsUART ((char *)"TWO CIRCUIT DETECTED\n\r");              // Send message.        
        }
        else
        {
            putsUART ((char *)"ONE CIRCUIT DETECTED\n\r");              // Send message.        
        }
        max_power = US_POWER;
        first_qdr = US_1qdr;
        third_qdr = US_3qdr;
        min_power = US_min_pwr;
    //-------------------------240VAC/50Hz detection------------------------------//
        if (Europe() != 0)
        {
    //-------------------------power level for all VACmotors at 50%---------------//
            
            putsUART ((char *)"EURO POWER\n\r");              // Send message.        
            max_power = EU_POWER;
            first_qdr = EU_1qdr;
            third_qdr = EU_3qdr;
            min_power = EU_min_pwr;
        }
        else
            putsUART ((char *)"US POWER\n\r");              // Send message.        
            
        vac1_power  = max_power;
        blow1_power = max_power;
        vac2_power  = max_power;
        blow2_power = max_power;
        IOCAN = 0b00000011;         //enable RA0 and RA1 negative zero crossing
        IOCAP = 0b00000000;         //disable RA0 and RA1 positive zero crossing
    //    IOCIE = ON;
        IOCIE = OFF;
        vac1 = 1;
        power1 = 20;
        while(1)
        {
            
            TMR5IE = ON;
            TMR5L  = 255 - (first_qdr - power1 + 2);
            TMR5H  = 0xFF;
            TMR5ON = ON;
            vac_mtr1 = RUNNING;
            counter1 = 0;
            IOCAF0    = OFF;        
            while(counter1 < 1);
         }
     
    timer 5 interrupt service
       
        if(TMR5IF)
        {
            TMR5IF = OFF;
            TMR5IE = OFF;
            TMR5ON = OFF;
            IOCIE = OFF;
            if (counter1 == 0)
            {
                VACMTR1 = MTRON;
                for (i =0; i<100; i++);
                VACMTR1 = MTROFF;
                counter1++;
                TMR5L  = 255 - ((third_qdr - power1) - (first_qdr - power1) - 20);
                TMR5H  = 0xFF;
                TMR5ON = ON;
                TMR5IE = ON;
            }
            else if(counter1 == 1)
            {
                VACMTR1 = MTRON;
                for (i =0; i<100; i++);
                VACMTR1 = MTROFF;    
            }
            //IOCIE = ON;
            return;
        }


    portion of initialization to indicate timer5 configuration
     
    /*-----------------------------------------------------------------*/    
        SWDTEN  = OFF;              //disable watchdog
        TMR0L   = 0xF0;             //10mS timer0 interrupt counts
        TMR0H   = 0xB2;             //timer0 in 16bit mode
        INTCON  = 0b11000000;        //GIE,PEIE
        PIE0    = 0b00100000;       //TMR0IE
        PIE1    = 0b00100000;       //RCIE
        PIE2    = 0b00000000;
        PIE3    = 0b00000000;
        PIE4    = 0b00010000;       //TMR5IE
        T5CON   = 0b11100100;
        T3CON   = 0b11100100;
        TMR5GE  = OFF;              //timer1 always counting
        TMR3GE  = OFF;


    #5
    upand_at_them
    Super Member
    • Total Posts : 739
    • Reward points : 0
    • Joined: 2005/05/16 07:02:38
    • Location: Pennsylvania
    • Status: online
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 13:13:42 (permalink)
    -1 (1)
    if(TMR5IF)

     
    And how do you expect your program to ever reach this line?
    #6
    1and0
    Access is Denied
    • Total Posts : 11501
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 14:43:30 (permalink)
    0
    upand_at_them
    if(TMR5IF)

    And how do you expect your program to ever reach this line?

    I think OP just posted only a portion of his ISR ;)  which really is not recommended.  He did the same for his initialization.
    #7
    ric
    Super Member
    • Total Posts : 28943
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 14:54:21 (permalink)
    +1 (1)
    Waste of time only posting bits of the code.
    Please post all of it, or as I already asked, a complete cut down example that shows the problem.
    (n.b. "all of the code" includes the CONFIG bit settings)

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #8
    Aussie Susan
    Super Member
    • Total Posts : 3787
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 18:19:19 (permalink)
    0
    Also how do you know that the ISR is not called?
    There are a number of things with your code that probably are not doing what you think they are but we really need to know how you are testing this to help further.
    Susan 
    #9
    razmiggee
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2020/10/07 14:59:06
    • Location: 0
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 19:29:32 (permalink)
    -2 (2)
    Allow me to explain the intended task.
    This aparatus is using a one cord or a two cord AC for system power. The zero crossing circuit delivers on pins RA0 and RA1 the pulses for the processor to track and based on timers 5 and 3 perform phase angle control of the AC cycles for soft start and reduced power when in europe. Blue tooth is an option that is being added for later implementation in production units. I have turned off all level change related interrupts and have only timer0 and RX interrupt enabled. I am trying to get the timer5 work based on predetermined timer loaded values to generate the pulse on VACMTR1 output pin. I dont have any action on timer5. I tried timer3 and timer1 same result. There is something fundamentally missing here. I cant put my finger on it. Following is the (.C) listing I have followed my post with the (.h) so you have a complete picture of what I am dealing with.
    Thank you.
     
    /************************************************/
    /*        H Y B R I D   S Y S T E M S                */
    /*        627 Ruberta Ave.,                         */
    /*        Glendale, Ca  91201                        */
    /*        (818) 247-6922                          */
    /*        This program is developed for            */
    /*         Vacuum System                            */
    /*                                                */
    /*        [C] This software is proprietary of     */
    /*        Hybrid Systems and may not be             */
    /*        distributed without written consent of     */
    /*        the officers of Hybrid Systems.            */
    /*                                                */
    /*        hybmrk18346.c                                */
    /*        DATE: 9/17/2020                            */
    /*        Device:16F690                            */
    /*        Checksum    0x????                      */
    /*      DATE: 09/05/2020                        */
    /*      added STDLIB for serial communication   */
    /*      added BLE complete control on CLEARS    */
    /*      switch status are displayed in BLE and  */
    /*      non BLE modes by monitoring the serial  */
    /*      communications port at 115.2k baud no   */
    /*      handshake used.                         */
    /*      Microchip controller changes to         */
    /*      PIC16F18346 09/17/2020                  */
    #define revision     17
    /************************************************/
        
    /*        Rev:    Date:        By:        Comments:
            ----    --------    ---        ----------------------------------
     *      1                   LK
     *      2                   LK
     *      3       09/05/20    DG      BLE additions
     *      4       09/17/20    DG      controller change PIC16F18346
     *      5       10/12/20    DG      implemented soft start
     *      6       10/15/20    DG      soft start executes upto 80% of the phase
     *      7       10/20/20    DG      implemented one and two circuit detections
     *      8       10/22/20    DG      IOCAN only implemented positive edge is OFF
     *      9       10/22/20    DG      5%-95% AC power control tested
     *      10      10/23/20    DG      soft-start new approach implemented
     *      11      10/24/20    DG      implemented soft-start and reduced power for all motors
     *      12                  DG      intermediate changes
     *      13                  DG      intermediate changes
     *      14      10/27/20    DG      intermediate changes
     *      15      10/28/20    DG      polling generates blinking - not good
     *      16      10/29/20    DG      timer5 and negative edge interrupts
     *      17      10/30/20    DG      timer5 testing still not getting interrupts
    */
    // PIC16F18346 Configuration Bit Settings

    // CONFIG1
    #pragma config FEXTOSC  = OFF      // FEXTOSC External Oscillator mode Selection bits (HS (crystal oscillator) above 4 MHz)
    #pragma config RSTOSC   = HFINT1   // Power-up default value for COSC bits (HFINTOSC (1MHz))
    #pragma config CLKOUTEN = OFF      // Clock Out Enable bit (CLKOUT function is disabled; I/O or oscillator function on OSC2)
    #pragma config CSWEN    = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
    #pragma config FCMEN    = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)

    // CONFIG2
    #pragma config MCLRE    = OFF      // Master Clear Enable bit (MCLR/VPP pin function is digital input; MCLR internally disabled; Weak pull-up under control of port pin's WPU control bit.)
    #pragma config PWRTE    = OFF       // Power-up Timer Enable bit (PWRT enabled)
    #pragma config WDTE     = OFF      // Watchdog Timer Enable bits (WDT disabled; SWDTEN is ignored)
    #pragma config LPBOREN  = OFF      // Low-power BOR enable bit (ULPBOR disabled)
    #pragma config BOREN    = ON       // Brown-out Reset Enable bits (Brown-out Reset enabled, SBOREN bit ignored)
    #pragma config BORV     = LOW      // Brown-out Reset Voltage selection bit (Brown-out voltage (Vbor) set to 2.45V)
    #pragma config PPS1WAY  = OFF      // PPSLOCK bit One-Way Set Enable bit (The PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle)
    #pragma config STVREN   = ON       // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a Reset)
    #pragma config DEBUG    = OFF      // Debugger enable bit (Background debugger disabled)

    // CONFIG3
    #pragma config WRT      = OFF      // User NVM self-write protection bits (Write protection off)
    #pragma config LVP      = OFF      // Low Voltage Programming OFF

    // CONFIG4
    #pragma config CP       = OFF      // User NVM Program Memory Code Protection bit (User NVM code protection disabled)
    #pragma config CPD      = OFF      // Data NVM Memory Code Protection bit (Data NVM code protection disabled)

    #include <xc.h>
    #include <stdio.h>              //08-05-2020
    #include <string.h>             //08-05-2020
    #include <stdlib.h>             //08-05-2020
    #include <pic16f18346.h>
    #include "hybmrk18346.h"


    void main(void)
    {
        IOCIE = OFF;
        sys_init();
        putsUART ((char *)"READY\n\r");              // Send message.
        putsUART ((char *)"Hybrid Systems\n\r");     //Send message.
        delay_ctr = 700;
        while(delay_ctr!=0);
    //---------------------------two circuit detection----------------------------//
        IOCAN   = 0b00000000;       //disable RA0 and RA1 negative zero crossing
        if (two_circuit() != 0)
        {
            putsUART ((char *)"TWO CIRCUIT DETECTED\n\r");              // Send message.        
        }
        else
        {
            putsUART ((char *)"ONE CIRCUIT DETECTED\n\r");              // Send message.        
        }
        max_power = US_POWER;
        first_qdr = US_1qdr;
        third_qdr = US_3qdr;
        min_power = US_min_pwr;
    //-------------------------240VAC/50Hz detection------------------------------//
        if (Europe() != 0)
        {
    //-------------------------power level for all VACmotors at 50%---------------//
            
            putsUART ((char *)"EURO POWER\n\r");              // Send message.        
            max_power = EU_POWER;
            first_qdr = EU_1qdr;
            third_qdr = EU_3qdr;
            min_power = EU_min_pwr;
        }
        else
            putsUART ((char *)"US POWER\n\r");              // Send message.        
            
        vac1_power  = max_power;
        blow1_power = max_power;
        vac2_power  = max_power;
        blow2_power = max_power;
    //    vac1_power  = 42;           //not steady good with 44
    //    blow1_power = 32;
        IOCAN = 0b00000011;         //enable RA0 and RA1 negative zero crossing
        IOCAP = 0b00000000;         //disable RA0 and RA1 positive zero crossing
    //    IOCIE = ON;
    //    IOCIE = OFF;
        vac1 = 0;
        power1 = 45;
        while(1)
        {
            
            TMR5IE = ON;
            TMR5GIE = ON;
            TMR5L  = 255 - (first_qdr - power1 + 2);
    //        TMR5L  = 0x00;
            TMR5H  = 0xFF;
            TMR5ON = ON;
    //        vac_mtr1 = RUNNING;
            counter1 = 0;
    //        IOCAF0    = OFF;        
            while(counter1 != 1)
            {
    //            sprintf(buffer,"T5L %d, T5H %d\n\r", TMR5L, TMR5H);
    //            putsUART ((char *) buffer);     // Send message.            
            }
    /*        
            if (power1 >5)
            {
                power1--;
            }
            else
            {
                power1 = 45;
            }
    */        
        }
        
    ///*-------------------phase angle firing  PWM test routine---------------------
        while (1)
        {
            vac1 = 0;
            VACMTR1 = MTROFF;
            blow1 = 0;
            BLOWMTR1 = MTROFF;
            putsUART ((char *)"MOTOR OFF\n\r");              // Send message.
            delay_ctr = 300;
            while(delay_ctr!=0);
            putsUART ((char *)"MOTOR ON\n\r");              // Send message.
            vacmtr1();
            blowmtr1();
    //        delay_ctr = 300;
    //        while(delay_ctr!=0);
    r1:
            run_vacs();
            goto r1;
    //        if (vac1_power > min_power)
    //        {
    //            vac1_power = vac1_power - min_power;
    //            if (vac1_power < min_power) vac1_power = min_power;
    //        }
    //        else
    //            vac1_power = max_power;
    //        putsUART ((char *)"BLOW1 SOFT START BEGIN\n\r");              // Send message.
    //        blowmtr1();
    //        putsUART ((char *)"BLOW1 SOFT START END\n\r");              // Send message.
    //        delay_ctr = 500;
    //        while(delay_ctr!=0);
    //        putsUART ((char *)"VAC2 SOFT START BEGIN\n\r");              // Send message.
    //        vacmtr2();
    //        putsUART ((char *)"VAC2 SOFT START END\n\r");              // Send message.
    //        delay_ctr = 500;
    //        while(delay_ctr!=0);
    //        putsUART ((char *)"BLOW2 SOFT START BEGIN\n\r");              // Send message.
    //        blowmtr2();
    //        putsUART ((char *)"BLOW2 SOFT START END\n\r");              // Send message.
    //        delay_ctr = 500;
    //        while(delay_ctr!=0);
    //        VACMTR1 = MTROFF;
    //        BLOWMTR1 = MTROFF;
    //        VACMTR2 = MTROFF;
    //        BLOWMTR2 = MTROFF;
    //        delay_ctr = 500;
    //        while(delay_ctr!=0);
        }
    //*/
    /*-------------------------- main loop----------------------------------------*/
        OpenUART();
        top:
        if (start_latch == ON) START_SW = ON;
        while(BLE_status == OFF)
        {        
            while((START_SW==OFF) && (PURGE_SW==OFF) && (BLE_status == OFF) )
            {
                BLE();
            }
            while(BLE_status == OFF)
            {
                if((STOP1 == ON)||(STOP2 == ON)||(PURGE_SW == ON))break;
                run_vacs();
                if(ECOMODE == ON)
                {    //chamber #1
                    VACMTR2=BLOWMTR2=MTROFF;
                    vac2=blow2=vac_mtr2=blow_mtr2= 0;
                    if((TOPLVL2 == FULL) && (BOTMLVL2 == FULL))break;
                    if(TOPLVL1 == FULL)
                    {
                        VACMTR1 = MTROFF;
                        vac1= 0;
                    }
                    if((TOPLVL1 == NOT_FULL) && (BLOWMTR1 == MTROFF))vacmtr1();//VACMTR1 = MTRON;
                    else if((BOTMLVL1 == NOT_EMPTY) && (VACMTR1 == MTROFF))blowmtr1();//BLOWMTR1 = MTRON;
                    else if(TOPLVL1 == FULL)
                    {
                        VACMTR1 = MTROFF;
                        vac1= 0;
                    }
                    else if(BOTMLVL1 == EMPTY)
                    {
                        BLOWMTR1 = MTROFF;
                        blow1= 0;
    //                    ECOMODE=2;        //1/3/20... 1 chamber and 1 cord op
                    }    
                    run_vacs();
                }    
                else if(CONT_SW == OFF)
                {        //continuous... 1/3/20 added ECOMODE=OFF
                    if(TOPLVL1 == FULL)
                    {
                        VACMTR1 = MTROFF;
                        vac1= 0;
                    }
                    if((TOPLVL1 == NOT_FULL) && (BLOWMTR1 == MTROFF) && (VACMTR2 == MTROFF))vacmtr1();//VACMTR1 = MTRON;
                    else if((BOTMLVL1 == NOT_EMPTY) && (VACMTR1 == MTROFF))blowmtr1();//BLOWMTR1 = MTRON;
                    else if(TOPLVL1 == FULL)
                    {
                        VACMTR1 = MTROFF;
                        vac1= 0;
                    }
                    else if(BOTMLVL1 == EMPTY)
                    {
                        BLOWMTR1 = MTROFF;
                        blow1= 0;
                    }
    //2/19/20                if(TOPLVL2==FULL && BOTMLVL2==EMPTY)break;
                    if(TOPLVL2 == FULL)
                    {
                        VACMTR2 = MTROFF;
                        vac2= 0;
                    }
                    if((TOPLVL2 == NOT_FULL) && (BLOWMTR2 == MTROFF) && (VACMTR1 == MTROFF))vacmtr2();//VACMTR2 = MTRON;
                    else if((BOTMLVL2 == NOT_EMPTY) && (VACMTR2 == MTROFF))blowmtr2();//BLOWMTR2 = MTRON;
                    else if(TOPLVL2 == FULL)
                    {
                        VACMTR2 = MTROFF;
                        vac2= 0;
                    }
                    else if(BOTMLVL2 == EMPTY)
                    {
                        BLOWMTR2 = MTROFF;
                        blow2= 0;
                    }
                    run_vacs();
                }    
                else if(CONT_SW == ON)
                {        //if BLOWMTR1 & BLOWMTR2 sync mode... 1/3/20 added ECOMODE=OFF
                    if(TOPLVL1 == FULL)
                    {
                        VACMTR1 = MTROFF;
                        vac1= 0;
                    }
                    if((TOPLVL1 == NOT_FULL) && (BLOWMTR1 == MTROFF) && (BLOWMTR2 == MTROFF))vacmtr1();//VACMTR1 = MTRON;
                    else if((BOTMLVL1 == NOT_EMPTY) && (VACMTR1 == MTROFF))blowmtr1();//BLOWMTR1 = MTRON;
                    else if(TOPLVL1 == FULL)
                    {
                        VACMTR1 = MTROFF;
                        vac1= 0;
                    }
                    else if(BOTMLVL1 == EMPTY)
                    {
                        BLOWMTR1 = MTROFF;
                        blow1= 0;
                    }
    //2/19/20                if(TOPLVL2==FULL && BOTMLVL2==EMPTY)break;
                    if(TOPLVL2 == FULL)
                    {
                        VACMTR2 = MTROFF;
                        vac2= 0;
                    }
                    if((TOPLVL2 == NOT_FULL) && (BLOWMTR2 == MTROFF) && (BLOWMTR1 == MTROFF))vacmtr2();//VACMTR2 = MTRON;
                    else if((BOTMLVL2 == NOT_EMPTY) && (VACMTR2 == MTROFF))blowmtr2();//BLOWMTR2 = MTRON;
                    else if(TOPLVL2 == FULL)
                    {
                        VACMTR2 = MTROFF;
                        vac2= 0;
                    }
                    else if(BOTMLVL2 == EMPTY)
                    {
                        BLOWMTR2 = MTROFF;
                        blow2= 0;
                    }
                    run_vacs();
                }
                BLE();
            }    
            VACMTR1=VACMTR2=BLOWMTR1=BLOWMTR2=MTROFF;
            vac1=vac2=blow2=blow2=vac_mtr1=vac_mtr2=blow_mtr1=blow_mtr2= 0;
            STOP2=OFF;
            while(PURGE_SW == ON)
            {
                if(ECOMODE==ON)
                {
                //    BLOWMTR1=MTRON;    //1/3/20 if ECOMODE then only 1 chamber purge
                    blowmtr1();
                    VACMTR1 = MTROFF;
                    vac1= 0;
                    BLOWMTR2=MTROFF;
                    blow2= 0;
                    run_vacs();
                }
                else
                {
                    blowmtr1();
                    blowmtr2();
                    VACMTR1=VACMTR2=MTROFF;
                    vac1= 0;
                    vac2= 0;
                    run_vacs();
                }
                BLE();
                if(BLE_status == ON)break;
            }
            if(BLE_status == ON)break;
            
            VACMTR1=VACMTR2=BLOWMTR1=BLOWMTR2=MTROFF;
            vac1=vac2=blow1=blow2= 0;
        }
    //---------------------stay here if BLE mode is activated---------------------//     
    //-------initialize all switch status from hardware to BLE soft switches------//
        START_SW_BLE = START_SW;
        PURGE_SW_BLE = PURGE_SW;
        ECOMODE_BLE  = ECOMODE;
        CONT_SW_BLE  = CONT_SW;
        Hyper_BLE    = Hyper;
        STOP1_BLE    = STOP1;
        STOP2_BLE    = STOP2;
        if (start_latch == ON) START_SW_BLE = ON;        
        while(BLE_status == ON)
        {
            while((START_SW_BLE == OFF) && (PURGE_SW_BLE == OFF) && (BLE_status == ON))
            {
                BLE();
            }
            while(BLE_status == ON)
            {
    //            if(PURGE_SW)break;
    //            if(TOPLVL1==FULL && BOTMLVL1==EMPTY)break;
                if((STOP1_BLE == ON)||(STOP2_BLE == ON)||(PURGE_SW_BLE == ON))break;
                if(ECOMODE_BLE == ON)
                {    //chamber #1
                    VACMTR2=BLOWMTR2=MTROFF;
                    if((TOPLVL2 == FULL) && (BOTMLVL2 == FULL))break;
                    if(TOPLVL1 == FULL)VACMTR1 = MTROFF;
                    if((TOPLVL1 == NOT_FULL) && (BLOWMTR1 == MTROFF))VACMTR1 = MTRON;
                    else if((BOTMLVL1 == NOT_EMPTY) && (VACMTR1 == MTROFF))BLOWMTR1 = MTRON;
                    else if(TOPLVL1 == FULL)VACMTR1 = MTROFF;
                    else if(BOTMLVL1 == EMPTY)
                    {
                        BLOWMTR1 = MTROFF;
    //                    ECOMODE=2;        //1/3/20... 1 chamber and 1 cord op
                    }    
                }    
                else if(CONT_SW_BLE == OFF){        //continuous... 1/3/20 added ECOMODE=OFF
                    if(TOPLVL1 == FULL)VACMTR1 = MTROFF;
                    if((TOPLVL1 == NOT_FULL) && (BLOWMTR1 == MTROFF) && (VACMTR2 == MTROFF))VACMTR1 = MTRON;
                    else if((BOTMLVL1 == NOT_EMPTY) && (VACMTR1 == MTROFF))BLOWMTR1 = MTRON;
                    else if(TOPLVL1 == FULL)VACMTR1 = MTROFF;
                    else if(BOTMLVL1 == EMPTY)BLOWMTR1 = MTROFF;
    //2/19/20                if(TOPLVL2==FULL && BOTMLVL2==EMPTY)break;
                    if(TOPLVL2 == FULL)VACMTR2 = MTROFF;    
                    if((TOPLVL2 == NOT_FULL) && (BLOWMTR2 == MTROFF) && (VACMTR1 == MTROFF))VACMTR2 = MTRON;
                    else if((BOTMLVL2 == NOT_EMPTY) && (VACMTR2 == MTROFF))BLOWMTR2 = MTRON;
                    else if(TOPLVL2 == FULL)VACMTR2 = MTROFF;
                    else if(BOTMLVL2 == EMPTY)BLOWMTR2 = MTROFF;
                }    
                else if(CONT_SW_BLE == ON){        //if BLOWMTR1 & BLOWMTR2 sync mode... 1/3/20 added ECOMODE=OFF
                    if(TOPLVL1 == FULL)VACMTR1 = MTROFF;
                    if((TOPLVL1 == NOT_FULL) && (BLOWMTR1 == MTROFF) && (BLOWMTR2 == MTROFF))VACMTR1 = MTRON;
                    else if((BOTMLVL1 == NOT_EMPTY) && (VACMTR1 == MTROFF))BLOWMTR1 = MTRON;
                    else if(TOPLVL1 == FULL)VACMTR1 = MTROFF;
                    else if(BOTMLVL1 == EMPTY)BLOWMTR1 = MTROFF;
    //2/19/20                if(TOPLVL2==FULL && BOTMLVL2==EMPTY)break;
                    if(TOPLVL2 == FULL)VACMTR2 = MTROFF;
                    if((TOPLVL2 == NOT_FULL) && (BLOWMTR2 == MTROFF) && (BLOWMTR1 == MTROFF))VACMTR2 = MTRON;
                    else if((BOTMLVL2 == NOT_EMPTY) && (VACMTR2 == MTROFF))BLOWMTR2 = MTRON;
                    else if(TOPLVL2 == FULL)VACMTR2 = MTROFF;
                    else if(BOTMLVL2 == EMPTY)BLOWMTR2 = MTROFF;
                }
                BLE();
            }
            VACMTR1=VACMTR2=BLOWMTR1=BLOWMTR2=MTROFF;
            STOP2_BLE=OFF;
            while(PURGE_SW_BLE == ON)
            {
                START_SW_BLE = OFF;
                STOP1_BLE = STOP2_BLE = OFF;
                if(ECOMODE_BLE == ON)
                {
                    BLOWMTR1 = MTRON;    //1/3/20 if ECOMODE then only 1 chamber purge
                    BLOWMTR2 = MTROFF;
                }
                else
                    BLOWMTR1=BLOWMTR2=MTRON;                
                BLE();
                if(BLE_status == OFF)break;
            }
            VACMTR1=VACMTR2=BLOWMTR1=BLOWMTR2=MTROFF;
            vac1=vac2=blow1=blow2=0;
            vac_mtr1=vac_mtr2=blow_mtr1=blow_mtr2=0;
        }
        goto top;
    }

    void run_vacs(void)
    {
        if (vac1 == 1)
        {
            while (vac_mtr1 == 0);
                VACMTR1 = MTROFF;
            if (TMR5L > (first_qdr - power1) && (counter1 < 1))
            {
                VACMTR1 = MTRON;
                counter1++;
            }
            if (TMR5L > (first_qdr - power1 + 2) && (counter1 < 2))
            {
                VACMTR1 = MTROFF;
                counter1++;
            }
            if (TMR5L > (third_qdr - power1)  && (counter1 < 3))
            {
                VACMTR1 = MTRON;
                counter1++;
            }
            if (TMR5L > (third_qdr - power1 + 2) && (counter1 < 4))     //1.3mS pulse
            {
                VACMTR1 = MTROFF;
                vac_mtr1 = 0;
                TMR5ON   = OFF;
                TMR5L    = ZERO;
                TMR5H    = ZERO;    
            }
        }
        if (blow1 == 1)
        {
            while (blow_mtr1 == 0);
                BLOWMTR1 = MTROFF;
            if (TMR5L > (first_qdr - power2) && (counter2 < 1))
            {
                BLOWMTR1 = MTRON;
                counter2++;
            }
            if (TMR5L > (first_qdr - power2 + 2) && (counter2 < 2))
            {
                BLOWMTR1 = MTROFF;
                counter2++;
            }
            if (TMR5L > (third_qdr - power2)  && (counter2 < 3))
            {
                BLOWMTR1 = MTRON;
                counter2++;
            }
            if (TMR5L > (third_qdr - power2 + 2) && (counter2 < 4))     //1.3mS pulse
            {
                BLOWMTR1 = MTROFF;
                blow_mtr1 = 0;
                TMR5ON    = OFF;
                TMR5L     = ZERO;
                TMR5H     = ZERO;    
            }
        }
    }

    void vacmtr1(void)
    {
        if ((VACMTR1 == MTROFF))
        {
            if (vac1_power < max_power)            //soft-start
            {
                vac_mtr1 = 0;
                vac1 = 1;
                IOCIE = ON;
                TMR5ON  = OFF;
                TMR5L   = ZERO;
                TMR5H   = ZERO;            
                for ( power1 = min_power; power1 < vac1_power; power1++)    //soft-start
                {
                    while(vac_mtr1 == 0);
                        VACMTR1 = MTROFF;
                    while (TMR5L < (first_qdr - power1));          
                        VACMTR1 = MTRON;
                    while (TMR5L < (first_qdr - power1) + 2);      //1.3mS pulse
                        VACMTR1 = MTROFF;
                    while (TMR5L < (third_qdr - power1));
                        VACMTR1 = MTRON;
                    while (TMR5L < (third_qdr - power1) + 2);     //1.3mS pulse
                        VACMTR1 = MTROFF;
                    TMR5ON = OFF;
                    vac_mtr1 = 0;
                    TMR5L   = ZERO;
                    TMR5H   = ZERO;                                          
                }
                power1 = vac1_power;
            }
            else                          //full power mode
            {
                VACMTR1 = MTRON;
                vac1 = 0;
            }
        }
    }
    void blowmtr1(void)
    {
        if ((BLOWMTR1 == MTROFF))
        {
            if (blow1_power < max_power)            //soft-start
            {
                blow_mtr1 = 0;
                blow1 = 1;
                IOCIE = ON;
                TMR5ON  = OFF;
                TMR5L   = ZERO;
                TMR5H   = ZERO;   
                for ( power2 = min_power; power2 < blow1_power; power2++)
                {
                    while(blow_mtr1 == 0);
                        BLOWMTR1 = MTROFF;
                    while (TMR5L < (first_qdr - power2));          
                        BLOWMTR1 = MTRON;
                    while (TMR5L < (first_qdr - power2) + 2);      //1.3mS pulse
                        BLOWMTR1 = MTROFF;
                    while (TMR5L < (third_qdr - power2));
                        BLOWMTR1 = MTRON;
                    while (TMR5L < (third_qdr - power2) + 2);     //1.3mS pulse
                        BLOWMTR1 = MTROFF;
                    TMR5ON = OFF;
                    blow_mtr1 = 0;
                    TMR5L   = ZERO;
                    TMR5H   = ZERO;                                          
                }      
                power2 = blow1_power;
            }
            else                          //full power mode
            {
                BLOWMTR1 = MTRON;
                blow1 = 0;
            }
        }
    }
    void vacmtr2(void)
    {
        if ((VACMTR2 == MTROFF) && (vac_mtr2 == 0))
        {
            vac2   = 1;
            if (vac2_power < max_power)            //soft-start
            {
                for ( power4 = min_power; power4 < vac2_power; power4++)
                {
                    delay_ctr = 1;
                    while(delay_ctr!=0);
                }   
    //            vac2 = 0;
                vac_mtr2 = RUNNING;
            }
            else                          //full power mode
            {
                VACMTR2 = MTRON;
                vac2 = 0;
            }
        }
    }
    void blowmtr2(void)
    {
        if ((BLOWMTR2 == MTROFF) && (blow_mtr2 == 0))
        {
            blow2   = 1;
            if (blow2_power < max_power)            //soft-start
            {
                for ( power3 = min_power; power3 < blow2_power; power3++)
                {
                    delay_ctr = 1;
                    while(delay_ctr!=0);
                }   
    //            blow2 = 0;
                blow_mtr2 = RUNNING;
            }
            else                          //full power mode
            {
                BLOWMTR2 = MTRON;
                blow2 = 0;
            }
        }
    }
    void __interrupt() isr(void)
    {
        GIE=0;
        PEIE=0;
        if(TMR0IF)
        {
            TMR0IF = OFF;
            TMR0IE = OFF;
    //        if((START_SW == ON) || (START_SW_BLE == ON))    //begin tracking usage time only when CLEARS is ON
            if (start_latch == ON)
            {
    /*---------------------hour , minute counts for display screen update--------*/
                 if (--tenms_min == 0)
                {
                    flag_eeprom_wr = ON;
                    tenms_min = TENMS_MIN;
                    if(++minutes == 60)
                    {
                        minutes = 0;
                        hours++;
                    }
                }
    /*---------------------------------------------------------------------------*/
            }
            --delay_ctr;                //general delay counts 10mS/count
            if(++tenms_ctr == 250)
            {     // 2.5 seconds
                tenms_ctr = 0;
                if(++qrt_ctr == 6)
                {     //6=15 sec -> 24=60sec
                    qrt_ctr=0;
                    //if(++min_ctr==60) min_ctr=0;
                    ++min_ctr;        
                }
            }
           
    //        motors_timeout();        
            debounce_inputs();

            TMR0L   = 0xF0;    //enters every 10ms with 32MHz
            TMR0H   = 0xB2;
            TMR0IE  = ON;
            return;
        }
        
        if(TMR5IF)
        {
            TMR5IF = OFF;
            TMR5IE = OFF;
            TMR5ON = OFF;
            IOCIE  = OFF;
            if (counter1 == 0)
            {
    //            for (iw =0; iw<300; iw++);
                VACMTR1 = MTRON;
                for (i =0; i<100; i++);
                VACMTR1 = MTROFF;
                counter1++;
                TMR5L  = 255 - ((third_qdr - power1) - (first_qdr - power1) - 20);
    //            TMR5L  = 0x00;
                TMR5H  = 0xFF;
                TMR5ON = ON;
                TMR5IE = ON;
            }
            else if(counter1 == 1)
            {
    //            for (iw =0; iw<500; iw++);
                counter1++;
                VACMTR1 = MTRON;
                for (i =0; i<100; i++);
                VACMTR1 = MTROFF;    
            }
            IOCIE = ON;       //10/30/20
            return;
        }

        if(RCIF)
        {
            RCIF = OFF;
            GIE  = OFF;
            PEIE = OFF;
            RCIE = OFF;
            RXdata[RXdata_index++] = RCREG;
            if((RCREG == '\r') || (RCREG == '\n'))
            {
    //            RXdata[RXdata_index] = '\0';
                display_RXdata = 1;
                RXdata_index = 0;        }
            RCIE = ON;
            return;
        }
        
        if (IOCAF0)
        {
            IOCIE   = OFF;
            IOCIF   = OFF;
            IOCAF0  = OFF;
            IOCIE   = ON;
        }
        GIE  = ON;
        PEIE = ON;
    }

    /*unsigned int analogue_chn (void)
    {
        ADON=1;
        GODONE=1;
        while(GODONE);
        atod = ADRESL + 256*ADRESH;
        if (atod < 5) atod = 5;
        return atod;
    }
    */
    unsigned char Europe(void)
    {
        unsigned char j;
        j=0;
        for (p=0; p<10; p++)
        {
            while(!IOCAF0);             //wait for first rising edge
            IOCAF0 = ZERO;
            TMR5L  = ZERO;
            TMR5ON = ON;
            while(!IOCAF0);
            IOCAF0 = ZERO;
            TMR5ON = OFF;
            if((TMR5L < 77) && (TMR5L > 65))j++;
        }
        if (j > 8)
            return 1;
        else
            return 0;
        
        return 0;
    }

    unsigned char two_circuit(void)
    {
        unsigned char j;
        j=0;
        for (p=0; p<10; p++)
        {
            while(!IOCAF0);             //wait for first rising edge
            IOCAF0 = ZERO;
            TMR5L  = ZERO;
            TMR5ON = ON;
            while(!IOCAF1);
            IOCAF1 = ZERO;
            TMR5ON = OFF;
            if(TMR5L > 40)j++;
        }
        if (j > 8)
            return 1;
        else
            return 0;
    }
    void motors_timeout(void)
    {
            if(VACMTR1 == MTRON)
            {
                if(VACMTR1_tmr == min_ctr)
                {
                    STOP2 = ON;
                    start_latch = OFF;
                }
            }
            else VACMTR1_tmr = min_ctr + MTR_ONTIME;
            if(VACMTR2 == MTRON)
            {
                if(VACMTR2_tmr == min_ctr)
                {
                    STOP2 = ON;
                    start_latch = OFF;
                }
            }
            else VACMTR2_tmr = min_ctr + MTR_ONTIME;
            if((PURGE_SW == OFF) && (BLOWMTR1 == MTRON))
            {
                if(BLOWMTR1_tmr == min_ctr)
                {
                    STOP2 = ON;
                    start_latch = OFF;
                }
            }
            else BLOWMTR1_tmr = min_ctr + MTR_ONTIME;
            if((PURGE_SW == OFF) && (BLOWMTR2 == MTRON))
            {
                if(BLOWMTR2_tmr == min_ctr)
                {
                    STOP2 = ON;
                    start_latch = OFF;
                }
            }
            else BLOWMTR2_tmr = min_ctr + MTR_ONTIME;
    }

    void debounce_inputs(void)
    {
        //level sensor inputs
        if(TOPLVL1_RAW == FULL)
        {
            i1TE=0;
            if(i1TF++>2){
                TOPLVL1 = FULL;
                i1TF=0;
            }
        }
        else
        {
            i1TF=0;
            if(i1TE++>2){
                TOPLVL1 = EMPTY;
                i1TE=0;
            }
        }
        if(BOTMLVL1_RAW == FULL)
        {
            i1BE=0;
            if(i1BF++>2){
                BOTMLVL1 = FULL;
                i1BF=0;
            }
        }
        else
        {
            i1BF=0;
            if(i1BE++>2){
                BOTMLVL1 = EMPTY;
                i1BE=0;
            }
        }
        if(TOPLVL2_RAW == FULL)
        {
            i2TE=0;
            if(i2TF++>2){
                TOPLVL2 = FULL;
                i2TF=0;
            }
        }
        else
        {
            i2TF=0;
            if(i2TE++>2){
                TOPLVL2 = EMPTY;
                i2TE=0;
            }
        }
        if(BOTMLVL2_RAW == FULL)
        {
            i2BE=0;
            if(i2BF++>2){
                BOTMLVL2 = FULL;
                i2BF=0;
            }
        }
        else
        {
            i2BF=0;
            if(i2BE++>2){
                BOTMLVL2 = EMPTY;
                i2BE=0;
            }
        }
        // mode setting switches inputs
        // add a bit that skips this if BLE is active remotely
        if (BLE_status == OFF)
        {
            if((ECOMODE_RAW == 1) && (ECOMODE == ON))
            {
                ECOMODE = OFF;
                STOP1   = ON;
                start_latch = OFF;
            }
            else if((ECOMODE_RAW == 1) && (ECOMODE == OFF)){
                ECOMODE = OFF;
                STOP1   = OFF;
            }
            else if((ECOMODE_RAW == 0) && (ECOMODE == OFF)){
                ECOMODE = ON;
                STOP1   = ON;
                start_latch = OFF;
            }
            else if((ECOMODE_RAW == 0) && (ECOMODE == ON)){
                ECOMODE = ON;
                STOP1   = OFF;
            }

            if(CONTMODE_RAW==0)
            {
                CONT_SW = ON;
                Hyper   = OFF;
            }
            else
            {
                CONT_SW = OFF;
                Hyper   = ON;
            }
            if(PURGE_SW_RAW == 0)
            {
                PURGE_SW = ON;
                START_SW = OFF;
                START_SW_BLE = OFF;
                STOP1_BLE = STOP2_BLE = OFF;
                start_latch = OFF;
            }
            else
            {
                PURGE_SW = OFF;
            }
            if(START_SW_RAW == 0)
            {
                START_SW    = ON;
                start_latch = ON;
            }
            else START_SW = OFF;                //commented put on 9/9/2020
        }

    /*    if(PURGE_SW_RAW){
            iPSWOFF=0;
            if(iPSWON++>10){
                PURGE_SW=ON;
                iPSWON=0;
            }
        }
        else{
            iPSWON=0;
            if(iPSWOFF++>10){
                PURGE_SW=OFF;
                iPSWOFF=0;
            }
        }    
        if(CONTMODERAW){
            iCSWOFF=0;
            if(iCSWON++>10){
                CONT_SW=ON;
                iCSWON=0;
            }
        }
        else{
            iCSWON=0;
            if(iCSWOFF++>10){
                CONT_SW=OFF;
                iCSWOFF=0;
            }
        }
    */
    }

    void HELP(void)
    {   
        putsUART ((char *)"--------------------------BLE ON commands------------------------\n\r");
        putsUART ((char *)"HELP  - paints this screen\n\r");
        putsUART ((char *)"EXIT  - goes back to rolling switch status\n\r");
        putsUART ((char *)"START - starts CLEARS\n\r");
        putsUART ((char *)"STOP  - stops CLEARS\n\r");
        putsUART ((char *)"PURGE - purges CLEARS continuously until STOP issued\n\r");
        putsUART ((char *)"ECO   - configures CLEARS in ECO mode 10A operation\n\r");
        putsUART ((char *)"NECO  - configures CLEARS in normal mode 20A operation\n\r");
        putsUART ((char *)"CONT  - configures CLEARS in CONTINUOUS mode 10A or 20A operation\n\r");
        putsUART ((char *)"HYP   - configures CLEARS in HYPER mode 20A operation\n\r");    
        putsUART ((char *)"PWR   - SETS MOTOR POWER XXX i.e. 050 IS 50% POWER\n\r");    
        putsUART ((char *)"----------------Below data is for display, only------------------\n\r");
        putsUART ((char *)"H:    - displays running HOURS of CLEARS machine\n\r");
        putsUART ((char *)"M:    - displays running MINUTES of CLEARS machine\n\r");
        putsUART ((char *)"Gal:  - displays running total GALLONS of displaced media by CLEARS\n\r");
        putsUART ((char *)"RESET - resets HOURS, MINUTES and GALLONS for new job for CLEARS\n\r");  
    }

    void Total(void)
    {
        putsUART ((char *)"--------------------------Unit Total usage------------------------\n\r");
        sprintf(buffer, "Total Hours %d, Total Minutes %d, Total Gallons %d,\n\r",
            total_hours,total_minutes,total_gallons);
        putsUART ((char *) buffer);     // Send message.
        
    }

    void SOFT_SW_init(void)
    {
        START_SW_BLE = OFF;
        PURGE_SW_BLE = OFF;
        ECOMODE_BLE  = OFF;
        CONT_SW_BLE  = OFF;
        Hyper_BLE    = OFF;
        STOP1_BLE    = OFF;
        STOP2_BLE    = OFF;
        BLE_status   = OFF;
        start_latch  = OFF;

    }

    void sys_init(void)
    {
        OSCCON1 = 0b01100000;       //HFINTOSC selection
        OSCFRQ  = 0b00000100;       //8Mhz operation
    /*----------------PORT A-------------------------------------------*/
        ANSELA  = 0b00000000;        //deselect analog channels
        WPUA    = 0b00000000;       //weak pull-ups disabled
        ODCONA  = 0b00000000;       //port A configured as push-pull
    //    SLRCONA = 0b11111111;       //limited slew rate
        SLRCONA = 0b00000000;
    //    INLVLA  = 0b00000011;     //10/30/20
    /*----------------PORT B-------------------------------------------*/
        ANSELB  = 0b00000000;       //deselect analog channels
        WPUB    = 0b00000000;       //weak pull-ups disabled
        ODCONB  = 0b00000000;       //port B configured as push-pull
    //    SLRCONB = 0b11111111;       //limited slew rate
        SLRCONB = 0b00000000;
    /*----------------PORT C-------------------------------------------*/
        ANSELC  = 0b00000000;       //deselect analog channels
        WPUC    = 0b00000000;       //weak pull-ups disabled
        ODCONC  = 0b00000000;       //port B configured as push-pull
    //    SLRCONC = 0b11111111;       //limited slew rate
        SLRCONC = 0b00000000;

    /*----------------Disable all port level change interrupt----------*/  
        IOCAN   = 0b00000011;       //RA0 (primary) and RA1 (secondary)zero crossing
        IOCAP   = 0b00000011;
        IOCBN   = 0b00000000;
        IOCBP   = 0b00000000;
        IOCCN   = 0b00000000;
        IOCCP   = 0b00000000;
    //    INLVLA  = 0b00000000;
    /*-----------------------------------------------------------------*/   
        TRISA   = TRISA_value;
        TRISB   = TRISB_value;      //RB7(TX)bit set as output
        TRISC   = TRISC_value;        //see port #define's above for TRIS values
        T0CON1  = 0b01000000;       //timer0 source is HFINTOSC w/ prescaler 1:1
        T0EN    = ON;               //enable timer0
        T016BIT = ON;               //timer0 in 16 bit mode
        IOCIE   = OFF;              //disable interrupt on level change
        DAC1EN  = OFF;
        MDEN    = OFF;
        CCP1EN  = OFF;
        CCP2EN  = OFF;
        CCP3EN  = OFF;
        CCP4EN  = OFF;
        TSEN    = OFF;              //die temperature measurement disabled
        PWM5EN  = OFF;
        PWM6EN  = OFF;
        PORTA   = 0b11111111;
    /*--------------------------------PPS settings---------------------*/   
        GIE = OFF;
        PPSLOCK = 0x55;
        PPSLOCK = 0xAA;
        PPSLOCK = 0x00;             //unlock PPS
        RXPPSbits.RXPPS     = 0x0D; //RX -> RB5
        RB7PPSbits.RB7PPS   = 0x14; //TX -> RB7
    //    CCP1PPSbits.CCP1PPS = 0x12; //CCP1 output on RC2 (VAC1) min PWM frequency 1.22KHz
    //    CCP2PPSbits.CCP2PPS = 0x15; //CCP2 output on RC5 (VAC2) too fast
    //    CCP3PPSbits.CCP3PPS = 0x13; //CCP3 output on RC3 (BLOW1)
    //    CCP4PPSbits.CCP4PPS = 0x14; //CCP4 output on RC4 (BLOW2)
        PPSLOCK = 0x55;
        PPSLOCK = 0xAA;
        PPSLOCK = 0x01;             //lock PPS
    /*-----------------------------------------------------------------*/    
        SWDTEN  = OFF;              //disable watchdog
        TMR0L   = 0xF0;             //10mS timer0 interrupt counts
        TMR0H   = 0xB2;             //timer0 in 16bit mode
        INTCON  = 0b11000000;        //GIE,PEIE
        PIE0    = 0b00100000;       //TMR0IE
        PIE1    = 0b00100000;       //RCIE
        PIE2    = 0b00000000;
        PIE3    = 0b00000000;
        PIE4    = 0b00010000;
        T5CON   = 0b11100100;
        T3CON   = 0b11100100;
        TMR5GE  = OFF;              //timer1 always counting
        TMR3GE  = OFF;
        baudUART();
        CloseUART();                //turn off usart if was previously on
        OpenUART();
        
        VACMTR1=VACMTR2=BLOWMTR1=BLOWMTR2=MTROFF;        //make sure VACMTRs are OFF
        vac1=vac2=blow1=blow2= 0;
        vac_mtr1=vac_mtr2=blow_mtr1=blow_mtr2=0;
        SOFT_SW_init();
    /*-------------initialize counters/timers ------------------------------------*/    
        manual_purge    = 0;
        tenms_ctr       = 0;
        min_ctr         = 0;
        qrt_ctr         = 0;
        VACMTR1_tmr     = 0;
        VACMTR2_tmr     = 0;
        BLOWMTR1_tmr    = 0;
        BLOWMTR2_tmr    = 0;    
        STOP1           = OFF;
        STOP2           = OFF;
        display_RXdata  = 0;
        tenms_min       = TENMS_MIN;
        Total_flag      = OFF;
        start_latch     = OFF;
        phase_detect    = ON;
    //-------------------------these shall be written in NV RAM-------------------//
        if (EEPROM_READ(10) == 0xFF )        //meaning first time CLEARS is operating
        {
            hours =   0;
            minutes = 0;
            gallons = 0;
            EEPROM_WRITE(0,hours);
            EEPROM_WRITE(1,minutes);
            EEPROM_WRITE(2,gallons);
            EEPROM_WRITE(4, 0);
            EEPROM_WRITE(5, 0);
            EEPROM_WRITE(6, 0);
            EEPROM_WRITE(10,0x00);           //CLEARS has history of operation
        }
        else
        {
            hours   = EEPROM_READ(0);
            minutes = EEPROM_READ(1);
            gallons = EEPROM_READ(2);
            total_hours   = EEPROM_READ(4);
            total_minutes = EEPROM_READ(5);
            total_gallons = EEPROM_READ(6);
        }
    }
     
     
    #10
    razmiggee
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2020/10/07 14:59:06
    • Location: 0
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 19:31:19 (permalink)
    0
    this is the .h file
    /******************************************************
            hybmrk18346.h
            9/17/2020
    ******************************************************/

    /******************************************************
            Macro Definitions
    ******************************************************/

    /******************************************************
            Constant Definitions
    ******************************************************/
    #define MTRON        0
    #define MTROFF        1
    #define    EMPTY        1    //NPN = 1, PNP = 0
    #define    FULL        0    //NPN = 0, PNP = 1
    #define NOT_EMPTY    0    //NPN = 0, PNP = 1
    #define NOT_FULL    1    //NPN = 1, PNP = 0
    #define    ON            1
    #define    OFF            0
    #define MTR_ONTIME     40    //x0.25S=10 Minutes
    #define TENMS_MIN   6000    //was 6000
    #define ZERO        0
    #define EU_POWER    25  //max allowed (240/2 VAC)
    #define US_POWER    49  //max allowed (115VAC)
    #define US_1qdr     57
    #define US_3qdr     123
    #define US_min_pwr  10
    #define EU_1qdr     72
    #define EU_3qdr     147
    #define EU_min_pwr  5
    #define RUNNING     1

    /******************************************************
            Port Definitions
    ******************************************************/
    #define ACPRIZCC                PORTAbits.RA0   //AC PRI ZERO CROSS
    #define ACSECZCC                PORTAbits.RA1   //AC SEC ZERO CROSS
    #define CONTMODE_RAW            PORTAbits.RA2   //CONTINUOUS MODE SWITCH INPUT
    #define START_SW_RAW            PORTAbits.RA3   //digital input, START SWITCH RAW
    #define BOTMLVL2_RAW            PORTAbits.RA4    //bottom level sensor input #2
    #define TOPLVL1_RAW                PORTAbits.RA5    //top level sensor input #1
    #define TRISA_value                0b11111111

    #define    RRB4                    PORTBbits.RB4                //
    #define RRB5                    PORTBbits.RB5                //
    #define RRB6                    PORTBbits.RB6                //Reserved
    #define RRB7                    PORTBbits.RB7                //
    #define TRISB_value                0b01111111      //RB7 is output (TX)

    #define ECOMODE_RAW                PORTCbits.RC0                //ECO MODE (10A/20A) SWITCH INPUT
    #define PURGE_SW_RAW            PORTCbits.RC1                //main switch input
    #define VACMTR1                    LATCbits.LATC2    //vacuum motor #1 output
    #define BLOWMTR1                LATCbits.LATC3    //blower motor #1 output
    #define    BLOWMTR2                LATCbits.LATC4    //blower motor #2 output
    #define VACMTR2                    LATCbits.LATC5    //vacuum motor #2 output
    #define TOPLVL2_RAW                PORTCbits.RC6                //top level sensor input #2
    #define BOTMLVL1_RAW            PORTCbits.RC7                //bottom level sensor input #1
    #define TRISC_value                0b11000011


    /******************************************************
            function declarations
    ******************************************************/
    void sys_init (void);
    void debounce_inputs (void);
    void motors_timeout(void);
    void BLE (void);
    void CloseUART(void);
    void OpenUART(void);
    void baudUART(void);
    void putsUART(char* );
    void BLE(void);
    void InitUART(void);
    void SOFT_SW_init(void);
    void HELP(void);
    void vacmtr1(void);
    void vacmtr2(void);
    void blowmtr1(void);
    void blowmtr2(void);
    void Total(void);
    void run_vacs(void);
    unsigned char two_circuit(void);
    unsigned char Europe(void);

    //unsigned int analogue_chn (void);

    /******************************************************
            variable definitions
    ******************************************************/
    unsigned int  delay_ctr;
    unsigned char TOPLVL1;
    unsigned char TOPLVL2;
    unsigned char BOTMLVL1;
    unsigned char BOTMLVL2;
    unsigned char PURGE_SW;
    unsigned char PURGE_SW_BLE;
    unsigned char CONT_SW;
    unsigned char CONT_SW_BLE;
    unsigned char i1TF;
    unsigned char i1BF;
    unsigned char i1TE;
    unsigned char i1BE;
    unsigned char i2TF;
    unsigned char i2BF;
    unsigned char i2TE;
    unsigned char i2BE;
    unsigned char iPSWON;
    unsigned char iPSWOFF;
    unsigned char iCSWON;
    unsigned char iCSWOFF;
    unsigned char START_SW;
    unsigned char START_SW_BLE;
    unsigned char ECOMODE;
    unsigned char ECOMODE_BLE;
    unsigned char STOP1;
    unsigned char STOP1_BLE;
    unsigned char STOP2;
    unsigned char STOP2_BLE;
    unsigned char manual_purge;
    unsigned char tenms_ctr;
    unsigned char min_ctr;
    unsigned char qrt_ctr;
    unsigned char VACMTR1_tmr;
    unsigned char VACMTR2_tmr;
    unsigned char BLOWMTR1_tmr;
    unsigned char BLOWMTR2_tmr;
    unsigned char BLE_status;
    unsigned char RXdata[16];
    unsigned char TXdata[16];
    unsigned char RXdata_index;
    unsigned char display_RXdata;
    unsigned int  INTGvalue;
    unsigned char one_time;
    unsigned char i;
    unsigned char p;
    unsigned char HELP_flag;
    unsigned char buffer[128];
    unsigned char flag_eeprom_wr;

    unsigned int  tenms_min;
    unsigned int  hours;
    unsigned char minutes;
    unsigned int  gallons;
    unsigned int  total_hours;
    unsigned char total_minutes;
    unsigned int  total_gallons;
    unsigned char Hyper;
    unsigned char Hyper_BLE;
    unsigned char Total_flag;
    unsigned char start_latch;
    unsigned char store_timerL;
    unsigned char store_timerH;
    unsigned char phase_detect;
    unsigned char vac_mtr1;
    unsigned char blow_mtr1;
    unsigned char vac_mtr2;
    unsigned char blow_mtr2;
    unsigned char power1;
    unsigned char power2;
    unsigned char power3;
    unsigned char power4;
    unsigned char vac1_power;
    unsigned char vac2_power;
    unsigned char blow1_power;
    unsigned char blow2_power;
    unsigned char vac1;
    unsigned char blow1;
    unsigned char vac2;
    unsigned char blow2;
    unsigned char max_power;
    unsigned int  power;
    unsigned char first_qdr;
    unsigned char third_qdr;
    unsigned char min_power;
    unsigned char reduced_power;
    unsigned char one_circuit;
    unsigned char counter1;
    unsigned char counter2;
    unsigned int  iw;

    /******************************************************
            function definitions
    ******************************************************/

    void baudUART()
    // FOSC 8Mhz, baudrate = 115.2K
    {
        SYNC  = 0;
        BRG16 = 1;
        BRGH  = 1;
    //    SPBRG = 34;                 //57.2k
        SPBRG = 16;                 //115.2k
    }

    void CloseUART()
    {
        RCIE = 0;                   //no receive interrupt
        TXIE = 0;                   //no transmit interrupt
        TXEN = 0;                   //disable transmit
        CREN = 0;                   //disable receive
        SPEN = 0;
    }

    void OpenUART()
    {
        SYNC = 0;
        SPEN = 1;
        TXEN = 1;                    //enable transmit
        CREN = 1;                    //enable receive
        RCIE = 1;                    //enable receive character interrupt
        TXIE = 0;                    //no transmit interrupt, at this time
    }

    void putsUART(char* TXdata)
    {
     while (*TXdata != 0)
     {    
        TXREG = *TXdata++;
        while (!TRMT);
     }
    }

    void BLE(void)
    {
        if(display_RXdata == 1)
        {
            if (strncmp("BLE ON", (char *)RXdata, 6) == 0)
            {
                BLE_status = ON;
            }
            else if (strncmp("BLE OFF", (char *)RXdata, 7) == 0)
            {
                BLE_status = OFF;
            }
            else if ((strncmp("HELP", (char *)RXdata, 4) == 0) && (HELP_flag == OFF))
            {
                HELP();
                HELP_flag = ON;
            }
            else if (strncmp("EXIT", (char *)RXdata, 4) == 0)
            {
                HELP_flag  = OFF;
                Total_flag = OFF;
            }
            else if ((strncmp("TOTAL", (char *)RXdata, 5) == 0) && (Total_flag == OFF))
            {
                Total();
                Total_flag = ON;
            }
        }
        run_vacs();
        if((display_RXdata == 1) && (BLE_status == ON))
        {
            display_RXdata = 0;
            if (strncmp("START", (char *)RXdata, 5) == 0)
            {
                START_SW_BLE = ON;
                STOP1_BLE = OFF;
                STOP2_BLE = OFF;
                PURGE_SW_BLE = OFF;
                start_latch = ON;
            }
            else if (strncmp("STOP", (char *)RXdata, 4) == 0)
            {
                STOP1_BLE = STOP2_BLE = ON;
                PURGE_SW_BLE = OFF;
                START_SW_BLE = OFF;
                start_latch  = OFF;
            }
            else if (strncmp("PURGE", (char *)RXdata, 5) == 0)
            {
                PURGE_SW_BLE = ON;
                STOP1_BLE    = OFF;
                STOP2_BLE    = OFF;
                START_SW_BLE = OFF;
                start_latch  = OFF;
            }
            else if(strncmp("CONT", (char *)RXdata, 4) == 0)
            {
                CONT_SW_BLE = OFF;
                Hyper_BLE   = ON;
            }    
            else if(strncmp("HYP", (char *)RXdata, 3) == 0)
            {
                CONT_SW_BLE = ON;
                Hyper_BLE   = OFF;
            }    
            else if(strncmp("ECO", (char *)RXdata, 3) == 0)
            {
                ECOMODE_BLE  = ON;
                STOP1_BLE = STOP2_BLE = ON;
                PURGE_SW_BLE = OFF;
                START_SW_BLE = OFF;
                Hyper_BLE    = OFF;
                CONT_SW_BLE  = ON;
                start_latch  = OFF;
            }
            else if(strncmp("NECO", (char *)RXdata, 4) == 0)
            {
                ECOMODE_BLE = OFF;
            }
            else if(strncmp("RESET", (char *)RXdata, 5) == 0)
            {
                GIE  = OFF;
                PEIE = OFF;
                hours=minutes=gallons = 0;
                EEPROM_WRITE (0, hours);
                EEPROM_WRITE (1, minutes);
                EEPROM_WRITE (2, gallons);
                GIE  = ON;
                PEIE = ON;
                OpenUART();
                TMR0IE = ON;
            }
            else if (strncmp("PWR", (char *)RXdata, 3) == 0)
            {
                reduced_power = atoi((char *) strstr(RXdata,"PWR")+3)/2;
                if (reduced_power > 50)reduced_power = 50;
                vac1_power  = reduced_power;
                blow1_power = reduced_power;
                vac2_power  = reduced_power;
                blow2_power = reduced_power;
            }
            for (i = 0; i < 16; i++) RXdata = NULL;    //clear receive array
        }
        run_vacs();
        
    //    debounce_inputs();
        motors_timeout();
        
        if ((HELP_flag == OFF) && (Total_flag == OFF))
        {
    /*------------------------------------test all input signals raw--------------*/        
    //        sprintf(buffer, "ST %d, SP1 %d, SP2 %d, PG %d, TOP1 %d, BOT1 %d, TOP2 %d, BOT2 %d, ECO %d, CON %d, HYP %d\n\r",
    //                START_SW, STOP1, STOP2, PURGE_SW, TOPLVL1_RAW, BOTMLVL1_RAW, TOPLVL2_RAW, BOTMLVL2_RAW, ECOMODE, CONT_SW, Hyper);
    //            putsUART ((char *) buffer);     // Send message.
    /*----------------------------------------------------------------------------*/
            if(BLE_status == ON)
            {
    //*            
    //            sprintf(buffer,"T5L %d\n\r", store_timer1L);
                sprintf(buffer, "St %d,Sp1 %d,Sp2 %d,Pg %d,Eco %d,Con %d,Hyp %d,BLE %d,H: %d,M: %d,Gal: %d,PWR: %d\n\r",
                    start_latch,STOP1_BLE,STOP2_BLE,PURGE_SW_BLE,ECOMODE_BLE,!CONT_SW_BLE,!Hyper_BLE,BLE_status,hours,minutes,gallons,(vac1_power*2));
                putsUART ((char *) buffer);     // Send message.
            }
            else
            {
    //            sprintf(buffer,"T5L %d\n\r", store_timer1L);
                sprintf(buffer, "St %d,Sp1 %d,Sp2 %d,Pg %d,Eco %d,Con %d,Hyp %d,BLE %d,H: %d,M: %d,Gal: %d,PWR: %d\n\r",
                    start_latch,STOP1,STOP2,PURGE_SW,ECOMODE,!CONT_SW,!Hyper,BLE_status,hours,minutes,gallons,(vac1_power*2));
                putsUART ((char *) buffer);     // Send message.
    //*/
            }        
        }
        
        if (flag_eeprom_wr == ON)               //is TRUE every minute
        {
            GIE    = OFF;
            PEIE   = OFF;
            TMR0IE = OFF;
            flag_eeprom_wr = OFF;
            EEPROM_WRITE (0, hours);
            EEPROM_WRITE (1, minutes);
            EEPROM_WRITE (2, gallons);
            total_minutes = total_minutes + 1;
            if (total_minutes >= 60)
            {
                total_minutes = total_minutes - 60;  
                total_hours   = total_hours + 1;
            }
            total_gallons = total_gallons + gallons;
            EEPROM_WRITE (4, total_hours);
            EEPROM_WRITE (5, total_minutes);
            EEPROM_WRITE (6, total_gallons);
            GIE    = ON;
            PEIE   = ON;
            OpenUART();
            TMR0IE = ON;
        }

    }



     
    #11
    1and0
    Access is Denied
    • Total Posts : 11501
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 20:22:18 (permalink)
    +2 (2)
    Do NOT touch (OFF and ON) any interrupt enable (IE) bits inside your ISR, including TMRxIE, RCIE, IOCIE, and especially PEIE and GIE.  Also, RCIF is a read-only bit; it cannot be directly set or cleared.
    #12
    1and0
    Access is Denied
    • Total Posts : 11501
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/10/30 21:09:25 (permalink)
    +3 (3)

            RXdata[RXdata_index++] = RCREG;
            if((RCREG == '\r') || (RCREG == '\n'))

    RCREG is a FIFO buffer. Here it is being read three times of possibly different values.
    #13
    Aussie Susan
    Super Member
    • Total Posts : 3787
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/11/01 18:53:59 (permalink)
    +2 (2)
    Hardly what I would call a small application that clearly shows the problem.
    And there are a log of things I can see that appear to be wrong - some of your code could well not appear as you have not used the 'code' tags.

    while(1)
        {
            
            TMR5IE = ON;
            TMR5L  = 255 - (first_qdr - power1 + 2);
            TMR5H  = 0xFF;
            TMR5ON = ON;
            vac_mtr1 = RUNNING;
            counter1 = 0;
            IOCAF0    = OFF;        
            while(counter1 < 1);
         }

    How do you expect this to exit to get to the rest of your code?
    If somehow you did get out of that loop, you then have:

    r1:
            run_vacs();
            goto r1;

    This may be where some of the issue lies:

        GIE = OFF;
        PPSLOCK = 0x55;
        PPSLOCK = 0xAA;
        PPSLOCK = 0x00;             //unlock PPS
     

    The first instruction turns off the interrupt system. There are places where you set the GIE bit but I'm not convinced that you ever execute those paths.
    It may be different for this processor but unlock code sequences normally must be executed as consecutive instructions to the CPU. Therefore these need to be coded in assembler. I don't think you have said what compiler you are using so I assume XC8 - check that they do not provide a macro or some other means of performing the unlock/lock sequence if it s needed.
    Most Microchip MCUs power up with the PPS registers unlocked so that you don't need to unlock them first. (Actually you can have issues during the early testing if you do play with the PPS (un)lock sequences because another power-in default is to allow the lock sequence only once and and not allow unlocking after that.) My advice is leave (un)locking the PPS registers until after you have everything working and are programming your MCU for production purposes.
    You have code in your '.h' file - this can be done if you are very careful but is generally the sign of a very bad code design and can lead to problems during the link phase if the '.h' file is included into separate compilation units.
    This code really does need a lot of tidying. I suggest that you put is all to one side, start with just a basic CPU initialisation and main loop, and then add in the various parts one at a time, testing each as you go.
    Susan
    #14
    razmiggee
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2020/10/07 14:59:06
    • Location: 0
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/11/03 11:33:52 (permalink)
    0
    Let me pose this problem of mine in a different way.
    Is there any knowledge that IOCIE interrupt and TMR5IE interrupt can interfere with each other?
    I got the TIMER5 interrupt to work but when the edge interrupt is turned on there is no interrupt received on IOCIE. the pins I use are RA0 and RA1 therefore, I look for IOCAF0 and IOCAF1 to get activated.
    Much appreciate any guidance.
     
    Raz
    #15
    razmiggee
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2020/10/07 14:59:06
    • Location: 0
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/11/03 11:39:38 (permalink)
    +1 (1)
    In response to Aussie SUSAN - The while(1) code is for testing. I don't intend to travel through the rest of the code. This is to make sure that TIMER5 and the IOCIE interrupts interact together correctly. Hope this lifts the concerns that how I get to the rest of the code.
     
    Thank you.
    Raz
     
     
     
    #16
    ric
    Super Member
    • Total Posts : 28943
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/11/03 11:58:31 (permalink)
    0
    razmiggee
    Is there any knowledge that IOCIE interrupt and TMR5IE interrupt can interfere with each other?

    Not in hardware. The only problem is if you have poorly coded interrupt service routines.
    The code you posted in #10 IS poorly coded, as 1and0 and Susan explained.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #17
    1and0
    Access is Denied
    • Total Posts : 11501
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/11/03 12:02:29 (permalink)
    +1 (1)
    razmiggee
    this is the .h file

    Do NOT put executable code in a .h header file.
     
    razmiggee
    Let me pose this problem of mine in a different way.
    Is there any knowledge that IOCIE interrupt and TMR5IE interrupt can interfere with each other?
    I got the TIMER5 interrupt to work but when the edge interrupt is turned on there is no interrupt received on IOCIE. the pins I use are RA0 and RA1 therefore, I look for IOCAF0 and IOCAF1 to get activated.
     
        if (IOCAF0)
        {
            IOCIE   = OFF;
            IOCIF   = OFF;
            IOCAF0  = OFF;
            IOCIE   = ON;
        }

    But your ISR handles IOC interrupt on only RA0, and IOCIF is a read-only flag. As I recall correctly, clearing IOC interrupt flags should be performed with a complement and AND operations to ensure no detected edge is lost; so read the IOC chapter of your PIC datasheet on how to do that.
     
    #18
    Aussie Susan
    Super Member
    • Total Posts : 3787
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: I'm not getting Timer 5 interrupt on PIC16F18346 2020/11/03 18:46:41 (permalink)
    0
    On devices such as yours that have only 1 ISR then the ISR will be called when:
    - the main code is running (it when not already in the ISR - the ISR is not reentrant)
    - both the xxIE and xxIF bits are set
    (See Figure 8-1 in the data sheet).
    If two interrupts occur simultaneously the following happens (which is basically what happens when 1 interrupt occurs):
    - the current instruction is allowed to complete
    - the ISR code is called and interrupts are disabled
    - in the ISR code, you need to test for which xxIF bit is set and handle the interrupt, including clearing the xxIF bit in whatever way is required for the module
    - the ISR exits and interrupts are re-enabled
    - either execute the next instruction or, if corresponding xxIE and xxIF bits are set, jump back to the ISR
    If you write the ISR so that it is a series of 'if(...)' statements testing the xxIF bits, then that provides a natural 'priority' to the interrupts but also means that if two interrupts have occurred simultaneously, then both might be handled in the one calling of the ISR. If not then, as you see form the above, if you exit the ISR and there is still an interrupt pending, then the ISR is simply called again.
    If you are finding that the interrupts are somehow interfering with each other, then you need to look at your code as to why.
    Susan
    #19
    Jump to:
    © 2020 APG vNext Commercial Version 4.5