thoughts on my project - Page 1
Forum section: electronics / projects

author: ali6x944
author_rank: Frequent Contributor
timestamp: January 08, 2020, 07:00:39 pm
content: Hi everyone,I'm posting to ask your opinion of my program structure, anyway I can optimize it or reduce its complexity without resorting to using MCC.so it is a derivation of an older project, I tried to reduce physical & syntax complexity by eliminating both the pain and confusion of using MCC and the low-power-mode pin:https://www.microchip.com/forums/m1024225.aspxthis project is not fully improved this project is not complete!!Code:/***************************************************************************************************************************** Author:Ali6x944* Date: 8/1/2020* Device: PIC16LF15313* Description: A program designed to run on PIC16LF15313, that facilitates a single-chip* solution to controlling 2 LED Panels/Arrays using a single multi-position slider switch and a pot to control brightness.****************************************************************************************************************************/// PIC16LF15313 Configuration Bit Settings// 'C' source line config statements// CONFIG1#pragma config FEXTOSC = OFF // External Oscillator mode selection bits (Oscillator not enabled)#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 = OFF // Clock Switch Enable bit (The NOSC and NDIV bits cannot be changed by user software)#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (FSCM timer disabled)// CONFIG2#pragma config MCLRE = ON // Master Clear Enable bit (MCLR pin is Master Clear function)#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)#pragma config LPBOREN = OFF // Low-Power BOR enable bit (ULPBOR disabled)#pragma config BOREN = OFF // Brown-out reset enable bits (Brown-out reset disabled)#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)#pragma config ZCD = OFF // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)#pragma config PPS1WAY = ON // Peripheral Pin Select one-way control (The PPSLOCK bit can be cleared and set only once in software)#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a reset)// CONFIG3#pragma config WDTCPS = WDTCPS_31// WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)#pragma config WDTE = OFF // WDT operating mode (WDT Disabled, SWDTEN is ignored)#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)#pragma config WDTCCS = SC // WDT input clock selector (Software Control)// CONFIG4#pragma config BBSIZE = BB512 // Boot Block Size Selection bits (512 words boot block size)#pragma config BBEN = OFF // Boot Block Enable bit (Boot Block disabled)#pragma config SAFEN = OFF // SAF Enable bit (SAF disabled)#pragma config WRTAPP = OFF // Application Block Write Protection bit (Application Block not write protected)#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block not write protected)#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration Register not write protected)#pragma config WRTSAF = OFF // Storage Area Flash Write Protection bit (SAF not write protected)#pragma config LVP = ON // Low Voltage Programming Enable bit (Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.)// CONFIG5#pragma config CP = OFF // UserNVM Program memory code protection bit (UserNVM code protection disabled)// #pragma config statements should precede project file includes.// Use project enums instead of #define for ON and OFF.#include <xc.h>#include <limits.h>#include <stdint.h>unsigned short RESULT; // ADC RESULT VARIABLE__bit BIG_SW; // VARIABLE INDICATING STATE OF BIG_SWITCH CONTROLLING BIG PANEL__bit SMALL_SW; // VARIABLE INDICATING STATE OF SMALL_SWITCH CONTROLING SMALL PANELint main(void){OSCFRQ=0b010; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 4MHzTRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGCCP1PPSbits.CCP1PPS=0b00000; // BIG LIGHT DRIVER (PWM), OUTPUTCCP2PPSbits.CCP2PPS=0b00001; // SMALL LIGHT DRIVER (PWM), OUTPUTADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SWSMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SWwhile(1){ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITSwhile(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ONRESULT=0b0000000000; // CLEAR THE VARIABLERESULT=ADRESH; // ADRESH IS IN THE LOWER 8 BITSRESULT=RESULT<<8; // ADRESH IS SHIFTED UP 8 BIT TO CORRECT LOCATIONRESULT=RESULT|ADRESL; //ADRESL IS JOINTED TO THE RESULT VARIABLE}while(BIG_SW==1||SMALL_SW==1){PMD1bits.TMR2MD=0b0; // TIMER2 MOUDLE ENABLEDT2CLKCONbits.CS=0b0011; // TIMER2 CLOCK SOURCE SELECT BIT (HFINTOSC)CCP1CONbits.CCP1FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP1CONbits.CCP1MODE=0b1111; // MODE IS SET TO PWM}}so TBH I am stuck trying to configure TIMER2 and CCP1 and 2 registers.I am still a noobie who is figuring out how C standards and XC8 peculiarities tie together.hopefully, I can implement low power mode using only a logical operand of BIG_SW and SMALL_SW for if neither one of them is high the low power mode is engaged.as for the file this time I am only using a single main.c file without any config.h file or anything other files to keep it simple.I would love to see your suggestions or good advice with regards to PWM situationthanks a lot.

author: ali6x944
author_rank: Frequent Contributor
timestamp: January 09, 2020, 05:58:36 am
content: how would the ccp module work?

author: ali6x944
author_rank: Frequent Contributor
timestamp: January 12, 2020, 02:27:42 pm
content: So here is what I cam up with for the weird ccp PWM module in the PIC16LF15313Code:/***************************************************************************************************************************** Author:Ali6x944* Date: 8/1/2020* Device: PIC16LF15313* Description: A program designed to run on PIC16LF15313, that facilitates a single-chip* solution to controlling 2 LED Panels/Arrays using a single multi-position slider switch and a pot to control brightness.****************************************************************************************************************************/// PIC16LF15313 Configuration Bit Settings// 'C' source line config statements// CONFIG1#pragma config FEXTOSC = OFF // External Oscillator mode selection bits (Oscillator not enabled)#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 = OFF // Clock Switch Enable bit (The NOSC and NDIV bits cannot be changed by user software)#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (FSCM timer disabled)// CONFIG2#pragma config MCLRE = ON // Master Clear Enable bit (MCLR pin is Master Clear function)#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)#pragma config LPBOREN = OFF // Low-Power BOR enable bit (ULPBOR disabled)#pragma config BOREN = OFF // Brown-out reset enable bits (Brown-out reset disabled)#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)#pragma config ZCD = OFF // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)#pragma config PPS1WAY = ON // Peripheral Pin Select one-way control (The PPSLOCK bit can be cleared and set only once in software)#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a reset)// CONFIG3#pragma config WDTCPS = WDTCPS_31// WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)#pragma config WDTE = OFF // WDT operating mode (WDT Disabled, SWDTEN is ignored)#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)#pragma config WDTCCS = SC // WDT input clock selector (Software Control)// CONFIG4#pragma config BBSIZE = BB512 // Boot Block Size Selection bits (512 words boot block size)#pragma config BBEN = OFF // Boot Block Enable bit (Boot Block disabled)#pragma config SAFEN = OFF // SAF Enable bit (SAF disabled)#pragma config WRTAPP = OFF // Application Block Write Protection bit (Application Block not write protected)#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block not write protected)#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration Register not write protected)#pragma config WRTSAF = OFF // Storage Area Flash Write Protection bit (SAF not write protected)#pragma config LVP = ON // Low Voltage Programming Enable bit (Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.)// CONFIG5#pragma config CP = OFF // UserNVM Program memory code protection bit (UserNVM code protection disabled)// #pragma config statements should precede project file includes.// Use project enums instead of #define for ON and OFF.#include <xc.h>#include <limits.h>#include <stdint.h>unsigned short RESULT; // ADC RESULT VARIABLE__bit BIG_SW; // VARIABLE INDICATING STATE OF BIG_SWITCH CONTROLLING BIG PANEL__bit SMALL_SW; // VARIABLE INDICATING STATE OF SMALL_SWITCH CONTROLING SMALL PANELint main(void){OSCFRQ=0b010; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 4MHzTRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGCCP1PPSbits.CCP1PPS=0b00000; // BIG LIGHT DRIVER (PWM->RA4), OUTPUTCCP2PPSbits.CCP2PPS=0b00001; // SMALL LIGHT DRIVER (PWM->RA5), OUTPUTADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SWSMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SWwhile(1){ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITSwhile(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ONRESULT=0b0000000000; // CLEAR THE VARIABLERESULT=ADRESH; // ADRESH IS IN THE LOWER 8 BITSRESULT=RESULT<<8; // ADRESH IS SHIFTED UP 8 BIT TO CORRECT LOCATIONRESULT=RESULT|ADRESL; //ADRESL IS JOINTED TO THE RESULT VARIABLE}while(BIG_SW==1||SMALL_SW==1){PMD1bits.TMR2MD=0b0; // TIMER2 MOUDLE ENABLEDT2CONbits.CKPS=0b000; //TIMER2 PRESCALER SET TO 1:1T2CONbits.OUTPS=0b0000; //TIMER2 POST-SCALER SET TO 1:1T2PRbits.T2PR=0b01100011; // PR2 REGESTER SET TO 99T2CLKCONbits.CS=0b0011; // TIMER2 CLOCK SOURCE SELECT BIT (HFINTOSC)if(BIG_SW==1){CCP1CONbits.CCP1FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP1CONbits.CCP1MODE=0b1111; // MODE IS SET TO PWMCCPR1Hbits.RH=RESULT&0b01;CCPR1Hbits.RH=RESULT&0b10;CCPR1Lbits.RL=RESULT<<8;T2CONbits.T2ON=0b1;}if(SMALL_SW==1){CCP2CONbits.CCP2FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP2CONbits.CCP2MODE=0b1111; // MODE IS SET TO PWMCCPR2Hbits.RH=RESULT&0b01;CCPR2Hbits.RH=RESULT&0b10;CCPR2Lbits.RL=RESULT<<8;T2CONbits.T2ON=0b1;}}}Any thoughts on it?plz i need all the help i can getnot sure of how those bitwise operations work

author: Prehistoricman
author_rank: Regular Contributor
timestamp: January 12, 2020, 08:13:43 pm
content: Quote from: ali6x944 on January 12, 2020, 02:27:42 pmWhat's the issue? You should be able to find a bunch of resources online regarding bitwise operations. Essentially, for registers, they will be setting or resetting particular bits to do a particular operation.You're asking very general questions that probably most people don't know how to answer. If you have some specific issue related to a single operation (for example) then you're more likely to get an answer to question about it.

author: ali6x944
author_rank: Frequent Contributor
timestamp: January 15, 2020, 08:06:08 am
content: Quote from: Prehistoricman on January 12, 2020, 08:13:43 pmsorry about that, I am kind of a huge noob in this regard so my questions may be quite general cus IDK what makes my programs fail -or work for that matter-however, there are 4 issues I am trying to solve:1) configuration of pwm (ccp/timer2)2) pps configuration ccp out3)Adc configuration4) program structure: loops inside main() vs. user-defined functionsthis light dimmer controller is designed for video recording applications -so it has to be of high frequency- to avoid flickering.I really don't have any issues with memory or ram usage so far, as I have most of the memory still vacant...thx for all help and replys

author: Prehistoricman
author_rank: Regular Contributor
timestamp: January 15, 2020, 05:30:55 pm
content: http://ww1.microchip.com/downloads/en/DeviceDoc/PIC16-L-F15313_23-Data-Sheet-40001897B.pdfThis is the data sheet for the PIC16LF15313. It contains info about all the registers you need to edit to configure those peripherals.Section 14 is for IO. Section 29 PWM. Section 20 ADC.You're still not asking specific questions. The idea behind helping people on a forum is that both sides need to contribute. Unless your task is trivial, nobody's going to solve it for you. And you need to help the helpers to help you.You say you're stuck. Stuck trying to do what?!

author: ali6x944
author_rank: Frequent Contributor
timestamp: January 15, 2020, 07:39:59 pm
content: @Prehistoricman, I am sorry if I was still vagueso let's start with PWM, I was following a gr8 tutorial made by deep blue embedded about the subject:https://deepbluembedded.com/pwm-pulse-width-modulation-tutorial/and encountered a problem here as the ccp module in the pic16f877a has a separate slave register (CCPR1H) to load the duty cycle info from CCPR1L register with extra two bits from the CCP1CON register; while the pic16lf15313 has both registers stuck together in the diagram page.303, i am confused about if the ccpr1h is still a slave register or not, however, I have treated it as not after reading this in PWM configuration section page.304:Quotein this case, what exactly is the point of the FMT bit in CCP1CON if I can apparently write to both registers?and can I treat them as one 16bit or one 8 and one 2-bit registers basically similar to the tutorial?also, is there a more efficient way to load the value of the "RESULT" variable to both registers without doing any bitwise operations?is aCode:#define _XTAL_FREQneeded if I use an internal oscillator, or is setting OSCFRQ only more appropriate?and for the oscillator, there is a bit to basically fine adjust the frequency OSCTUNE, do I have to declare it too or can I just leave it?

author: Prehistoricman
author_rank: Regular Contributor
timestamp: January 16, 2020, 02:52:35 am
content: Great, that is much easier to answer.Quote from: ali6x944 on January 15, 2020, 07:39:59 pmCCPR1H is not a slave register. I think the registers in the newer chip make a lot more sense. The CCPR1 H/L act as normal high/low registers stuck together to form a 16-bit word. The FMT value selects if the upper 10 bits or the lower 10 bits of that word are used in the comparison with the timer (this feature is a bit odd if you ask me).QuoteYou may be able to treat it as one register if your C library supports it. The name would probably be CCPR1.Alternatively, yes, use both the high and low to set your 10-bit value.Quote from: ali6x944 on January 15, 2020, 07:39:59 pmRESULT is an unsigned short, which I think means a byte. I would advise not to use old C types but rather stdint types like uint8_t, int32_t, etc. as these are more explicit and readable. At the place I work, we run an automated tool that highlights use of built-in types as a problem.I don't entirely understand you question about _XTAL_FREQ and OSCFRQ. If you want to set the PWM to be at a specific frequency, then you must know the clock frequency as well so you can properly calculate the number of cycles needed. If you're using the internal oscillator, then yes, set OSCFRQ and you can then base your later calculations off of whatever frequency you chose.You may leave OSCTUNE.

author: ali6x944
author_rank: Frequent Contributor
timestamp: January 16, 2020, 12:33:31 pm
content: that is interesting, so in the uint16_t would be the most suitable for the "RESULT" var, is there any possibility for uint10_t or some other unsigned 10-bit datatype in XC8?Code:uint16_t RESULT; // ADC RESULT VARIABLE...if(BIG_SW==1){CCP1CONbits.CCP1FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP1CONbits.CCP1MODE=0b1111; // MODE IS SET TO PWMCCPR1=RESULT;PIR4bits.TMR2IF=0b0;T2CONbits.T2ON=0b1;}So this is how it will be implemented, right? from my understanding, it will be fully loaded by the variable, but will the extra 6 just be ignored with a right-justified RESULT var?now do I need to configure the LAT register for the PWM out?for the ADC setup, I think the only question that comes to mind is ADFM bit of the ADCON1 register is manipulating it necessary when I am loading the result?Code:ADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)...while(1){ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITSwhile(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ONRESULT=0b0000000000; // CLEAR THE VARIABLERESULT=ADRESH; // ADRESH IS IN THE LOWER 8 BITSRESULT=RESULT<<8; // ADRESH IS SHIFTED UP 8 BIT TO CORRECT LOCATIONRESULT=RESULT|ADRESL; //ADRESL IS JOINTED TO THE RESULT VARIABLE}

author: Prehistoricman
author_rank: Regular Contributor
timestamp: January 16, 2020, 01:06:45 pm
content: I'm saying there is a chance your library supports this 16-bit combined register CCPR1. Just try it! I don't know anything about it. You could also read the header files where these names are defined.If you're using a proper IDE, you can follow names to where they are defined, so this is very helpful.No, you don't get 10-bit data types.Your DAC is 10-bit so you will have to use a 16-bit uint.Can you expand on your question about the LAT register? I can't find it in the datasheet.ADFM basically does the same thing as the FMT bit. Just as with FMT, I would set it and leave it (in setup code, not the loop).Code:RESULT=0b0000000000; // CLEAR THE VARIABLERESULT=ADRESH; // ADRESH IS IN THE LOWER 8 BITSRESULT=RESULT<<8; // ADRESH IS SHIFTED UP 8 BIT TO CORRECT LOCATIONRESULT=RESULT|ADRESL; //ADRESL IS JOINTED TO THE RESULT VARIABLEThis code is not great. You don't have to clear RESULT before loading it with anything else. You should also make use of C's assignment operators. I would write this on one or two lines, as such:Code:RESULT = ADRESH << 8 | ADRESL; // Load ADC valueRESULT = ADRESH << 8; //Load ADC high valueRESULT |= ADRESL; //Load ADC low value

author: rstofer
author_rank: Super Contributor
timestamp: January 18, 2020, 10:07:50 pm
content: Given that you never exit the while(1) loop, how do you expect to get to the while(BIG_SW==1||SMALL_SW==1) loop?

author: ali6x944
author_rank: Frequent Contributor
timestamp: January 21, 2020, 03:45:15 pm
content: Quote from: rstofer on January 18, 2020, 10:07:50 pmcan't the PIC run both loops? if not, what is the best way to exit the loop yet periodically read the pot ANSA2?Quote from: Prehistoricman on January 16, 2020, 01:06:45 pmcool, I'm using MPLABX IDE, XC8 (2.00V), so if a word turns blue it is supported, right?I searched about the definition in the project files and I came empty-handed, I think I'm missing something as usualQuote from: Prehistoricman on January 16, 2020, 01:06:45 pmand with regards to LATx register, my question was:do I need to configure the LATx register to get pwm out of the CCPx register? or is not need as the ccp_out pps is enough?

author: Prehistoricman
author_rank: Regular Contributor
timestamp: January 21, 2020, 11:42:48 pm
content: Quote from: ali6x944 on January 21, 2020, 03:45:15 pmHaha... good joke.I guess you have little programming experience. The fundamental idea behind C code is that it goes from top to bottom in order of execution. You have no defined exit to that first loop so the 2nd one will never get reached. Even if you did reach the second loop, you never update BIG_SW or SMALL_SW and you would probably fall out of main(). A good practice is to have an empty infinite loop at the end of main() so you will never ever return from main().You need to have a think about how the processor will run the code you've written, and how you should rewrite it to function as you wish.Quote from: ali6x944 on January 21, 2020, 03:45:15 pmI don't know how MPLABX functions. Again, just try it. The answers to these questions should become apparent just by pressing buttons and figuring out how the IDE works. You can always just build the project and see what fails (bad practice but it works).Quote from: ali6x944 on January 21, 2020, 03:45:15 pmI don't see LATx configuring in the PWM section so yeah I assume that is not necessary. LATx is just the output data and if you're using a peripheral, there's no need to set this because it's bypassed.You do however need to set the RxyPPS register as it says on page 314.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 12, 2020, 05:35:38 am
content: hi again,so I tried to make adc_result into a function but it seems not to work, the error messages seem confusing to me...Code:uint16_t RESULT; // ADC RESULT VARIABLE__bit BIG_SW; // VARIABLE INDICATING STATE OF BIG_SWITCH CONTROLLING BIG PANEL__bit SMALL_SW; // VARIABLE INDICATING STATE OF SMALL_SWITCH CONTROLING SMALL PANELvoid ADC_RESULT(uint16_t RESULT){ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITSwhile(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ONRESULT = ADRESH << 8; //Load ADC high valueRESULT |= ADRESL; //Load ADC low valuereturn RESULT;}int main(void){OSCFRQ=0b010; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 4MHzTRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGCCP1PPSbits.CCP1PPS=0b00000; // BIG LIGHT DRIVER (PWM->RA4), OUTPUTCCP2PPSbits.CCP2PPS=0b00001; // SMALL LIGHT DRIVER (PWM->RA5), OUTPUTADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SWSMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SWwhile(BIG_SW==1||SMALL_SW==1){PMD1bits.TMR2MD=0b0; // TIMER2 MOUDLE ENABLEDT2CONbits.CKPS=0b000; //TIMER2 PRESCALER SET TO 1:1T2CONbits.OUTPS=0b0000; //TIMER2 POST-SCALER SET TO 1:1T2PRbits.T2PR=0b01100011; // PR2 REGESTER SET TO 99T2CLKCONbits.CS=0b0011; // TIMER2 CLOCK SOURCE SELECT BIT (HFINTOSC)CCP1CONbits.CCP1FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP1CONbits.CCP1MODE=0b1111; // MODE IS SET TO PWMCCP2CONbits.CCP2FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP2CONbits.CCP2MODE=0b1111; // MODE IS SET TO PWMif(BIG_SW==1){ADC_RESULT();CCPR1=RESULT;PIR4bits.TMR2IF=0b0;T2CONbits.T2ON=0b1;}if(SMALL_SW==1){ADC_RESULT();CCPR2=RESULT;PIR4bits.TMR2IF=0b0;T2CONbits.T2ON=0b1;}}}and the error messages were:Code:main.c:65:9: error: void function 'ADC_RESULT' should not return a value [-Wreturn-type]return RESULT;^ ~~~~~~main.c:106:24: error: too few arguments to function call, single argument 'RESULT' was not specifiedADC_RESULT();~~~~~~~~~~ ^main.c:59:1: note: 'ADC_RESULT' declared herevoid ADC_RESULT(uint16_t RESULT)^main.c:113:24: error: too few arguments to function call, single argument 'RESULT' was not specifiedADC_RESULT();~~~~~~~~~~ ^main.c:59:1: note: 'ADC_RESULT' declared herevoid ADC_RESULT(uint16_t RESULT)^3 errors generated.BUILD FAILED (exit value 2, total time: 1s)so I tried to fix it by removing the return RESULT, and the uint16_t RESULT from inside void ADC_RESULT(uint16_t RESULT)...Code:CLEAN SUCCESSFUL (total time: 1ms)main.c:120:1: warning: control reaches end of non-void function [-Wreturn-type]}^1 warning generated.Memory Summary:Program space used 88h ( 136) of 800h words ( 6.6%)Data space used 8h ( 8) of 100h bytes ( 3.1%)EEPROM space None availableData stack space used 0h ( 0) of F0h bytes ( 0.0%)Configuration bits used 5h ( 5) of 5h words (100.0%)ID Location space used 0h ( 0) of 4h bytes ( 0.0%)BUILD SUCCESSFUL (total time: 2s)Loading completedhowever not really sure how to get rid of the 120:1: warning and not really sure what it does...now is it necessary with my current code set up to do the same with the PWM ccp code sections?also with this new ADC_result function, will the micro keep looping it when it enters either the if(SMALL_SW==1) or if(BIG_SW==1)?

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 12, 2020, 12:02:11 pm
content: Functions always specify a result type before the function name. If it's any type except for void, that means the function returns a value. Functions that do return must have a return statement. Functions that don't return must not have a return statement.In the way you've set up your ADC_RESULT function, you shouldn't return. You're using a global variable RESULT to store the ADC_RESULT rather than a return value and return statement.You've also incorrectly set up ADC_RESULT to accept an argument called RESULT. You can remove that. That's why your calls to ADC_RESULT are causing errors.Again, you don't want to ever leave main(). Your while loop will end if BIG_SW and SMALL_SW are not 1. The function will attempt to return to god knows where and if you're lucky, the microcontroller will reset.And again, you're not updating BIG_SW or SMALL_SW. You only read from the GPIO port once.So, my suggested changes are:Remove the condition from the while loop and change it to while (true) or while (1). This is known as an infinite loop.Inside the loop, read the button values into BIG_SW and SMALL_SW.Think about all the register operations you have in the loop there. Do you need to run these all the time?

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 12, 2020, 08:55:12 pm
content: Quote from: Prehistoricman on March 12, 2020, 12:02:11 pmok cool, so the function ADC_RESULT will become:Code:uint16_t ADC_RESULT(){ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITSwhile(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ONRESULT = ADRESH << 8; //Load ADC high valueRESULT |= ADRESL; //Load ADC low value}main(){...}Quote from: Prehistoricman on March 12, 2020, 12:02:11 pmfor the updating of BIG_SW and SMALL_SW value, how can I do it without interrupting the PWM and ADC read cycle?I was planing the for the addition of a sleep condition in the loop were if neither BIG_SW and SMALL_SW==1 then the micro goes to sleep.Quote from: Prehistoricman on March 12, 2020, 12:02:11 pmfor the run time I would say the ADC AND TMR2 CCP1 are the only things that should run all the time.I am trying to figure out if the sleep condition gonna screw up with something...

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 12, 2020, 10:16:31 pm
content: Quote from: ali6x944 on March 12, 2020, 08:55:12 pmAlmost. Change the return type from uint16_t to void. This means the function does not return a value.Quote from: ali6x944 on March 12, 2020, 08:55:12 pmReading two bits from IO is hardly interrupting. What do you think the problem might be? The PWM module should continue doing its thing regardless of how long ADC readout or IO polling might take.If you want to move to dealing with sleep, there's a couple of things to consider:Pressing the buttons should wake the microcontroller (right?), so they need to be interrupt-driven, and the IO needs to be set up to deliver interrupts.Does the PWM module operate in sleep mode? Some chips have multiple levels of sleep.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 14, 2020, 08:19:31 am
content: Quote from: Prehistoricman on March 12, 2020, 10:16:31 pmwell, hopefully, it will wake up if the state of the SMALL/BIG_SW changes or if the value of RESULT variable changes? not sure if this is possible??after a bit of reading thou I think going for a combination of doze mode during operation and idle mode in the off condition is a good idea:Quotefor one I will get a lower power consumption during operation and power-down, and relatively easy wake-up code -I think-.the questions become how can I implement them in the loop?I was thinking of something like this:Code:...int main(){...[the doze mode setup]while(BIG_SW==1||SMALL_SW==1){...}if (BIG_SW!=1&&SMALL_SW!=1){[sleep mode setup]}}

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 14, 2020, 12:41:52 pm
content: Quote from: ali6x944 on March 14, 2020, 08:19:31 amNot really. Sleep generally halts or resets the CPU. You have no variables, code execution, whatever. You won't be able to initiate ADC reads at all.This doze mode is interesting though. It basically slows down the CPU. Probably doesn't save a lot of power compared to idle/sleep.Quote from: ali6x944 on March 14, 2020, 08:19:31 amThat could work. You can move the sleep stuff to be after the loop. You drop out of the loop when neither button is pressed, then go to sleep.Make sure you have the interrupts for wake-up set up on your two button GPIOs.You should always (again) make sure that main() ends with an infinite loop. So after initialising sleep, loop forever.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 14, 2020, 03:11:32 pm
content: Quote from: Prehistoricman on March 14, 2020, 12:41:52 pmwell, can I implement that by a simple While(1) loop which the while(BIG_SW==1||SMALL_SW==1) and an if statement where the sleep instruction is placed?and for the interrupts, I really don't know how to set up those; but here I go so bear with me:Quoteso according to this, the peripheral used to wake up the CPU must be able to operate without the system clock, and here we will be using BIG/SMALL_SW as our interrupt source, the question is how many external interrupt pins do I have? here I found two different things in the datasheet, a External interrupt input and Interrupt-on-change input both can wake up the cpu from sleep...so I looked up this IOC thingy and came up with this:Quoteso this looks more promising, so I have to set the ioc and IOCIE bit of the PIE0 registers for both RA4 and RA5 which is my BIG/SMALL_SW pins to falling edge trigger...So this is what I came with, notice I did not include the idle setup yet:Code:int main(void){OSCFRQ=0b010; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 4MHzTRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGCCP1PPSbits.CCP1PPS=0b00000; // BIG LIGHT DRIVER (PWM->RA4), OUTPUTCCP2PPSbits.CCP2PPS=0b00001; // SMALL LIGHT DRIVER (PWM->RA5), OUTPUTADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SWSMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SWPIE0bits.IOCIE=1;//INTERUPT-ON-CHANGE ENABLE BIT IS SETIOCANbits.IOCAN4=1;//INTERUPT-ON-CHANGE PORTA (RA4) NEGATIVE EDGE TRIGGEREDIOCANbits.IOCAN5=1;//INTERUPT-ON-CHANGE PORTA (RA5) NEGATIVE EDGE TRIGGEREDwhile(1){while(BIG_SW==1||SMALL_SW==1){PMD1bits.TMR2MD=0b0; // TIMER2 MOUDLE ENABLEDT2CONbits.CKPS=0b000; //TIMER2 PRESCALER SET TO 1:1T2CONbits.OUTPS=0b0000; //TIMER2 POST-SCALER SET TO 1:1T2PRbits.T2PR=0b01100011; // PR2 REGESTER SET TO 99T2CLKCONbits.CS=0b0011; // TIMER2 CLOCK SOURCE SELECT BIT (HFINTOSC)CCP1CONbits.CCP1FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP1CONbits.CCP1MODE=0b1111; // MODE IS SET TO PWMCCP2CONbits.CCP2FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP2CONbits.CCP2MODE=0b1111; // MODE IS SET TO PWMif(BIG_SW==1){ADC_RESULT();CCPR1=RESULT;PIR4bits.TMR2IF=0b0;T2CONbits.T2ON=0b1;}if(SMALL_SW==1){ADC_RESULT();CCPR2=RESULT;PIR4bits.TMR2IF=0b0;T2CONbits.T2ON=0b1;}}if (BIG_SW==0&&SMALL_SW==0){SLEEP;}}}the sleep thou gave me an error:Code:main.c:130:13: error: use of undeclared identifier 'SLEEP'

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 14, 2020, 07:03:33 pm
content: Is the instruction called sleep? If so, you can write it in inline assembly:asm volatile("sleep")

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 14, 2020, 07:07:39 pm
content: it gave me another error:Code:main.c:130:13: error: use of undeclared identifier 'asm'

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 14, 2020, 07:58:32 pm
content: Google says try to use __asm__ instead

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 15, 2020, 05:49:36 am
content: Quote from: Prehistoricman on March 14, 2020, 07:58:32 pmthat worksbut will it wake up if the IOC flag is set? or does it need a special interrupt routine/function?and for the doze mode will the reduction in cpu speed effect the RESULT update in the ccp register?

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 15, 2020, 01:06:51 pm
content: Quote from: ali6x944 on March 15, 2020, 05:49:36 amGenerally the CPU wakes up on interrupt. So interrupt on change should make wake on change. Just try it dude!I don't see why CPU speed would affect any of the peripherals. The peripherals still run on the fast clock and they should operate as normal.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 15, 2020, 02:33:03 pm
content: it didn't work at allIDK WTF is going on...maybe I messed something up in my ccp register code or it is not leaving sleepCode:/***************************************************************************************************************************** Author:Ali6x944* Date: 8/1/2020* Device: PIC16LF15313* Description: A program designed to run on PIC16LF15313, that facilitates a single-chip* solution to controlling 2 LED Panels/Arrays using a single multi-position slider switch and a pot to control brightness.****************************************************************************************************************************/// PIC16LF15313 Configuration Bit Settings// 'C' source line config statements// CONFIG1#pragma config FEXTOSC = OFF // External Oscillator mode selection bits (Oscillator not enabled)#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 = OFF // Clock Switch Enable bit (The NOSC and NDIV bits cannot be changed by user software)#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (FSCM timer disabled)// CONFIG2#pragma config MCLRE = ON // Master Clear Enable bit (MCLR pin is Master Clear function)#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)#pragma config LPBOREN = OFF // Low-Power BOR enable bit (ULPBOR disabled)#pragma config BOREN = OFF // Brown-out reset enable bits (Brown-out reset disabled)#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)#pragma config ZCD = OFF // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)#pragma config PPS1WAY = ON // Peripheral Pin Select one-way control (The PPSLOCK bit can be cleared and set only once in software)#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a reset)// CONFIG3#pragma config WDTCPS = WDTCPS_31// WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)#pragma config WDTE = OFF // WDT operating mode (WDT Disabled, SWDTEN is ignored)#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)#pragma config WDTCCS = SC // WDT input clock selector (Software Control)// CONFIG4#pragma config BBSIZE = BB512 // Boot Block Size Selection bits (512 words boot block size)#pragma config BBEN = OFF // Boot Block Enable bit (Boot Block disabled)#pragma config SAFEN = OFF // SAF Enable bit (SAF disabled)#pragma config WRTAPP = OFF // Application Block Write Protection bit (Application Block not write protected)#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block not write protected)#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration Register not write protected)#pragma config WRTSAF = OFF // Storage Area Flash Write Protection bit (SAF not write protected)#pragma config LVP = ON // Low Voltage Programming Enable bit (Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.)// CONFIG5#pragma config CP = OFF // UserNVM Program memory code protection bit (UserNVM code protection disabled)// #pragma config statements should precede project file includes.// Use project enums instead of #define for ON and OFF.#include <xc.h>#include <limits.h>#include <stdint.h>/*VARIABLE DEFFENITION SECTION*/uint16_t RESULT; // ADC RESULT VARIABLE__bit BIG_SW; // VARIABLE INDICATING STATE OF BIG_SWITCH CONTROLLING BIG PANEL__bit SMALL_SW; // VARIABLE INDICATING STATE OF SMALL_SWITCH CONTROLING SMALL PANEL/*FUNCTION INTITILIZATION SECTION*/void ADC_RESULT(){ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITSwhile(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ONRESULT = ADRESH << 8; //Load ADC high valueRESULT |= ADRESL; //Load ADC low value}/*MAIN LOOP*/int main(void){OSCFRQ=0b010; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 4MHzTRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGCCP1PPSbits.CCP1PPS=0b00000; // BIG LIGHT DRIVER (PWM->RA4), OUTPUTCCP2PPSbits.CCP2PPS=0b00001; // SMALL LIGHT DRIVER (PWM->RA5), OUTPUTADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SWSMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SWPIE0bits.IOCIE=1;//INTERUPT-ON-CHANGE ENABLE BIT IS SETIOCANbits.IOCAN4=1;//INTERUPT-ON-CHANGE PORTA (RA4) NEGATIVE EDGE TRIGGEREDIOCANbits.IOCAN5=1;//INTERUPT-ON-CHANGE PORTA (RA5) NEGATIVE EDGE TRIGGEREDwhile(1){while(BIG_SW==1||SMALL_SW==1){PMD1bits.TMR2MD=0b0; // TIMER2 MOUDLE ENABLEDT2CONbits.CKPS=0b000; //TIMER2 PRESCALER SET TO 1:1T2CONbits.OUTPS=0b0000; //TIMER2 POST-SCALER SET TO 1:1T2PRbits.T2PR=0b01100011; // PR2 REGESTER SET TO 99T2CLKCONbits.CS=0b0011; // TIMER2 CLOCK SOURCE SELECT BIT (HFINTOSC)CCP1CONbits.CCP1FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP1CONbits.CCP1MODE=0b1111; // MODE IS SET TO PWMCCP2CONbits.CCP2FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP2CONbits.CCP2MODE=0b1111; // MODE IS SET TO PWMif(BIG_SW==1){ADC_RESULT();CCPR1=RESULT;PIR4bits.TMR2IF=0b0;T2CONbits.T2ON=0b1;}if(SMALL_SW==1){ADC_RESULT();CCPR2=RESULT;PIR4bits.TMR2IF=0b0;T2CONbits.T2ON=0b1;}}if (BIG_SW==0&&SMALL_SW==0){__asm__("SLEEP");}}}Edit:I just removed the sleep section and it does not seem to work...this is the part that I removed:Code:if (BIG_SW==0&&SMALL_SW==0){__asm__("SLEEP");}

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 15, 2020, 03:38:34 pm
content: Are you sure you ever enter sleep?I keep telling you that you aren't updating the BIG_SW and SMALL_SW variables, but you aren't making any changes. Why?!I suggest you get your code working, forgetting about sleep (because your LED panels will consume far more power than the microcontroller). Work up from something that works.If you want to fix sleep, here's some ideas:You might need an interrupt handler for the interrupts you just enabled. With nothing to reset the interrupt request, the micro will not trigger additional interrupts.Blink an LED while the CPU is active. It will stop blinking when it goes to sleep.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 15, 2020, 03:49:50 pm
content: Quote from: Prehistoricman on March 15, 2020, 03:38:34 pmcool, so how do I do that? I mean the BIG_SW and SMALL_SW variables continues update

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 15, 2020, 08:07:44 pm
content: Well you already update them once:Code:BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SWSMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SWSo just run this inside the main loop.Your comments kind of highlights the misunderstanding. It's not 'assigned'. The value of the pins is read and that value is put into the variable.Consider this example:x = 2y = xx = 3What is y?In normal languages, it will be 2. The assignment of x to y means "the value of x is copied to y". If you only run the copy once, you get one copy.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 19, 2020, 08:18:58 am
content: ok so I think I did what u meant, and it didn't work, so I overdid it for good measure and it didn't workCode:/*MAIN LOOP*/int main(void){OSCFRQ=0b010; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 4MHzTRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGCCP1PPSbits.CCP1PPS=0b00000; // BIG LIGHT DRIVER (PWM->RA4), OUTPUTCCP2PPSbits.CCP2PPS=0b00001; // SMALL LIGHT DRIVER (PWM->RA5), OUTPUTADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)PIE0bits.IOCIE=1;//INTERUPT-ON-CHANGE ENABLE BIT IS SETIOCANbits.IOCAN4=1;//INTERUPT-ON-CHANGE PORTA (RA4) NEGATIVE EDGE TRIGGEREDIOCANbits.IOCAN5=1;//INTERUPT-ON-CHANGE PORTA (RA5) NEGATIVE EDGE TRIGGEREDwhile(1){BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SWSMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SWwhile(BIG_SW==1||SMALL_SW==1){PMD1bits.TMR2MD=0b0; // TIMER2 MOUDLE ENABLEDT2CONbits.CKPS=0b000; //TIMER2 PRESCALER SET TO 1:1T2CONbits.OUTPS=0b0000; //TIMER2 POST-SCALER SET TO 1:1T2PRbits.T2PR=0b01100011; // PR2 REGESTER SET TO 99T2CLKCONbits.CS=0b0011; // TIMER2 CLOCK SOURCE SELECT BIT (HFINTOSC)CCP1CONbits.CCP1FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP1CONbits.CCP1MODE=0b1111; // MODE IS SET TO PWMCCP2CONbits.CCP2FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)CCP2CONbits.CCP2MODE=0b1111; // MODE IS SET TO PWMif(BIG_SW==1){BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SWSMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SWADC_RESULT();CCPR1=RESULT;PIR4bits.TMR2IF=0b0;T2CONbits.T2ON=0b1;}if(SMALL_SW==1){BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SWSMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SWADC_RESULT();CCPR2=RESULT;PIR4bits.TMR2IF=0b0;T2CONbits.T2ON=0b1;}}}}I tried all combinations of the main loop and the subloops but it didn't work, I even got a new chip just to check I am not crazy and it doesn't seem to workjust as a form of sanity check, I went and removed the ccp and ADC stuff and just used the LATx register to output a high if its corresponding switch is high and it still didn't workso just to check that my chip isn't dead or something, I got a new one and tried it out and it didn't work with and without the trimmed codeso I trimmed the whole program down to a just blink a led at lata0 and it finally workedat this point, I have to follow an empirical approach, so I rewrote my program around the functioning blink program...so here is a rundown of all the code that seems to be screwing with the operation of the code:1)Code:OSCFRQ =0b010; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 4MHzapparently, this code seems to slow down the CPU for some reason so I fixed it by increasing the clock:Code:OSCFRQ =0b101; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 16MHzI also add a #define _XTAL_FREQ 4000000 to make the delay function work and will be removed later...2)reading and updating big switch, however, proved to be annoyingly difficult, I tried to do it inside the main loop, outside the main loop, in one IOC ISR, in two sperate IOC ISR, to the point of absolute insanityat this point I admit couldn't conditionally toggle a GPIO on or off if my life depended on it3)for both the ccp and ADC sanity check I had to rely on some conditional statement and let's just say that didn't go very well

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 19, 2020, 12:04:58 pm
content: Damn, that really sucks.Maybe you can try using the whole-port names instead of bitfields. Like:TRISA = 0x034; //RA0, 1 output. RA2, 4, 5 input(PORTA & 0x10) > 0 //Reads RA4(PORTA & 0x20) > 0 //Reads RA4

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 19, 2020, 12:22:11 pm
content: Quote from: Prehistoricman on March 19, 2020, 12:04:58 pmgive me a minute...Edit:that doesn't seem to work

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 19, 2020, 08:17:33 pm
content: Just to clarify: does 'doesn't work' mean that it compiles fine but doesn't run fine?Have you checked that the pins that you're outputting to are functioning normally? Did you do the LED check on these ones?Can you set an output to turn the LED on, then change its pin mode to be input? Does the LED go out? Do this in a loop with output both high and low, just for sanity checking.How are you compiling this? Perhaps this is a compilation issue.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 20, 2020, 10:22:16 am
content: Quote from: Prehistoricman on March 19, 2020, 08:17:33 pmexactly.Quote from: Prehistoricman on March 19, 2020, 08:17:33 pmyes, I did the LED check exclusively on the output pins (RA0, RA1), both timing and output voltage seem normal.Quote from: Prehistoricman on March 19, 2020, 08:17:33 pmSo what u want me to do is set (RA0, RA1) to be inputs? or am I missing something?Quote from: Prehistoricman on March 19, 2020, 08:17:33 pmdidn't understand the question? do you mean the compiler type? it is XC8 v2.00

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 20, 2020, 11:47:52 am
content: Quote from: ali6x944 on March 20, 2020, 10:22:16 amYeah. These are the steps:Set pin to be outputSet pin highdelaySet pin to be inputdelaySet pin to be outputSet pin lowdelaySet pin to be inputdelayloop (do it all again)When you configure the pin as an input, it should go high-impedance. So any LED connected will turn off. What you should see is that the LED is only turned on for one delay (set this to be 0.5s or 1s).This test is to confirm that setting the pin as an input is working correctly.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 21, 2020, 06:55:44 am
content: ok so here is the test code:Code:/*MAIN LOOP*/void main(void){OSCFRQ =0b101; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 16MHzwhile(1){TRISAbits.TRISA0=0;LATAbits.LATA0=1;__delay_ms(500);TRISAbits.TRISA0=1;__delay_ms(500);TRISAbits.TRISA0=0;LATAbits.LATA0=0;__delay_ms(500);TRISAbits.TRISA0=1;__delay_ms(500);}and here is a scope capture of the RA0 pin:

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 21, 2020, 07:07:51 am
content: do I test the other ones?cus it seems to work...however in when TRISA is 1, the chip gives around 60 Hz 500mv pk-pk ripple I don't know if that is normal, I suspect it is just interference coming through the mains because my scope is not earthed...

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 21, 2020, 12:50:11 pm
content: That looks great. The interference is actually great here because you can clearly see when the pin is high-impedance.So let's try reading that pin when it's configured as an input:Code:#include <stdbool.h>/*MAIN LOOP*/void main(void){OSCFRQ =0b101; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 16MHzbool read;while(1){TRISAbits.TRISA0=0; //outputLATAbits.LATA0=read;__delay_ms(500);TRISAbits.TRISA0=1; //input__delay_ms(100);read = PORTAbits.RA0;__delay_ms(400);}}This should set the output to be the same value as the input. Try pulling the pin low or high with a resistor (don't short it) and see if the output phase follows the input value.

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 21, 2020, 02:11:53 pm
content: Hold up.I found this amazing information source:https://www.microforum.cc/topic/6-what-is-the-difference-between-port-x-and-lat-x-on-pic16-and-pic18-microcontrollers-and-what-does-anselx-actually-do/This could certainly be related to your issue.The main takeaways are:Don't use PORTxbits for writing to pins, use LATxbitsSet ANSELxbits to 0 on all pins you want to read fromBut the whole thing is a good read to know why these pieces of advice hold.So try your pin-reading demos again with these changes.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 22, 2020, 05:21:10 pm
content: Quotewell, this is kinda what we did in the beginning, the only difference now is I had to specify all ANSELx register bits which I assumed where zero unless otherwise manipulated...Code:#define BIG_SW PORTAbits.RA4 //READ RA4 AND ASSIGN IT TO BIG_SW#define SMALL_SW PORTAbits.RA5 //READ RA5 AND ASSIGN IT TO SMALL_SW/*MAIN LOOP*/void main(void){OSCFRQ =0b101; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 16MHz/*TRISx AND ANSELx ASSIGNMENT */TRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA0=0; // ANSELA0(ANSA0) DISABLED, INPUT DIGITALANSELAbits.ANSA1=0; // ANSELA0(ANSA1) DISABLED, INPUT DIGITALANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGANSELAbits.ANSA4=0; // ANSELA4(ANSA4) DISABLED, INPUT DIGITALANSELAbits.ANSA5=0; // ANSELA5(ANSA5) DISABLED, INPUT DIGITALLATAbits.LATA1 = 0;LATAbits.LATA0 = 0;while(1){if(BIG_SW){LATAbits.LATA0 = 1; //LED ON}if(SMALL_SW){LATAbits.LATA1 = 1; //LED ON}else{LATAbits.LATA1 = 0;LATAbits.LATA0 = 0;}}}so, this is my sanity check, and it seems to work well, however, if both switches are high or low dose not go into the else condition...I later added these and it now goes to the else condition if both are low but when both are high the output is still high for some reason:Code:#define BIG_SW PORTAbits.RA4 //READ RA4 AND ASSIGN IT TO BIG_SW#define SMALL_SW PORTAbits.RA5 //READ RA5 AND ASSIGN IT TO SMALL_SW/*MAIN LOOP*/void main(void){OSCFRQ =0b101; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 16MHz/*TRISx AND ANSELx ASSIGNMENT */TRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA0=0; // ANSELA0(ANSA0) DISABLED, INPUT DIGITALANSELAbits.ANSA1=0; // ANSELA0(ANSA1) DISABLED, INPUT DIGITALANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGANSELAbits.ANSA4=0; // ANSELA4(ANSA4) DISABLED, INPUT DIGITALANSELAbits.ANSA5=0; // ANSELA5(ANSA5) DISABLED, INPUT DIGITALLATAbits.LATA1 = 0;LATAbits.LATA0 = 0;while(1){if(BIG_SW){LATAbits.LATA0 = 1; //LED ONLATAbits.LATA1 = 0; //LED off}if(SMALL_SW){LATAbits.LATA1 = 1; //LED ONLATAbits.LATA0 = 0; //LED off}else{LATAbits.LATA1 = 0;LATAbits.LATA0 = 0;}}}

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 22, 2020, 05:44:39 pm
content: now I found a weird thing also when I checked the signal on the scope:1)PHOTO_1:when RA0 is high and RA1 is low...and for some reason, RA1 oscillates??so I was kinda confused so I fired up channel 2 of my scope and here is what I got not that the blue is RA0 and the yellow RA1:2)PHOTO_2:is when both are on, they also oscillate.3)PHOTO_3:when RA1 is high and RA0 is low, no oscillation???4)PHOTO_4:when RA0 is high and RA1 is low, but this frame is with measurement.

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 22, 2020, 08:59:52 pm
content: Code:if(BIG_SW){LATAbits.LATA0 = 1; //LED ONLATAbits.LATA1 = 0; //LED off}if(SMALL_SW){LATAbits.LATA1 = 1; //LED ONLATAbits.LATA0 = 0; //LED off}else{LATAbits.LATA1 = 0;LATAbits.LATA0 = 0;}This is where something is probably going wrong.'else' only pairs up with one 'if'. So the first if statement is not exclusive with the second. In other words, both can happen.You probably meant to have 'else if' on the second one.Quote from: ali6x944 on March 22, 2020, 05:44:39 pmTo clarify, in this whole post you were talking about only RA0 and RA1, not RA4 and RA5 (your inputs). You don't mean that, right?

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 23, 2020, 05:33:01 am
content: Quote from: Prehistoricman on March 22, 2020, 08:59:52 pmcorrect, this is exclusively the output behavior of RA0 and RA1.Quote from: Prehistoricman on March 22, 2020, 08:59:52 pmso I did that and it still doesn't enter the else condition:Code:while(1){if(BIG_SW){LATAbits.LATA0 = 1; //LED ONLATAbits.LATA1 = 0; //LED off}else if(SMALL_SW){LATAbits.LATA1 = 1; //LED ONLATAbits.LATA0 = 0; //LED off}else{LATAbits.LATA1 = 0;LATAbits.LATA0 = 0;}}now the oscilations are gone completly, and it turns off when both (RA4,RA5) are low, which is good.however, it still dose not turn off when both (RA4,RA5) are high, instade RA0 goes high when both (RA4,RA5) are high.

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 23, 2020, 01:04:19 pm
content: Your buttons probably short the pin to ground.

author: ali6x944
author_rank: Frequent Contributor
timestamp: March 23, 2020, 03:05:29 pm
content: Quote from: Prehistoricman on March 23, 2020, 01:04:19 pmnot really, RA4 and RA5 are pulled to ground by 1k resistors and the buttons are jumper wires, so no it is not shorting, but it is always connected to ground via the 1k pulldown resistor...

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 23, 2020, 05:23:48 pm
content: So they short to Vcc? Can you give a wiring diagram/schematic?Notice you don't have a condition in the code for both buttons being high. BIG_SW has priority over SMALL_SW.

author: ali6x944
author_rank: Frequent Contributor
timestamp: April 03, 2020, 04:41:24 pm
content: so this the current wiring is attached below...also, I have modified the code to solve the problem to this now:Code:/*MAIN FUNCTION*/void main(void){OSCFRQ =0b101; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 16MHz/*TRISx AND ANSELx ASSIGNMENT */TRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA0=0; // ANSELA0(ANSA0) DISABLED, INPUT DIGITALANSELAbits.ANSA1=0; // ANSELA0(ANSA1) DISABLED, INPUT DIGITALANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGANSELAbits.ANSA4=0; // ANSELA4(ANSA4) DISABLED, INPUT DIGITALANSELAbits.ANSA5=0; // ANSELA5(ANSA5) DISABLED, INPUT DIGITAL/*LATx STEADY-STATE*/LATAbits.LATA1 = 0;LATAbits.LATA0 = 0;/*MAIN LOOP*/while(1){if((BIG_SW&&SMALL_SW)||(!BIG_SW&&!SMALL_SW)){LATAbits.LATA0 = 0; //LED OFFLATAbits.LATA1 = 0; //LED OFF}else if(SMALL_SW){LATAbits.LATA1 = 1; //LED ONLATAbits.LATA0 = 0; //LED OFF}else if (BIG_SW){LATAbits.LATA1 = 0; //LED OFFLATAbits.LATA0 = 1; //LED ON}}}sorry for not checking it with the scope thou cus I had to do a bit of housekeeping...soon however I will upload some.

author: Prehistoricman
author_rank: Regular Contributor
timestamp: April 04, 2020, 12:13:42 am
content: Does it work as you expect now?Btw, this lineCode:if((BIG_SW&&SMALL_SW)||(!BIG_SW&&!SMALL_SW))can be changed toCode:if (BIG_SW == SMALL_SW)to make it more readable

author: ali6x944
author_rank: Frequent Contributor
timestamp: April 04, 2020, 12:08:30 pm
content: Quote from: Prehistoricman on April 04, 2020, 12:13:42 amyes, it does logicallyfor the code modification, it works also, and it is implemented now.I haven't checked the electrical profile of the signal at RA0, RA1 thou, will be checking it soon.

author: ali6x944
author_rank: Frequent Contributor
timestamp: April 16, 2020, 02:36:12 pm
content: hi again,I have checked the electrical profile of the signal at RA0, RA1:

author: ali6x944
author_rank: Frequent Contributor
timestamp: April 16, 2020, 02:36:43 pm
content: things to be going ok

author: ali6x944
author_rank: Frequent Contributor
timestamp: April 18, 2020, 05:02:29 pm
content: for the ADC and TMR2 and CCP setups and routines:should they be done in functions outside the main function and called from within the main loop?for the to be tested ADC and TMR2 and CCP functionalities I think I will test both TMR2 and CCP last cus of their sheer complexity, but I am finding it hard to basically test it without the other two...anyways this is what I came up with:Code:.../*INCLUDES AND DEFINITIONS*/#include <xc.h>#include <stdint.h>#define _XTAL_FREQ 4000000/*VARIABLE DEFFENITION SECTION*/uint16_t RESULT; // ADC RESULT VARIABLE#define BIG_SW PORTAbits.RA4 //READ RA4 AND ASSIGN IT TO BIG_SW#define SMALL_SW PORTAbits.RA5 //READ RA5 AND ASSIGN IT TO SMALL_SW/*FUNCTION INTITILIZATION SECTION*/void ADC_INIT(){ADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)}void ADC_RESULT(){ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITSwhile(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ONRESULT = ADRESH << 8; //Load ADC high valueRESULT |= ADRESL; //Load ADC low value}void ADC_TEST(){if ((SMALL_SW||BIG_SW)&&(RESULT>512)){LATAbits.LATA1 = 1; //LED ONLATAbits.LATA0 = 1; //LED ON__delay_ms(1000);LATAbits.LATA1 = 0; //LED OFFLATAbits.LATA0 = 0; //LED OFF__delay_ms(1000);}else if(SMALL_SW&&(RESULT<512)){LATAbits.LATA1 = 1; //LED ON}else if (BIG_SW&&(RESULT<512)){LATAbits.LATA0 = 1; //LED ON}}/*MAIN FUNCTION*/void main(void){OSCFRQ =0b101; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 16MHz//(BIG_SW&&SMALL_SW)||(!BIG_SW&&!SMALL_SW)/*TRISx AND ANSELx ASSIGNMENT */TRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA0=0; // ANSELA0(ANSA0) DISABLED, INPUT DIGITALANSELAbits.ANSA1=0; // ANSELA0(ANSA1) DISABLED, INPUT DIGITALANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGANSELAbits.ANSA4=0; // ANSELA4(ANSA4) DISABLED, INPUT DIGITALANSELAbits.ANSA5=0; // ANSELA5(ANSA5) DISABLED, INPUT DIGITAL/*LATx STEADY-STATE*/LATAbits.LATA1 = 0;LATAbits.LATA0 = 0;/*FUNCTION INTITILIZATION CALL*/ADC_INIT();/*MAIN LOOP*/while(1){if(BIG_SW==SMALL_SW){LATAbits.LATA0 = 0; //LED OFFLATAbits.LATA1 = 0; //LED OFF}else if(SMALL_SW){ADC_RESULT();ADC_TEST();}else if (BIG_SW){ADC_RESULT();ADC_TEST();}}}It seems to work pretty nicely however it glitches around the 512 marks, or when if I switch between the big and small switch, but as a proof of operation, I am stuck trying to do the same but for TMR2 and CCP as the individual test function is kinda confusing to write independently from ADC.

author: Prehistoricman
author_rank: Regular Contributor
timestamp: April 19, 2020, 02:10:29 am
content: Quote from: ali6x944 on April 18, 2020, 05:02:29 pmYeah, that would probably be neater.Quote from: ali6x944 on April 18, 2020, 05:02:29 pmSince you know that you have your input code working then it would be fine to add the PWM to that.Quote from: ali6x944 on April 18, 2020, 05:02:29 pmThe glitching could be noise on the ADC/input. If you had an Arduino and printed the ADC value to serial, you would see it fluctuate a bit.Do you want to explain how you're stuck?As the first test of PWM, I would leave out the switch logic and just make the pot control the dimming of the LEDs.

author: ali6x944
author_rank: Frequent Contributor
timestamp: April 19, 2020, 03:58:45 pm
content: Quote from: Prehistoricman on April 19, 2020, 02:10:29 amwell, this is where I am stuck:1. TMR2 and CCP initialization function:A) is it better to initialize them together in a single function or in separate functions?B) in section "28.3.2 SETUP FOR PWM OPERATION" step 1:Quoteso the CCP here should be an input? but how when I am clearing the TRIS bit?2.test methodology:A) how can I verify the operation of the CCP or the TMR2 if the total PWM function does not work during implementation? i.e. how can I test them independently in their intended role?B) how can I eliminate faults caused by signal noise or physical irregularities during testing, so I am testing only the code?

author: Prehistoricman
author_rank: Regular Contributor
timestamp: April 29, 2020, 04:57:19 pm
content: Sorry about the late reply. I hope these answers are still useful to you.Quote from: ali6x944 on April 19, 2020, 03:58:45 pmI think I would initialise them together since you have no use for using them independently.Quote from: ali6x944 on April 19, 2020, 03:58:45 pmThis is just part of the initialisation. You see it's step 1? It's so the PWM isn't being used while it's being configured, therefore reducing glitches. The TRIS bit is cleared in step 6.Quote from: ali6x944 on April 19, 2020, 03:58:45 pmA) I don't think you can. Without setting up the CCP, you can't make PWM happen. Without setting up TMR2, you have no control over the pulse width.B) Have your pulse width input be controlled by a for loop, for example. I wouldn't bother since you already know the ADC code is working.

author: ali6x944
author_rank: Frequent Contributor
timestamp: June 20, 2020, 04:48:07 pm
content: hi again,so I am kinda stuck with the PWM subroutine...Code:#include <xc.h>#include <stdint.h>#define _XTAL_FREQ 4000000/*VARIABLE DEFFENITION SECTION*/uint16_t RESULT; // ADC RESULT VARIABLE#define BIG_SW PORTAbits.RA4 //READ RA4 AND ASSIGN IT TO BIG_SW#define SMALL_SW PORTAbits.RA5 //READ RA5 AND ASSIGN IT TO SMALL_SW/*FUNCTION INTITILIZATION SECTION*/void ADC_INIT(){ADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)}void ADC_RESULT(){ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITSwhile(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ONRESULT = ADRESH << 8; //Load ADC high valueRESULT |= ADRESL; //Load ADC low value}void CCP1_TMR2_INIT(){CCP1PPSbits.CCP1PPS=0b00000; // BIG LIGHT DRIVER (PWM->RA0), OUTPUTTRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTPR2bits.T2PR=0b10; // PR2 SET TO 2CCP1CONbits.MODE=0b1111; // CPP1 MODE (PWM)CCP1CONbits.FMT=1; // RIGHT-ALIGNED PWM FORMATPIR4bits.TMR2IF=0; // TIMER2 INTERUPT FLAG CLEAREDT2CONbits.CKPS=0b000; // 1:1 TIMER2 PRESCALER VALUET2CONbits.OUTPS=0b0000; // 1:1 TIMER2 POSTSCALER VALUET2CONbits.ON=1; // TIMER2 ON}void CCP2_TMR2_INIT(){CCP2PPSbits.CCP2PPS=0b00000; // SMALL LIGHT DRIVER (PWM->RA1), OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTPR2bits.T2PR=0b10; // PR2 SET TO 2CCP2CONbits.MODE=0b1111; // CPP2 MODE (PWM)CCP2CONbits.FMT=0; // LEFT-ALIGNED PWM FORMATPIR4bits.TMR2IF=0; // TIMER2 INTERUPT FLAG CLEAREDT2CONbits.CKPS=0b000; // 1:1 TIMER2 PRESCALER VALUET2CONbits.OUTPS=0b0000; // 1:1 TIMER2 POSTSCALER VALUET2CONbits.ON=1; // TIMER2 ON}void PWM1_SBR(){if (BIG_SW){CCP1CONbits.CCP1EN=1; // CCP1 MODULE ONCCPR1L:CCPR1H=RESULT; // LOAD RESULT IN CCPR1L:CCPR1H REGISTER}else{CCP1CONbits.CCP1EN=0; // CCP1 MODULE OFF}}void PWM2_SBR(){if (SMALL_SW){CCP2CONbits.CCP2EN=1; // CCP2 MODULE ONCCPR2L:CCPR2H=RESULT; // LOAD RESULT IN CCPR2L:CCPR2H REGISTER}else{CCP2CONbits.CCP2EN=0; // CCP2 MODULE OFF}}/*MAIN FUNCTION*/void main(void){OSCFRQ =0b101; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 16MHz//(BIG_SW&&SMALL_SW)||(!BIG_SW&&!SMALL_SW)/*TRISx AND ANSELx ASSIGNMENT*/TRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUTTRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUTTRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUTTRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUTTRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUTANSELAbits.ANSA0=0; // ANSELA0(ANSA0) DISABLED, INPUT DIGITALANSELAbits.ANSA1=0; // ANSELA0(ANSA1) DISABLED, INPUT DIGITALANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOGANSELAbits.ANSA4=0; // ANSELA4(ANSA4) DISABLED, INPUT DIGITALANSELAbits.ANSA5=0; // ANSELA5(ANSA5) DISABLED, INPUT DIGITAL/*CCPx ASSIGNMENT*/CCP1PPSbits.CCP1PPS=0b00000; // BIG LIGHT DRIVER (PWM->RA0), OUTPUTCCP2PPSbits.CCP2PPS=0b00001; // SMALL LIGHT DRIVER (PWM->RA1), OUTPUT/*LATx STEADY-STATE*/LATAbits.LATA1 = 0;LATAbits.LATA0 = 0;/*FUNCTION INTITILIZATION CALL*/ADC_INIT();CCP1_TMR2_INIT();CCP2_TMR2_INIT();/*MAIN LOOP*/while(1){if(BIG_SW==SMALL_SW){LATAbits.LATA0 = 0; //LED OFFLATAbits.LATA1 = 0; //LED OFF}else if(SMALL_SW){ADC_RESULT();PWM2_SBR();}else if (BIG_SW){ADC_RESULT();PWM1_SBR();}}}I think I followed the steps correctly, but I'm not really sure...I think the problem is in PWMx_SBR I tried to manipulate it but with no real improvement

author: ali6x944
author_rank: Frequent Contributor
timestamp: July 18, 2020, 12:21:46 pm
content: am I missing something in the initialization or the actual pwm subroutine function?