1
\$\begingroup\$

I am working on an inclinometer project using an accelerometer, MMA1220KEG and a PIC16F1783, it is designed to switch a relay when the angle of inclination is below 15 degrees and illuminates a series of LEDs to indicate the uses is close to this angle, if at 15 degree inclination or above for more than 1 second the relay disengages until at a safe angle.

I have made up a prototype of breadboard with resistors and LEDs to simulate the outputs as per the specification but I have a problem where Pin 16 (RC5) is constantly high and the corresponding LED is illuminated, when the power is removed from the PIC the LED switches off but strangely comes back on if a high is applied to pin 3 (RA1) I have tried numerous things to try and rectify the cost such as changing bits in the alternative pin function register to change the priority of the output pins but nothing seems to help, but I thought a fresh knowledgeable perspective would help from the people of this site :)

I've checked the accelerometer which works as expected.

Any advise or thoughts?

Thanks in advance

[![inclinometer schematic][1]][1]

please see schematic, at the moment i'm trying to rectify the code for the indicators

I've reprogrammed another PIC and changed part of the code relating to the red zone

 /******************************************************************************/
/* Project: PIC16F1783  Measure MMA1220KEG accelerometer                      /
/
output indicator LEDs and activate relay below 15 deg / / Author: Ben Thomas / / Date: 27/07/17 / / Pin Assignments; P2 RA0 AN0 input from Accelerometer / / P3 RA1 input connected to status pin (high if fault / / or if self test is initialised) /
/
P4 RA2 output connected to accelerometer self / / test pin (output high to reset delay before / / checking status pin / / P11 RC0 output connected to GREEN LED (below trip 1 / / output high else low Between 0-11 degrees) / / P12 RC1 output connected to AMB1 LED (between trip 1 / / and trip 2 output high else low between 11-12 / / degrees) / / P13 RC2 output connected to AMB2 LED (between trip 2 / / trip 3 output high else low between 12-13 degrees)/ / P14 RC3 output connected to AMB3 LED (between trip 3 / / and trip 4 output high between 13-14 degrees / / else low) / / P15 RC4 output connected to AMB4 LED (between trip 4 / / and 5 output high between 14-15 degrees else low) / / P16 RC5 output connected to RED LED (equal and above / / trip 5 output high 15 degrees and above else low) / / P17 RC6 output connected to accelerometer fault LED / / P18 RC7 output connected to relay triggering device / / output high when accelerometer output is below 15 / / degrees if above 15 degrees for 1S or longer / / output low until below 15 degrees */ /******************************************************************************/ //Calculate average ADC result and convert to angle //angle = asin((int)(ADRES-Voffset) / SENSE);

/******************************************************************************/ /* Files to Include */ /******************************************************************************/

#include <xc.h>         /* XC8 General Include File */
#include <stdint.h>
#include <math.h>

// CONFIG1

pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)

pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)

pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)

pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)

pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)

pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)

pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)

pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)

pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)

pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2

pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)

pragma config PLLEN = ON // PLL Enable (4x PLL enabled)

pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)

pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)

pragma config LVP = OFF // Low-Voltage Programming Enable (Low-voltage programming disabled)

/******************************************************************************/ /* User Global Variable Declaration */ /******************************************************************************/ //#define NSAMPLES 3 //size of sample array //#define _XTAL_FREQ 4000000 //oscillator frequency for delay_ms()

define Voffset 2.5 //offset of Accelerometer

define SENSE 0.25 //sensitivity of Accelerometer

define TRIP1P 2087 //trip 1 positive end of green zone 1st amber zone

define TRIP1N 2009 // trip 1 negative end of green zone 1st amber sone

define TRIP2P 2091 // Trip 2 positive second amber zone

define TRIP2N 2005 //Trip 2 negative second amber zone

define TRIP3P 2094 //trip 3 positive third amber zone

define TRIP3N 2002 //trip 3 negative third amber zone

define TRIP4P 2094 //trip 4 positive fourth amber zone

define TRIP4N 1998 //trip 4 negative fourth amber zone

define TRIP5P 2101 //trip 5 positive red zone

define TRIP5N 1995 //trip 5 negative red zone

//#define db_cnt1 122 //1S db count for timer0

define STATUS LATAbits.LATA1 //accelerometer status pin

define SLFTST LATAbits.LATA2 //accelerometer self test pin

define GREEN LATCbits.LATC0 //GREEN LED 'OK' zone

define AMB1 LATCbits.LATC1 //AMB1 LED 11-12 degrees

define AMB2 LATCbits.LATC2 //AMB2 LED 12-13 degrees

define AMB3 LATCbits.LATC3 //AMB3 LED 13-14 degrees

define AMB4 LATCbits.LATC4 //AMB4 LED 14-15 degrees

define RED LATCbits.LATC5 //RED LED 15 degrees and above

define FAULT LATCbits.LATC6 //LED indicating Accelerometer fault

define RLY LATCbits.LATC7 //Relay trigger output

uint8_t db_cnt1; uint8_t state = 0;
//uint8_t smp_buf[NSAMPLES]; //Array of samples for moving average

/****PROTOTYPES****/

/****MACROS********/

define TMR0_2 (TMR0 & 1<<2) //access to TMR0<2>

void initialise(void) { TRISC = 0; //configure all PORTC as outputs //TRISA = 0; //configure all PORTA as outputs TRISA = 0b00000011; //configure RA0 and RA1 as inputs only ANSELAbits.ANSA0 = 1; CM1CON0 = 0; //Disable comparator 1 (RB0, RB1 digital) CM2CON0 = 0; //Disable comparator 2 (RC0, RC1 digital) FVRCON = 0; //Disable CVref -> RC2 usable state = 0;

//configure ADC (P147/148)

//ADCON0
ADCON0bits.ADRMD = 0; //ADRESL and ADRESH provide data formatted for a 12-bit result
ADCON0bits.CHS = 00000; //AN0 selected
ADCON0bits.GO_nDONE = 0; // conversion not in progress
ADCON0bits.ADON = 1;    //ADC enable bit
                        //-> AN0 ready for sampling 
//ADCON1
ADCON1bits.ADFM = 0;    //ADC result format is 'sign-magnitude result format
ADCON1bits.ADCS = 100;  //ADC Conversion clock = FOSC/4
ADCON1bits.ADNREF = 0;  //ADC negative voltage reference is Vss
ADCON1bits.ADPREF = 00; //ADC positive voltage reference is Vdd

ADCON2bits.TRIGSEL = 0000;  //ADC auto conversion disabled
ADCON2bits.CHSN = 1111;     //ADC Negative reference - selected by ADNREF         
//configure timer Option Register (174)
OPTION_REGbits.nWPUEN = 1;  //All weak pull-ups are disabled (except nMCLR if enabled)
OPTION_REGbits.TMR0CS = 0;  //Timer0 clock source internal instruction cycle Fosc/4 (Fosc = 32MHz/4 = 8MHz)
OPTION_REGbits.PSA = 0;     //Prescaler is assigned to the Timer0 module
OPTION_REGbits.PS = 111;    //Prescaler rate select bit 1:256
                            //-> increment every 32 uS
                            //-> TMR0 overflows every 8.192mS ()

APFCONbits.SDOSEL = 1;
APFCONbits.CCP1SEL = 1;
APFCONbits.SCKSEL = 1;
APFCONbits.SDISEL = 1;
APFCONbits.TXSEL = 1;
APFCONbits.CCP2SEL = 1;

T1CON = 0;
PSMC1CONbits.PSMC1EN = 0;
PSMC2CONbits.PSMC2EN = 0;

} /*void delay1s(void) //1 second delay { db_cnt1 = 0; while (db_cnt1 < 1000/8) //125*8ms =1s { TMR0 = 0; while (TMR0 < 250) //wait for 8mS 8000/32 ; ++db_cnt1; //increment 8ms counter

}
return;

} * */ /******************************************************************************/ /* Main Program */ /******************************************************************************/ void main(void) { //double angle; // Scaled ADC output in degrees (0-99) initialise();

while(1) { switch(state) { case 0: ADCON0bits.GO = 1; //start ADC conversion while (ADCON0bits.GO_nDONE) //wait until conversion finished ; state = 1; break; case 1: if ((ADRES<TRIP1P && ADRES>TRIP1N) && STATUS == 0) //green zone below 11 degrees { FAULT = 0; state = 10; break; } else if (((ADRES>=TRIP1P && ADRES<TRIP2P) || (ADRES<=TRIP1N && ADRES>TRIP2N)) && STATUS == 0) //AMB1 zone between 11-12 degrees { FAULT = 0; state = 20; break; } else if (((ADRES>=TRIP2P && ADRES<TRIP3P) || (ADRES<=TRIP2N && ADRES>TRIP3N)) && STATUS == 0) //AMB2 zone between 12-13 degrees { FAULT = 0; state = 30; break; } else if (((ADRES>=TRIP3P && ADRES<TRIP4P) || (ADRES<=TRIP3N && ADRES>TRIP4N)) && STATUS == 0) //AMB3 zone between 13-14 degrees { FAULT = 0; state = 40; break; } else if (((ADRES>=TRIP4P && ADRES<TRIP5P) || (ADRES<=TRIP4N && ADRES>TRIP5N)) && STATUS == 0) //AMB4 zone between 14-15 degrees { FAULT = 0; state = 50; break; } else if ((ADRES>=TRIP5P && ADRES<=TRIP5N) && STATUS == 0) //RED zone 15 degrees or higher { FAULT = 0; state = 60; break; } else if (STATUS == 1) //FAULT state mode { state = 70; break; } else state = 0; break; case 10: //green zone angle less than 11 degrees RLY = 1; GREEN = 1; AMB1 = 0; AMB2 = 0; AMB3 = 0; AMB4 = 0; RED = 0; state = 0; break; case 20: //1st amber zone 11-12 degrees RLY = 1; GREEN = 0; AMB1 = 1; AMB2 = 0; AMB3 = 0; AMB4 = 0; RED = 0; state = 0; break; case 30: //2nd amber zone 12-13 degrees RLY = 1; GREEN = 0; AMB1 = 0; AMB2 = 1; AMB3 = 0; AMB4 = 0; RED = 0; state = 0; break; case 40: //3rd amber zone 13-14 degrees RLY = 1; GREEN = 0; AMB1 = 0; AMB2 = 0; AMB3 = 1; AMB4 = 0; RED = 0; state = 0; break; case 50: //4th amber zone 14-15 degrees RLY = 1; GREEN = 0; AMB1 = 0; AMB2 = 0; AMB3 = 0; AMB4 = 1; RED = 0; state = 0; break; case 60: //red zone 15 degrees and above GREEN = 0; AMB1 = 0; AMB2 = 0; AMB3 = 0; AMB4 = 0; RED = 1; if ((ADRES>=TRIP5P && ADRES<=TRIP5N) && STATUS == 0) { state = 61; break; } else { state = 0; break; } break; case 61: if ((ADRES>=TRIP5P && ADRES<=TRIP5N) && STATUS == 0) { //delay1s(); db_cnt1 = 0; while((((ADRES>=TRIP5P && ADRES<=TRIP5N) && STATUS == 0))&& db_cnt1 <1000/8) //1S debounce delay { TMR0 = 0; //clear timer while (TMR0 < 8000/32) ; ++db_cnt1; } if(db_cnt1 >= 1000/8 && ((ADRES>=TRIP5P && ADRES<=TRIP5N) && STATUS == 0)) //if debounce delay is exceeded disengage relay { RLY = 0; state = 0; break; } else state = 0; break; } else state = 0; break; case 70: //initiate test to decipher if unit is faulty SLFTST = 1; db_cnt1 = 0; while (db_cnt1 < 48/8) //48ms delay { TMR0 = 0; //clear timer while (TMR0 < 8000/32) ; ++db_cnt1; } SLFTST = 0; db_cnt1 = 0; while (db_cnt1 < 48/8) //48ms delay { TMR0 = 0; //clear timer while (TMR0 < 8000/32) ; ++db_cnt1; } if(STATUS == 1) { FAULT = 1; state = 0; break; } else { state = 0; break; } break; } }

}

now more LEDs are on, the ones attached to pins 11, 12, 13, 14 and 16.

schematic

\$\endgroup\$
  • \$\begingroup\$ I don't have time to get deeply into your problem, and the lack of a schematic increases the workload of anyone reading who tries to understand this configuration. However, one quick bit of help: "when the power is removed from the PIC the LED switches off but strangely comes back on if a high is applied to pin 3 (RA1)" - It seems you applied a voltage to RA1 when the MCU was unpowered. Don't apply a voltage to a pin on an unpowered MCU, even if that would be OK when the same MCU is powered. This can cause various problems, too long to explain here. Best of luck with the question. \$\endgroup\$ – SamGibson Jul 28 '17 at 14:43
  • \$\begingroup\$ Have a look at this video from eevBlog by Dave Jones to understand why LED can come on when you have no power to PIC. youtube.com/watch?v=2yFh7Vv0Paw Agree with SamGibson, please provide a schematic. \$\endgroup\$ – J Rodgers Jul 28 '17 at 15:00
  • \$\begingroup\$ Please see edit for schematic and additional info, code has been edited and a new PIC was programmed, new results are more LEDs illuminate while PIC is powered. \$\endgroup\$ – btommo Jul 28 '17 at 15:57
0
\$\begingroup\$

define TMR0_2 (TMR0 & 1<<2) //access to TMR0<2>

That's just a very poor form of programming. You have two choices:

  1. remember the priority of calculations; or

  2. use brackets liberally so you enforce the order of calculations to your liking.

it is designed to switch a relay when the angle of inclination is below 15 degrees and illuminates a series of LEDs ...

then code like that, instead of a set of states without any comments for you (later) or others trying to help you to understand easily what's going on.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.