The Program stops running as sensors detects something

Thread Starter

Khisraw

Joined Nov 14, 2020
56
Hi,

I am using the PIC12F1571 MCU in our latest design. It is connected to two sensors (TSSP58038- Proximity, IRA-S210ST01- PIR sensor) with analog input.

The PIR is connected to RA0 and the Proximity sensor is connected to RA2.

The program:

As soon as the PIR sensor detects anything(Goes to 3V), the program should turn on the PWM(Pin RA1) and then reads the second sensor from the RA2 pin. If RA2 is over 3V, then it should toggle the Pin RA4.

Hardware:

I am using the Curiosity kit(DM164137)

The problem.
As soon as the sensor detects anything, the program which is being run on the MPLABX is halted. The codes seem it doesn't get into the second if.

Since I have spent over a week on this, I am running out of ways to test, so anyone has any suggestion?

Codes are below
C:
#include <xc.h>
#define _XTAL_FREQ 20000000

#include "newxc8_header.h"
#include <stdio.h>
#include <stdlib.h>
#include <pic12f1571.h>
#define PIR RA0
#define PROX_PWM RA1 //FOR PROXIMITY SENSOR it's the pwm signal
#define PROX_IN RA2 //the output pin of the proximity sensor
int adc_resultPIR;
int adc_resultPROXI;




void toggle() {//toggle output on RA4
 
    LATAbits.LATA5 = ~LATAbits.LATA5;
    __delay_ms(10);
  

}

void setADC0() {

    adc_resultPIR = 0;
    ADCON0 = 0x01;
    // ADFM left; ADPREF VDD; ADCS FOSC/2;
    ADCON1 = 0x80;
    // TRIGSEL no_auto_trigger;
    ADCON2 = 0x00;
    // ADRESL 0;
    ADRESL = 0x00;
    // ADRESH 0;
    ADRESH = 0x00;

    ADCON0bits.CHS = 0x00;
    // Turn on the ADC module
    ADCON0bits.ADON = 1;
    // Acquisition time delay

    __delay_ms(2);
    // Start the ADC conversion
    ADCON0bits.GO_nDONE = 1;

    // Wait for the conversion to finish
    while (ADCON0bits.GO_nDONE)
{
    }
    // Conversion finished, return the result
    adc_resultPIR = ((ADRESH << 8) + ADRESL);
}
void setADC1() {//for proximity sensor

    adc_resultPROXI = 0;
    ADCON0 = 0x09;
    // ADFM left; ADPREF VDD; ADCS FOSC/2;
   ADCON1 = 0x80;
    // TRIGSEL no_auto_trigger;
    ADCON2 = 0x00;
    // ADRESL 0;
    ADRESL = 0x00;
    // ADRESH 0;
    ADRESH = 0x00;
   
    // Turn on the ADC module
    ADCON0bits.ADON = 1;
    // Acquisition time delay

    __delay_ms(2);
    // Start the ADC conversion
    ADCON0bits.GO_nDONE = 1;

    // Wait for the conversion to finish
    while (ADCON0bits.GO_nDONE)
{
    }
    // Conversion finished, return the result
    adc_resultPROXI = ((ADRESH << 8) + ADRESL);
}

void setupPWM() {
    // PWM 1 Setup
    PWM1CLKCON = 0x00; // 32 prescaler, CLK: Fosc
    PWM1PR = 526; // period 500ms
    //PWM1DC = 7811; // Duty cycle
    PWM1DC = 368;
    PWM1INTE = 0x00;
    PWM1INTF = 0x00;
    PWM1PH = 0; // Phase counter 0
    PWM1OFL = 0x01; // PWM1OFL 1;
    PWM1CON = 0xC0; // MODE standard_PWM; POL active_hi; OE enabled; EN enabled;
    PWM1LDCONbits.LDA = 1; // Load OF, PH, DC, and PR buffers
    PWM3CON = 0x00;
  
 
}

void main(void) {
    TRISA = 0b00000101;
    ANSELA = 0x05;
  
    while (1) {
        setADC0();
        __delay_ms(100);
        if (adc_resultPIR > 600) //>620 for PIR sensor 3V
        {
            setupPWM();
          
            __delay_ms(100); //Wait
            setADC1();
            __delay_ms(100);
            if(adc_resultPROXI > 820) //820 for PROXI sensor 4V
            {
                toggle();
                PWM1CON=0x00;
                __delay_ms(10);
            }
           
            //toggle();
        }
        else{
             PWM1CON=0x00;
            
        }
    }
}
Mod edit: code tags - JohnInTX
 

click_here

Joined Sep 22, 2020
548
Set up a UART output and view values of readings on a terminal program

Or

Get an LED/resistor and put it on an unused output. Set it high if a condition is met, like <400

Edit - You can also use the LED to see what line the code is getting stuck at
 
Last edited:

ErnieM

Joined Apr 24, 2011
8,377
Are you doing in circuit debugging?

A PICKit can do that. Over several trials you should easily see exactly which step bombs out, and the conditions that light the fuse.
 

John P

Joined Oct 14, 2008
2,025
This is clearly wrong--this is from the setADC0() function, but they both have it:
Code:
   // Wait for the conversion to finish
    while (ADCON0bits.GO_nDONE)
{
    }
    // Conversion finished, return the result
    adc_resultPIR = ((ADRESH << 8) + ADRESL);
There's nothing between the { and } marks. At the very least, there should be a bare semicolon.
 

click_here

Joined Sep 22, 2020
548
This is clearly wrong--this is from the setADC0() function, but they both have it:
Code:
   // Wait for the conversion to finish
    while (ADCON0bits.GO_nDONE)
{
    }
    // Conversion finished, return the result
    adc_resultPIR = ((ADRESH << 8) + ADRESL);
There's nothing between the { and } marks. At the very least, there should be a bare semicolon.
The better way is to do either a "null statement"
Code:
while(banana != apple);
Or explicitly saying that you want the loop to loop again
Code:
while(banana != apple)
{
    continue;
}
That being said, I don't think that there is anything in the standards saying that you can't have an empty compound statement/block.
 

John P

Joined Oct 14, 2008
2,025
You can have an empty space between brackets, like
{ }
But if you do, it'll be ignored by the compiler as it it were whitespace. What the code does is the same as
Code:
while (ADCON0bits.GO_nDONE)
    adc_resultPIR = ((ADRESH << 8) + ADRESL);
I would write it as
Code:
while (ADCON0bits.GO_nDONE) 
  ;
The semicolon sitting there alone, indented relative to the while() line, would be a reminder that there's a loop running.
 

BobaMosfet

Joined Jul 1, 2009
2,110
Hi,

I am using the PIC12F1571 MCU in our latest design. It is connected to two sensors (TSSP58038- Proximity, IRA-S210ST01- PIR sensor) with analog input.

The PIR is connected to RA0 and the Proximity sensor is connected to RA2.

The program:

As soon as the PIR sensor detects anything(Goes to 3V), the program should turn on the PWM(Pin RA1) and then reads the second sensor from the RA2 pin. If RA2 is over 3V, then it should toggle the Pin RA4.

Hardware:

I am using the Curiosity kit(DM164137)

The problem.
As soon as the sensor detects anything, the program which is being run on the MPLABX is halted. The codes seem it doesn't get into the second if.

Since I have spent over a week on this, I am running out of ways to test, so anyone has any suggestion?

Codes are below
C:
#include <xc.h>
#define _XTAL_FREQ 20000000

#include "newxc8_header.h"
#include <stdio.h>
#include <stdlib.h>
#include <pic12f1571.h>
#define PIR RA0
#define PROX_PWM RA1 //FOR PROXIMITY SENSOR it's the pwm signal
#define PROX_IN RA2 //the output pin of the proximity sensor
int adc_resultPIR;
int adc_resultPROXI;




void toggle() {//toggle output on RA4

    LATAbits.LATA5 = ~LATAbits.LATA5;
    __delay_ms(10);
 

}

void setADC0() {

    adc_resultPIR = 0;
    ADCON0 = 0x01;
    // ADFM left; ADPREF VDD; ADCS FOSC/2;
    ADCON1 = 0x80;
    // TRIGSEL no_auto_trigger;
    ADCON2 = 0x00;
    // ADRESL 0;
    ADRESL = 0x00;
    // ADRESH 0;
    ADRESH = 0x00;

    ADCON0bits.CHS = 0x00;
    // Turn on the ADC module
    ADCON0bits.ADON = 1;
    // Acquisition time delay

    __delay_ms(2);
    // Start the ADC conversion
    ADCON0bits.GO_nDONE = 1;

    // Wait for the conversion to finish
    while (ADCON0bits.GO_nDONE)
{
    }
    // Conversion finished, return the result
    adc_resultPIR = ((ADRESH << 8) + ADRESL);
}
void setADC1() {//for proximity sensor

    adc_resultPROXI = 0;
    ADCON0 = 0x09;
    // ADFM left; ADPREF VDD; ADCS FOSC/2;
   ADCON1 = 0x80;
    // TRIGSEL no_auto_trigger;
    ADCON2 = 0x00;
    // ADRESL 0;
    ADRESL = 0x00;
    // ADRESH 0;
    ADRESH = 0x00;
  
    // Turn on the ADC module
    ADCON0bits.ADON = 1;
    // Acquisition time delay

    __delay_ms(2);
    // Start the ADC conversion
    ADCON0bits.GO_nDONE = 1;

    // Wait for the conversion to finish
    while (ADCON0bits.GO_nDONE)
{
    }
    // Conversion finished, return the result
    adc_resultPROXI = ((ADRESH << 8) + ADRESL);
}

void setupPWM() {
    // PWM 1 Setup
    PWM1CLKCON = 0x00; // 32 prescaler, CLK: Fosc
    PWM1PR = 526; // period 500ms
    //PWM1DC = 7811; // Duty cycle
    PWM1DC = 368;
    PWM1INTE = 0x00;
    PWM1INTF = 0x00;
    PWM1PH = 0; // Phase counter 0
    PWM1OFL = 0x01; // PWM1OFL 1;
    PWM1CON = 0xC0; // MODE standard_PWM; POL active_hi; OE enabled; EN enabled;
    PWM1LDCONbits.LDA = 1; // Load OF, PH, DC, and PR buffers
    PWM3CON = 0x00;
 

}

void main(void) {
    TRISA = 0b00000101;
    ANSELA = 0x05;
 
    while (1) {
        setADC0();
        __delay_ms(100);
        if (adc_resultPIR > 600) //>620 for PIR sensor 3V
        {
            setupPWM();
         
            __delay_ms(100); //Wait
            setADC1();
            __delay_ms(100);
            if(adc_resultPROXI > 820) //820 for PROXI sensor 4V
            {
                toggle();
                PWM1CON=0x00;
                __delay_ms(10);
            }
          
            //toggle();
        }
        else{
             PWM1CON=0x00;
           
        }
    }
}
Mod edit: code tags - JohnInTX
...and have you flow-charted your code? professionals do it. Forces them to document the logic and easily find logic errors.
 

click_here

Joined Sep 22, 2020
548
You can have an empty space between brackets, like
{ }
But if you do, it'll be ignored by the compiler as it it were whitespace. What the code does is the same as
Code:
while (ADCON0bits.GO_nDONE)
    adc_resultPIR = ((ADRESH << 8) + ADRESL);
That is not true.

The "{" and "}" make the "loop body" for the "while" iteration statement and will never be optimized out.

Here is the two actual snips from my listing files for the XC8 compiler running in PRO mode with optimization on:
Code:
   436                           ;AnalogueToGyro.c: 175: while (!OSCSTATbits.LFIOFR);
   437                          
   438  0763  1C9A                   btfss    26,1    ;volatile
   439  0764  2F63                   goto    l100
Code:
   436                           ;AnalogueToGyro.c: 175: while (!OSCSTATbits.LFIOFR){}
   437                          
   438  0763  1C9A                   btfss    26,1    ;volatile
   439  0764  2F63                   goto    l100
It produces the exact same code.
 
Last edited:

click_here

Joined Sep 22, 2020
548
I noticed that you don't disable weak pull-ups either globally (refer to the OPTION_REG register) or individually (refer to the appropriate WPUx register) - This is required under section 15.2.6 of the datasheet.

You'll need to go through this section and make sure that you have done everything needed for an ADC conversion.
 

John P

Joined Oct 14, 2008
2,025
I have to admit I got that item about empty brackets wrong. If you have {...} inline in your program, a compiler will skip over it without adding anything to the output, but evidently while(test_something){...} does function as a loop. It doesn't seem consistent to me, but that's the way it is.
 

takao21203

Joined Apr 28, 2012
3,702
I dont like
Code:
while
.
It is misleading and a source of bugs.

I use this
Code:
restart:;
...
goto restart;
...
for(i=0;i<5;i++)
{
if(some condition) goto loopfinish;
}
loopfinish:;
if goto is used over short distance it is not a problem.

And yes you should use a debug LED or display and check if certain positions of
your code are even reached at all.
 

click_here

Joined Sep 22, 2020
548
How on Earth is a "goto" statement better than a "while" statement?

"goto" has caused more headaches than anything - Just Google goto in the C language

Code:
for(i=0;i<5;i++)
{
if(some condition) goto loopfinish;
}
loopfinish:;
Why wouldn't you use the "break" statement?
Code:
for(i=0;i<5;i++)
{
    if(some condition) 
    {
        break;
    }
}
 
Top