Thread: some help needed for ADC programming

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    12

    some help needed for ADC programming

    Hi,
    I am trying to get a series of LED's to light up when a qtc pressure pill is pressed, using a 16f684. I have adapted an existing ADC program to try and do this and have managed to get the LED's to light up. The problem however lies with the fact that I can not seem to get the LED's to stay at the light level wanted (using the pressure) once the QTC has been released.

    I have made 4 PWM's using for loops to set the required LED brightness for each of the ADC values.

    I have a basic knowledge in C programming and have tried several different ways of trying to get the light level to stay.

    What do i need to do in order to keep the light level constant (indefinitely) until the QTC registers another pressure? Do I need to make a switch case/ an interupt? As previously stated my knowledge in C is limited. Any help would be greatly appreciated. The code is below;



    Code:
    #include <pic.h>
    #include <stdio.h>
    #include <string.h>
    
    /*  cFlash.c - Simple C Program to Flash an LED on a PIC16F684
    
    RA4 - LED Positive Connection
    RA5 - LED Negative Connection
    
    */
    
    __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
      & UNPROTECT & BORDIS & IESODIS & FCMDIS);
    
    
    int i, j;
    
    //#define E RC4
    //#define RS RC5
    //#define QTC1 RA0					//Defines QTC1 as RA0 input
    //#define QTC2 RA4					//Defines QTC2 as RA4 input
    //#define QTC3 RA3					//Defines QTC3 as RA3 input
    
    
    const char display_portc[]= {0b00000001, 0b00000010, 0b00000100, 0b00001000, 0b00010000, 0b00100000};
    
    const char display_porta[]= {0b00000001, 0b00000010, 0b00000100, 0b00001000, 0b00010000, 0b00100000};
    
    int ADCresult= 0;
    
    
    void manualPWM()
    
    {
    						
    					 //while (1)
    					//while (ADCresult<= 60)
            			for (i = 0; i < 2; i++)  //  Simple 500ms Delay
                			for (j = 0; j < 10; j++);
    
           				PORTC= display_portc[0];                //  LED On
    
           				 for (i = 0; i < 10; i++)  //  Simple 500ms Delay
                				for (j = 0; j < 100; j++);
    
            			 PORTC= display_portc[1];                //  LED Off
          //GODONE = 0;
    
    }
    
    
    
    void manualPWM2()
    {
    					//	while (1)	
    					  //while (ADCresult<= 120)
            			for (i = 0; i < 15; i++)  //  Simple 500ms Delay
                			for (j = 0; j < 5; j++);
    
           				PORTC= display_portc[0];               //  LED On
    
           				 for (i = 0; i < 10; i++)  //  Simple 500ms Delay
                				for (j = 0; j < 55; j++);
    
            			 PORTC= display_portc[1];                //  LED Off
    //GODONE = 0;
    }
    
    
    
    void manualPWM3()
    {
    						
    					//while (1)
      					 //while (ADCresult<= 180)
            			for (i = 0; i < 25; i++)  //  Simple 500ms Delay
                			for (j = 0; j < 10; j++);
    
           				PORTC= display_portc[0];                //  LED On
    
           				 for (i = 0; i < 10; i++)  //  Simple 500ms Delay
                				for (j = 0; j < 55; j++);
    
            			 PORTC= display_portc[1];                //  LED Off
    					//GODONE = 0;
    }
    
    
    
    void manualPWM4()
    {
    					//	while (1)	
    					   //while (ADCresult<= 240)
            			for (i = 0; i < 255; i++)  //  Simple 500ms Delay
                			for (j = 0; j < 129; j++);
    
           				PORTC= display_portc[0];                //  LED On
    
           				 for (i = 0; i < 10; i++)  //  Simple 500ms Delay
                				for (j = 0; j < 1; j++);
    
            			 PORTC= display_portc[1];                //  LED Off
    //GODONE = 0;
           }  
    
    
    
    
    main()
    {
    	int ADCresult= 0;
        PORTA = 1;
    	PORTC = 0;
        CMCON0 = 7;                 			//  Turn off Comparators
        ANSEL = 0b00000100;       				 //Pin 11- RA2 as analogue input
    	TRISA= 0b0000100;         							//PortA  input
       	TRISC = 0;                  				//PortC as output
    	ADCON0= 0b00001001;  	//Result left justified format, voltage reference= VDD, 
    							//AN2= analogue input, initiates ADC and waiting to start conversion.
    	ADCON1= 0b00010000;   	 //  For 4 Mhz, 8Tosc= 2 uS, which > 1.6 uS, the minimum requirement
    
    
    
    
    
    
    
    
        while(1)               //  Loop Forever
       {
    	GODONE = 1;                				//Start conversion.
         while (GODONE== 1);   				//Wait until conversion is done.
         ADCresult= ADRESH;    			//Transfer from ADRESH to ADCresult.  
    
    
    if(ADCresult< 255) PORTA= 0; 
    if(ADCresult<= 30) PORTC= display_portc[0];
            
    else if(ADCresult<= 60) 
    {
    			manualPWM();			
    					
          }
    
    else if(ADCresult<= 120) 
    {
    		manualPWM2();					
    					  
    }
    
    else if(ADCresult<= 180)
    {
    						
    		manualPWM3();			
      					 
    }
    
    else if(ADCresult<= 240) 
    {
    		manualPWM4();					
    					 
           }  
                  
    
    
    
    
    }  //  End cFlash
    }
    A big thanks to anyone that can help point me in the right direction as have been working on this for a long time without any real success.

    O.lewis

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Please fix your comments
    You have this comment after a lot of lines; where it is likely false.

    // Simple 500ms Delay

    Without a better understanding of what does what I see no way for me to help you.
    You have related no way in which the control you have related to the ADC result.
    You need to figure out how they relate? Linear or something else.
    You may need a variable PWM modulation.
    Did you see if the chip you have supports real PWM?
    Edit: It does support real PWM.

    Tim S.
    Last edited by stahta01; 03-31-2011 at 10:13 AM.

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    How is this different from your other post. Cross posting, bumping and double-posting are all poor form. Read the forum guidelines. And have a little patience. Throwing 169 lines of messy code at us for your custom embedded setup and expecting an answer in a couple hours is a little silly. This isn't a full time job for us.

    Now, on to your problem. This is all speculation since I don't have a circuit or anything to go off of, and I'm unfamiliar with QTCs. I suspect your lights are messed up because you are always reading the ADC value and updating ADCresult, even when the QTC isn't pressed. You need to figure out how your program will know the QTC is pressed or released, instead of just getting the current ADC value every time. Basically, your code needs to look something like this:
    Code:
    if QTC pressed
        ADCresult = get ADC value
    // else it keeps the last value
    set_lights(pressure)
    That way, you're only updating the pressure value when the QTC is actually pressed. Once it's released, you will stop updating the pressure variable but keep running your PWM routines, thus keeping the lights at the appropriate levels.

  4. #4
    Registered User
    Join Date
    Mar 2011
    Posts
    12
    I apologise for double posting, I hadnt realised that my other post was logged, as I couldnt find it, this shall not happen again. I do realise that you are taking time out to help without the need to and this is very much appreciated. Once again I do apologise.


    For TimS.

    The //500ms delay is incorrect and should not read this. These delays are to provide a dimming effect on the LED's (a manual PWM) as I could not get the real PWM to work properly.

    The 4 different delay (for loop) functions allow for 4 different brightnesses with the LEDs. these are to try and accomplish 25%, 50%, 75% and 100% brightness. The brightness level is judges by the amount of pressure placed on the QTC sensor. although the problem lies with the fact that once the pressure is released, the brightness goes back to full, and will not stay at the desired level (PWM)


    anduril462

    The QTC is set in a potential divider, going into AN2. Would it help if I posted a circuit schematic?

    I believe that you are correct in saying that the ADC is always being updated, and therefore the LED are reacting only when the QTC is pressed. as previously stated I can upload a circuit schematic if necessary.

    I will try to alter the code (now tomorrow as it now late in the UK) as you have suggested to see if I can achieve the desired results, as your advice would achieve the effects that I need to achieve

    Thank you so much for your help so far

    O.Lewis

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Go ahead and try my changes. If you still have trouble, then come back and post your schematic and modified code for us to take another look at it.

  6. #6
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Yep! posting the schematic would be good, and why didn't the builtin PWM module work?

  7. #7
    Registered User
    Join Date
    Mar 2011
    Posts
    12
    I believe in order to get the built in PWM to work, you need to have the 16f684.inc file. I tried this and it still didnt work. I was told by my lecturer that you can make your own PWM using for loops. This seems to be the best option at the moment in order to get a working program. Once the program has been written and is working I can then go back and alter the code to enable the on board PWM. The circuit schematic will follow shortly

    Cheers,

    O.Lewis

  8. #8
    Registered User
    Join Date
    Mar 2011
    Posts
    12
    I have attached the schematic to the program. there are 3 RGB LED's in the circuit, however for the program, I am only trying to control one with pressure, as I believe that it is possible to amend the program afterwards to suit more LED's. The LED in use is located on pin RC1 and the analogue input is in AN2.

    anduril462

    I have tried to implement your code suggestion, however I am not sure that I am following it correctly as I am not sure how to "get ADC value"

    I have tried a few codes along the lines of
    Code:
    if (QTC==1);
    (ADCresult<= 240)
    {
    manualPWM4()
    }
    else (ADCresult==180)
    I tried this to prevent the QTC from causing the ADC result to go back to 0. Is this along the right lines?

    I was also thinking that by using a function call, like in the original program, I could stop the ADC from constantly updating, although again I was unsuccessful.

    One amendment that I have made that has worked well is reversing the manual PWM's to allow a light pressure to cause a dim light and a hard pressure to cause a bright light (with intervals in-between)

    would it be possible for you to explain your code snippet in a bit more detail as I can not seem to find my way around it.


    Thankyou very much for your help so far.

    O.Lewis

    Sorry the previous attachment did not work. please see attached for schematic

    O.lewis
    Last edited by O.lewis; 04-01-2011 at 01:59 PM.

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by O.lewis View Post
    Code:
    if (QTC==1);
    You certainly don't want that semicolon there. It makes that if statement do nothing whatsoever.

    Code:
         GODONE = 1;                				//Start conversion.
         while (GODONE== 1);   				//Wait until conversion is done.
         ADCresult= ADRESH;    			//Transfer from ADRESH to ADCresult.
    Those 3 lines are what cause the ADC to read in a value and store it in ADCresult. Assuming the QTC is considered as being pressed when QTC is equal to one (as in the above code snippet with your incorrect if statement), what I was suggesting simply to wrap the ADC reading code in a simple if block, like this:
    Code:
    if (QTC == 1) {  // QTC is being pressed
        // only read a value from the ADC when the QTC is being pressed
        GODONE = 1;                				//Start conversion.
        while (GODONE== 1);   				//Wait until conversion is done.
        ADCresult= ADRESH;    			//Transfer from ADRESH to ADCresult.  
    }
    ...
    // now, if the QTC wasn't pressed, ADCresult has the same value it did last time through the main while(1) loop.

  10. #10
    Registered User
    Join Date
    Mar 2011
    Posts
    12
    Brilliant thanks for explaining that! I will give that a go on Monday as am not with my code until then. I really appreciate all the help so far. Hopefully this will enable the results that are needed.

    Am I correct in saying that I need to define QTC as AN2 like

    Code:
    #define QTC RA2                     //defines QTC as input RA2
    Regards,

    O.Lewis

  11. #11
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by O.lewis View Post
    Am I correct in saying that I need to define QTC as AN2 like

    Code:
    #define QTC RA2                     //defines QTC as input RA2
    Regards,

    O.Lewis
    Yep! if it's wired according to the posted schematic.

  12. #12
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by O.lewis View Post
    The 4 different delay (for loop) functions allow for 4 different brightnesses with the LEDs. these are to try and accomplish 25%, 50%, 75% and 100% brightness. The brightness level is judges by the amount of pressure placed on the QTC sensor. although the problem lies with the fact that once the pressure is released, the brightness goes back to full, and will not stay at the desired level (PWM)
    What is a QTC? A pressure sensor that creates a potential difference? And post a better version of the schematic - this one is hardly legible.
    What should be the brightness level once the QTC is released? I'd guess zero, but want to be sure about the expectation. And, have you tried to wire the reference voltage ie Vref pin to the QTC?

    Perhaps adding an if block for the ADC read equaling zero might be the thing, as in
    Code:
    if (ADCresult == 0) PORTC = display_portc[1];
    else if (ADCresult<= 30) PORTC = display_portc[0];
    Last edited by itCbitC; 04-04-2011 at 08:47 AM.

  13. #13
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Is QTC digital or Analog?

    Tim S.

  14. #14
    Registered User
    Join Date
    Mar 2011
    Posts
    12
    itCbitC

    QTC is a pressure sensor called Quantum Tunnelling composite. it acts as an electrical insulator until it is pressed which allows the flow electrons.

    With regards to the code, I would like the program to register the highest ADC value when pressed, and change the light brightness to the relevant level. By this I mean, a 25% pressure will cause a 25% brightness. The problem that I am having is that the brightness then falls back to zero (as you said) and this is not wanted.



    stahta01

    From what I understand of QTC, it provides an analog signal when pressed.




    I have not been able to get into the labs this week to play around with my code, although am hoping to get in on tursday/friday to try all the suggestions so far.
    Thankyou everyone for your inputs so far. I will be sure to try out every suggestion and get back to you with all the results I get.

    I look forward to sharing this all with you

    O.Lewis

    itCbitC

    I will also get a better schematic up as soon as possible

    O.Lewis
    Last edited by O.lewis; 04-06-2011 at 02:03 PM.

  15. #15
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by O.lewis View Post
    itCbitC

    QTC is a pressure sensor called Quantum Tunnelling composite. it acts as an electrical insulator until it is pressed which allows the flow electrons.

    With regards to the code, I would like the program to register the highest ADC value when pressed, and change the light brightness to the relevant level. By this I mean, a 25% pressure will cause a 25% brightness. The problem that I am having is that the brightness then falls back to zero (as you said) and this is not wanted.

    stahta01

    From what I understand of QTC, it provides an analog signal when pressed.
    If I understand you correctly, you're want to find the max pressure when the QTC is pressed and once it stops, you want to output the corresponding LED brightness until the QTC is pressed again?

    So lets start with the find the maximum part. The general approach is:
    Code:
    initialize max to the smallest possible number
    for each element being examined
        if the element is greater than max
            set max to the value of element
    The problem with using just that code is that, if I press the QTC really hard the first time, then gently every time after that, your will never reset the max to reflect the most recent press, so it will always appear as if the QTC was pressed really hard. We need to find out when the QTC goes from unpressed to pressed, so we can reset max to the smallest value and start looking again. To do this, we need to know what state we were in last time and what state we're in now. Presumably the QTC will register 0 on your ADC if it's not pressed:
    Code:
    initialize prev_state to 0
    infinite loop
        QTC = read ADC
        if QTC is not zero
            if prev_state is 0
                reset max to smallest number
            if QTC > max
                max = QTC
        prev_state = QTC
        display LED brightness for max

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 0
    Last Post: 12-08-2009, 07:39 AM
  2. free needed or not?
    By quantt in forum Linux Programming
    Replies: 3
    Last Post: 06-25-2009, 09:32 AM
  3. C Programmers needed for Direct Hire positions
    By canefan in forum Projects and Job Recruitment
    Replies: 0
    Last Post: 09-24-2008, 11:55 AM
  4. C++ help needed
    By Enkindu in forum Projects and Job Recruitment
    Replies: 3
    Last Post: 08-31-2004, 11:24 PM
  5. Who's telling the truth??? Career Advice Needed Badly
    By Ican'tCjax,fl in forum C Programming
    Replies: 1
    Last Post: 11-06-2002, 06:16 PM