Thread: LED with adjustable flash, need help

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

    LED with adjustable flash, need help

    I want to modify the following code which flashes an LED on and off so that I can add a potentiometer to vary the speed of the flash, but I don't know how to do it.

    Code:
    #include <avr/io.h> 
    #include <inttypes.h>   
    #include "../lib/delay.h" 
    
    // PIN DEFINITIONS:
    // PC4 -- LED anode
    
    int main() {
        DDRC |= (1<<PC4);            // LED as output
        while(1) {                   // loop forever
            PORTC |= (1<<PC4);      // turn on LED
            delay_ms(500);          //delay for 500 milliseconds ON
            PORTC &= ~(1<<PC4);    // turn off LED
            delay_ms(500);          //delay for 500 milliseconds OFF
      }
      return 0;
    }

    Here's my attempt at modifying it. Turning the pot does nothing, it just flashes as normal.

    Code:
    #include <avr/io.h> 
    #include <inttypes.h>   
    #include "../lib/delay.h" 
    
    // PIN DEFINITIONS: 
    // PC0 --potentiometer to vary flash rate/speed of LED
    // PC4 -- LED anode   
    
    void adc_init() {   
      ADMUX = 0;   
      ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);   
      ADCSRA |= (1<<ADSC); 
    }   
    
    uint8_t adc_read() {   
      while(ADCSRA & (1<<ADSC)) {   
      }   
      uint16_t result = ADCL;   
      ADCSRA |= (1<<ADSC);   
      return result; 
    } 
    
    int main() {     
    
       adc_init(0);     
       DDRC |= (1<<PC4);               // LED as output    
       while(1) {                      // loop forever
           PORTC |= (1<<PC4);         // turn on LED              
           delay_ms(500);             //delay for 500 milliseconds ON 
           PORTC &= ~(1<<PC4);       // turn off LED              
           delay_ms(500);             //delay for 500 milliseconds OFF   
    }    
    return 0; 
    }
    So how can I get the pot to change the flash rate/speed? Something to do with the delay_ms perhaps, but what? Thank you.

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by nyg78 View Post
    I want to modify the following code which flashes an LED on and off so that I can add a potentiometer to vary the speed of the flash, but I don't know how to do it.

    So how can I get the pot to change the flash rate/speed? Something to do with the delay_ms perhaps, but what? Thank you.
    You should be able to use some multiple of the adc_read() return value to vary the delay()...
    But first you'll have to call the function, at least once per loop.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    5
    Quote Originally Posted by CommonTater View Post
    You should be able to use some multiple of the adc_read() return value to vary the delay()...
    But first you'll have to call the function, at least once per loop.
    So, would I add this under "int main" to call it, or maybe under "while"? (I'm new to C Programming in case that isn't obvious.)

    Code:
    adc_read();
    Thank you.

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    I'd put it in the while loop so that the speed changes dynamically as you move the control. Outside the loop it's only going to check the speed when the program starts.

    Code:
    int main() {     
        int time;
       adc_init(0);     
       DDRC |= (1<<PC4);               // LED as output    
       while(1) {                      // loop forever
          time = adc_read() *100;
          PORTC |= (1<<PC4);         // turn on LED              
           delay_ms(time);       
           PORTC &= ~(1<<PC4);       // turn off LED              
           delay_ms(time);     
    }

  5. #5
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    You should call adc_init without a parameter, like adc_init().
    adc_read didn't look right to me logic-wise so I looked up the register names and found this tutorial which appears to be for the same hardware you are using.
    Using the Analog To Digital Converter. | eXtreme Electronics
    Probably way too much help though.

  6. #6
    Registered User
    Join Date
    Mar 2011
    Posts
    5
    Thank you for your replies. Unfortunately, I still can't get the pot to work. I'm using an ATmega168 and a 14mhz crystal if that helps. The middle lug of the pot is connected to PC0, the left lug is connected to GND, and the right lug is connected to AREF. Any other suggestions on how to get this to work?

  7. #7
    Registered User
    Join Date
    May 2009
    Posts
    3,507
    Code:
    uint8_t adc_read() {   
      while(ADCSRA & (1<<ADSC)) {   
      }   
      uint16_t result = ADCL;   
      ADCSRA |= (1<<ADSC);   
      return result; 
    }
    Why does the type of the function return NOT match the type of the variable result?

    Tim S.

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by nyg78 View Post
    Thank you for your replies. Unfortunately, I still can't get the pot to work. I'm using an ATmega168 and a 14mhz crystal if that helps. The middle lug of the pot is connected to PC0, the left lug is connected to GND, and the right lug is connected to AREF. Any other suggestions on how to get this to work?
    Have you tried tying the right lug to VCC?

  9. #9
    Registered User
    Join Date
    Mar 2011
    Posts
    5
    Quote Originally Posted by CommonTater View Post
    Have you tried tying the right lug to VCC?
    Yes, and I even reversed the connections to the outer lugs in case it was hooked up backwards and it still doesn't work.

  10. #10
    Registered User
    Join Date
    May 2009
    Posts
    3,507
    Do NOT use AREF hooked up to your pot. The datasheet says only hookup an high impedance volt meter; the pin is should NOT be used as a power source.

    Are you using an internal or external VREF?

    From 23.5.2 ADC Voltage Reference
    AVCC is connected to the ADC through a passive switch. The internal 1.1V reference is gener-
    ated from the internal bandgap reference (VBG) through an internal amplifier. In either case, the
    external AREF pin is directly connected to the ADC, and the reference voltage can be made
    more immune to noise by connecting a capacitor between the AREF pin and ground. VREF can
    also be measured at the AREF pin with a high impedance voltmeter. Note that VREF is a high
    impedance source, and only a capacitive load should be connected in a system.
    I suggest changing the following
    Code:
    void adc_init() {   
      ADMUX = 0;
    to this instead

    Code:
    void adc_init() {   
      ADMUX=(1<<REFS0); /* reference voltage will be Vcc */
    Code from URL posted by someone else above.
    Using the Analog To Digital Converter. | eXtreme Electronics

    And, you MUST hook up the pot to an external power source; I suggest Vcc.

    Tim S.
    Last edited by stahta01; 04-03-2011 at 01:32 PM.

  11. #11
    Registered User
    Join Date
    Mar 2011
    Posts
    5
    Ok, I'm getting somewhere, but not exactly what I want. When I turn the pot while the battery is connected, nothing happens. If I turn the pot, unhook the battery, then hook the battery back up, the flash speed has changed. If I wind the pot back to 0, unhook the battery, then hook it back up, the LED will be on solid, no flashing. The weird thing is, the LED doesn't flash the fastest when the pot is on 10, it flashes fastest when I wind the pot back to about 7 or 8. At 10 on the pot, it's slower. I'm using a new B100k pot. The right lug is connected to VCC, center lug to PC0, and left lug to GND.

  12. #12
    Registered User
    Join Date
    May 2009
    Posts
    3,507
    23.2 Overview
    The ADC generates a 10-bit result which is presented in the ADC Data Registers, ADCH and
    ADCL. By default, the result is presented right adjusted, but can optionally be presented left
    adjusted by setting the ADLAR bit in ADMUX.
    That is likely because you are using ADCL instead of ADCH (or just ADC).

    I strongly suggest reading the manual/datasheet if you wish to learn/get good grade or money.

    Tim S.
    Last edited by stahta01; 04-04-2011 at 05:39 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Flash on Apple Devices Discussion
    By DavidP in forum General Discussions
    Replies: 58
    Last Post: 05-05-2010, 09:20 AM
  2. Flashing LED Program
    By AWJay in forum C Programming
    Replies: 5
    Last Post: 02-16-2010, 11:13 AM
  3. Switch function problem
    By ahming in forum C Programming
    Replies: 3
    Last Post: 04-01-2008, 09:40 AM
  4. Replies: 1
    Last Post: 08-11-2006, 05:44 AM
  5. Flash <--> c++
    By c-- in forum C++ Programming
    Replies: 7
    Last Post: 09-13-2002, 11:26 PM