Timer

Hmm, it’s not clear from just that snippet. This time, could you post a copy of your entire source code?

-Adam

No Problem. to me it doesnt look that much different from the delay method, but if it allows me to do multiple things at once…

A lot of the source code is to do with the LCD

        // F_CPU tells util/delay.h our clock frequency
       #define F_CPU 8000000UL   // Orangutan frequency (8MHz)

        #include <avr/io.h>
        #include <util/delay.h>
		#include <avr/interrupt.h>

      volatile unsigned int timer_tick;      //global timer variable MUST BE DECLARED VOLATILE

        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[8] = {0,0,0,'.',0,0,0,'s',0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
          
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------


        //STANDARD MAIN FUNCTION

        int main( void )
        {

          //--------------------------------------
          //LCD STUFF TO GO IN MAIN FUNCTION
          //--------------------------------------
         

               // Make sure all our registers are clear
               DDRB = 0;
               DDRC = 0;
               DDRD = 0;

               PORTB = 0;
               PORTC = 0;
               PORTD = 0;

          // Initialize the LCD
          lcd_init();
          //-----------------------------
          //END MAIN FUNCTION LCD STUFF
          //------------------------------
DDRC &= ~(1 << PC5);
PORTC|=(1<<PC5);  


unsigned int time_ms1 = 0;
unsigned int time_ms2 = 0;
  


  
while (PINC&(1<<PC5))  // loop here until first button press
  ;
//initialize timer 0
TCNT0=~(124);//preload counter to overflow after 1 ms (125 counts)
TIMSK=(1<<TOIE0);//enable interrupt on timer0 overflow
TCCR0=(1<<CS01)|(1<<CS00);//set timer to normal mode with CPU clock/64 (125 kHz)

sei();//enable all interrupts

// time an event:
   timer_tick=0;            //start timer, clear global millisecond counter
TCNT0 = ~(124);

while (1)  // loop forever
{
  _delay_ms(10);  // delay for 10 ms to debounce the press

  while (!(PINC&(1<<PC5)))  // loop here until button is released
   ;
  _delay_ms(10);  // delay for 10 ms to debounce button release

  time_ms1 = 0;  // here is where we start timing
  time_ms2 = 0;
  TCNT0 = 10;

 
  while (PINC&(1<<PC5))  // loop here until second button press
  {    
   }
   time_ms1 = timer_tick;      //get the value of the millisecond counter
  }
  
  while (!(PINC&(1<<PC5)))  // loop here until button is released
   ;
  _delay_ms(10);  // delay for 10 ms to debounce button release
  
  TCNT0 = 10;
while (PINC&(1<<PC5))  // loop here until 3rd button press
  {
  }
 time_ms2 = timer_tick;      //get the value of the millisecond counter

  
  lcd_line1();// display the times
  lcd_time(time_ms1);
  lcd_line2();
  lcd_time(time_ms2);  
}

     





/*
TIMER 0 overflow interrupt service routine
This routine is called every millisecond
Operation: increment global variable timer_tick, reload TCNT0 to count 125 clock cycles
*/

ISR(TIMER0_OVF_vect)
{
   timer_tick++;
   TCNT0 = ~(125);         //preload counter to overflow after 1 ms (125 counts)
}
     

        

It looks like you’re configuring things correctly, but the big problem I see is that your code never breaks out of the while(1) loop, so it never gets to the part where it prints information to the LCD.

One other little problem I see is in this line:

unsigned char st[8] = {0,0,0,’.’,0,0,0,‘s’,0};

You’re only allocating memory for an array of eight variables, but then filling it with nine. It’s probably not doing any harm, but there’s no telling what that ninth character is overwriting when this runs on your microcontroller.

-Adam

So is it using interupts - my piece of code? Does that mean i could set it to do other things if another button was pressed somewhere else?

I was told by another forum writer that I needed that line: unsigned char st[8] = {0,0,0,’.’,0,0,0,‘s’,0}; to end with a 0 and that was the reason junk came up on the screen alot???

Below is a modifed version of the same piece of code. ( the old one works but the timing is not true (seconds are not seconds))

This time i am trying to give myself the option of doing different things, I want it to look out for other buttons being pressed, and if so go to different functions. As interrupts though. I only have one and thats the one i have been working on, but would like the option of others. Comethings not right though even though it compiles, it doesnt run through correctly?

Aah, that’s a good point, and Jim would know, the Orangutan-Lib LCD function is based on code he wrote. You should end with a zero so the LCD_String function knows it’s at the end of your string, but you need to create a nine character array to hold it, so:

st[9] = {0,0,0,’.’,0,0,0,‘s’,0};

Your code is now using timers and timer-overflow interrupts, so it could potentially be doing other things since it’s not using delays to do the timing. Instead it is now checking for button presses all the time. You could make a loop that checks the button state, then does something else, then delays for a millisecond or so (the timer overflow interrupt can interrupt the delay), and do multiple things that way.

There are also special pins on the AVR microcontrollers that can be set to generate an interrupt when their digital state changes, so you could have a button press automatically generate an interrupt and you wouldn’t have to check the button state at all. Unfortunately the ATMega8 only has two such pins, and neither are user-accessable on the Orangutan.

-Adam

OK, I think i know how to do that with one thing needed to be done on a button press:

while (PINC&(1<<PC5))
;
{
if (!PINC&(1<<PC5))
{
//go to function to time...
function();
}
}

but what about different button presses, because that only does that when button PC5 isnt pressed, it would keep doing that even if button PC4 was pressed, and had its own while function…

is there a way to look out for any button being pressed, or a few buttons being pressed, i.e

 while ((PINC&(1<<PC5))) or ((PINC&(1<<PC4)))
 {
 	if (!(PINC&(1<<PC5)))
 		{
	_delay_ms(10);  // delay for 10 ms to debounce the press
	time();
		}
		else if ((PINC&(1<<PC4)))
			{
		//run a different function
			}
}

is that possible?

Yeah, something like that would work great, but checking the button states in the argument of the while loop wouldn’t work well. Depending on precisely where in the loop your program is running when a button is pressed it would have a good chance of being missed. Instead you could do something like this:

while(1){
	if (!(PINC&(1<<PC5))){
		_delay_ms(10);//delay for 10 ms to debounce the press
		time();
		break;
	}else if(!(PINC&(1<<PC4))){
		_delay_ms(10)//delay for 10 ms to debounce the press
		//run a different function
		break;
	}
}

The “while(1)” loop goes forever, but if either button is pressed an outside function is called, and after that function is done the “break” statement will immediately break out of the loop, and go to the first line of code after it.

-Adam

Yeah that looks much better, cheers. and not i can add as many buttons as i want!

Quick last question ( i think for a while anyway), I have an array, of the numbers 1 to 36, but not in that order.

I have a script that as a potentiometer is turned, it clicks through those numbers.

I want to update it so that when i press a button, it recognises all the numbers after that one, and prints them on the screen - but in he order they are stored in the array. I also want to change it, so that when you click through them with the pot, the current number appears on the screen, but i want it to click through in order, but print them back not in orger?

Does that make any sense.

Here is the code that clicks through them out of order

while(1)
		{



// Initialize the ADC:
		analog_init();



// The endless loop
			for(;;)
			{


				// scale the potentiometer ADC value (0 - 255) to be a number from 0 - 36
  				unsigned char pot_idx = (unsigned char)(analog8(7) * 36 / 255);
  				
  				lcd_line2();
  				lcd_int(single_zero_wheel[pot_idx]);
 				 _delay_ms(25);

			}
		return 1;


		}

What would need to be done?

THanks and sorry?

I’m not sure exactly what you mean at the end by “click through in order, but print them back not in order”.

If you wanted to print the POT-selected number, and every other number after it in the array when a button is pressed, you could do something like this:

// Initialize the ADC:
analog_init();
unsigned char i;

while(1){

	// The endless loop
	while(PINC&(1<<PC5)){
		// scale the potentiometer ADC value (0 - 255) to be a number from 0 - 36
		unsigned char pot_idx=(unsigned char)(analog8(7)*36/255);

		lcd_line2();
		lcd_int(single_zero_wheel[pot_idx]);
		
		_delay_ms(25);
	}
	
	while(pot_idx<=33){//the single zero wheel array actually has 33 numbers, including the zero, right?
		lcd_line2();
		lcd_int(single_zero_wheel[pot_idx]);
		
		pot_idx++;//increment pot_idx
		
		for(i=0;i<10;i++){
			_delay_ms(25);
		}
	}
}

This will flash the current number and all the rest of the numbers in the array on the screen for a quarter of a second each. I’m assuming you’re using the same button (PC5), and that your single_zero_wheel array has 33 numbers in it (from zero to 32). If it actually only has 32 numbers in it you should change that loop to while(pot_idx<=32).

-Adam

I for got to show you the array, it might have made more sense then…

const unsigned char single_zero_wheel[37]={0,32,15,19,4,21,2,25,17,34,6,
                                 27,13,36,11,30,8,23,10,5,24,
                                 16,33,1,20,14,31,9,22,18,29,
                                 7,28,12,35,3,26};

while(1)
		{



// Initialize the ADC:
		analog_init();



// The endless loop
			for(;;)
			{


				// scale the potentiometer ADC value (0 - 255) to be a number from 0 - 36
  				unsigned char pot_idx = (unsigned char)(analog8(7) * 36 / 255);
  				
  				lcd_line2();
  				lcd_int(single_zero_wheel[pot_idx]);
 				 _delay_ms(25);

			}
		return 1;

So you see how the numbers 1 to 36 are not in order in the array. And as you turn the pot, it flicks through the numbers in the array 0, 32 15, 19 etc…

What I want is as you turn the pot, the numbers flick through in order on the screen so you can see where you are, - 0, 1, 2, 3, 4, 5,6 etc. Then if you stop on a number lets say number 28, and press a button, PC4 for example, it displays all the numbers after that in the array, 22, 35, 3, 26 on the led.

Its quicker to scroll through 36 numbers in ordr, because you know whats coming next…

EDIT:

I just changed my code to inlcude you little while loop waiting for a button to be pressed, and now i;m getting some vector error?
Including all code but it is to do with the function right at the bottom that controls the timer…

        // F_CPU tells util/delay.h our clock frequency
       #define F_CPU 1000000UL   // Orangutan frequency (8MHz)

        #include <avr/io.h>
        #include <util/delay.h>
		#include <avr/interrupt.h>

      unsigned int time_ms1 = 0;
	unsigned int time_ms2 = 0;
	  volatile unsigned int timer_tick;      //global timer variable MUST BE DECLARED VOLATILE

        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[8] = {0,0,0,'.',0,0,0,'s',0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
          
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------


        //STANDARD MAIN FUNCTION

        int main( void )
        {

          //--------------------------------------
          //LCD STUFF TO GO IN MAIN FUNCTION
          //--------------------------------------
         

               // Make sure all our registers are clear
               DDRB = 0;
               DDRC = 0;
               DDRD = 0;

               PORTB = 0;
               PORTC = 0;
               PORTD = 0;

          // Initialize the LCD
          lcd_init();
          //-----------------------------
          //END MAIN FUNCTION LCD STUFF
          //------------------------------
DDRC &= ~(1 << PC5);
PORTC|=(1<<PC5);  

DDRC &= ~(1 << PC4);
PORTC|=(1<<PC4); 


 //initialize timer 0
TCNT0=~(124);//preload counter to overflow after 1 ms (125 counts)
TIMSK=(1<<TOIE0);//enable interrupt on timer0 overflow
TCCR0=(1<<CS01)|(1<<CS00);//set timer to normal mode with CPU clock/64 (125 kHz)

sei();//enable all interrupts

// time an event:
   timer_tick=0;            //start timer, clear global millisecond counter
TCNT0 = ~(124); 


 while(1){
   if (!(PINC&(1<<PC5))){
      _delay_ms(10);//delay for 10 ms to debounce the press
      time();
      break;
   }else if(!(PINC&(1<<PC4))){
      _delay_ms(10);//delay for 10 ms to debounce the press
      //run a different function
      break;
   }


}

     
int time()
{
while (PINC&(1<<PC5))  // loop here until first button press
  ;
while (1)  // loop forever
{
  _delay_ms(10);  // delay for 10 ms to debounce the press

  while (!(PINC&(1<<PC5)))  // loop here until button is released
   ;
  _delay_ms(10);  // delay for 10 ms to debounce button release

  time_ms1 = 0;  // here is where we start timing
  time_ms2 = 0;
  TCNT0 = 10;

 
  while (PINC&(1<<PC5))  // loop here until second button press
  {    
   }
   time_ms1 = timer_tick;      //get the value of the millisecond counter
  
  
  while (!(PINC&(1<<PC5)))  // loop here until button is released
   ;
  _delay_ms(10);  // delay for 10 ms to debounce button release
  
  TCNT0 = 10;
while (PINC&(1<<PC5))  // loop here until 3rd button press
  {
  }
 time_ms2 = timer_tick;      //get the value of the millisecond counter

  
  lcd_line1();// display the times
  lcd_time(time_ms1);
  lcd_line2();
  lcd_time(time_ms2);  
}
}





/*
TIMER 0 overflow interrupt service routine
This routine is called every millisecond
Operation: increment global variable timer_tick, reload TCNT0 to count 125 clock cycles
*/

ISR(TIMER0_OVF_vect)
{
   timer_tick++;
   TCNT0 = ~(125);         //preload counter to overflow after 1 ms (125 counts)
}
     


        

Sorry, but this error has never happened before???

Aah, I get it. You want to pick the number, then spin the wheel! One simple way to do this would be to add a second array, an ordered list of the locations of the numbers on the wheel. Lets call it single_zero_order. Looking at the order of numbers on the single zero wheel, zero is in the zero’th place, 1 is in the 23’rd place, 2 is in the sixth place, and so on. It would look something like this:

const unsigned char single_zero_wheel[37]={0,32,15,19,4,21,2,25,17,34,6,
								 27,13,36,11,30,8,23,10,5,24,
								 16,33,1,20,14,31,9,22,18,29,
								 7,28,12,35,3,26};

const unsigned char single_zero_order[37]={0,23,6,35,4,19,10,31,16,27,18,
								14,33,12,25,2,21,8,29,3,24,5,
								28,17,20,7,36,11,32,30,15,26,
								1,22,9,34,13};

// Initialize the ADC:
analog_init();
unsigned char i;

while(1){

   // The endless loop
   while(PINC&(1<<PC5)){//while button PC5 is not pressed
	  // scale the potentiometer ADC value (0 - 255) to be a number from 0 - 36
	  unsigned char pot_idx=(unsigned char)(analog8(7)*36/255);

	  lcd_line2();
	  lcd_int(pot_idx);
	  
	  _delay_ms(25);
   }
   
   pot_idx=single_zero_order[pot_idx];
   
   while(pot_idx<=37){
	  lcd_line2();
	  lcd_int(single_zero_wheel[pot_idx]);
	  
	  pot_idx++;//increment pot_idx
	  
	  for(i=0;i<10;i++){
		 _delay_ms(25);
	  }
   }
}

So while you’re turning the pot, the LCD is actually displaying the pot_idx variable directly. When you press the button, the program looks up where that number is on the wheel from the number order array, and starts displaying wheel numbers starting with that one. Neat!

For your stopwatch program problem, it looks like you were one closing brace short at the end of the main function. Also, if you don’t have function prototypes, functions should be written out before other functions that call them. I moved the “time()” function to just before the main function. This isn’t really a problem for the interrupt functions, since they aren’t called like normal functions, so I left the interrupt function where it was. Also, I changed st[8] to st[9] in the “lcd_time” function (like we discussed earlier), and just for proper housekeeping I added a “return 0” line to the end of the main function:

        // F_CPU tells util/delay.h our clock frequency
       #define F_CPU 1000000UL   // Orangutan frequency (8MHz)

        #include <avr/io.h>
        #include <util/delay.h>
      #include <avr/interrupt.h>

      unsigned int time_ms1 = 0;
   unsigned int time_ms2 = 0;
     volatile unsigned int timer_tick;      //global timer variable MUST BE DECLARED VOLATILE

        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[9] = {0,0,0,'.',0,0,0,'s',0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
         
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

int time(){
	while (PINC&(1<<PC5));  // loop here until first button press

	while (1){  // loop forever
		_delay_ms(10);  // delay for 10 ms to debounce the press
		
		while (!(PINC&(1<<PC5)));  // loop here until button is released
		
		_delay_ms(10);  // delay for 10 ms to debounce button release
		
		time_ms1 = 0;  // here is where we start timing
		time_ms2 = 0;
		TCNT0 = 10;
		
		
		while (PINC&(1<<PC5));  // loop here until second button press
		time_ms1 = timer_tick;      //get the value of the millisecond counter
				
		while (!(PINC&(1<<PC5)));  // loop here until button is released
		
		_delay_ms(10);  // delay for 10 ms to debounce button release
		
		TCNT0 = 10;
		while (PINC&(1<<PC5));  // loop here until 3rd button press

		time_ms2 = timer_tick;      //get the value of the millisecond counter
		
		lcd_line1();// display the times
		lcd_time(time_ms1);
		lcd_line2();
		lcd_time(time_ms2); 
	}
}

//STANDARD MAIN FUNCTION

int main( void ){
	//--------------------------------------
	//LCD STUFF TO GO IN MAIN FUNCTION
	//--------------------------------------
		
	// Make sure all our registers are clear
	DDRB = 0;
	DDRC = 0;
	DDRD = 0;
	
	PORTB = 0;
	PORTC = 0;
	PORTD = 0;
	
	// Initialize the LCD
	lcd_init();
	//-----------------------------
	//END MAIN FUNCTION LCD STUFF
	//------------------------------
	DDRC &= ~(1 << PC5);
	PORTC|=(1<<PC5); 
	
	DDRC &= ~(1 << PC4);
	PORTC|=(1<<PC4);
		
	//initialize timer 0
	TCNT0=~(124);//preload counter to overflow after 1 ms (125 counts)
	TIMSK=(1<<TOIE0);//enable interrupt on timer0 overflow
	TCCR0=(1<<CS01)|(1<<CS00);//set timer to normal mode with CPU clock/64 (125 kHz)
	
	sei();//enable all interrupts
	
	// time an event:
	timer_tick=0;            //start timer, clear global millisecond counter
	TCNT0 = ~(124);
		
	while(1){
		if (!(PINC&(1<<PC5))){
			_delay_ms(10);//delay for 10 ms to debounce the press
			time();
			break;
		}else if(!(PINC&(1<<PC4))){
			_delay_ms(10);//delay for 10 ms to debounce the press
			//run a different function
			break;
		}
	}

	return 0;
}

/*
TIMER 0 overflow interrupt service routine
This routine is called every millisecond
Operation: increment global variable timer_tick, reload TCNT0 to count 125 clock cycles
*/

ISR(TIMER0_OVF_vect)
{
   timer_tick++;
   TCNT0 = ~(125);         //preload counter to overflow after 1 ms (125 counts)
}

This version of the code should compile with no errors or warnings.

-Adam

Thats so good, thank you, It works, but i think i have the timing wrong.

I want the orangutan to run at full speed 8MHZ, so i have that opening line

#define F_CPU 8000000UL   // Orangutan frequency (8MHz)

at 8.

I have my fuse set to 8mhz start up time 6CK +64ms, and i dont know what else to change, but its far from accurate…

The only thing fasing me also, is i have a warning that opens delay.h when clicked on and highleights a line compiler optimization disabled:

which makes me wonder whether my timings wont work as designed?

With your project open in AVR Studio go to Project->Configuration Options. On the configuration window there should be a drop-down menu labeled “Optimization”. Change the setting of this menu from “-O0” to “-O1” and click okay. That should take care of the “optimization disabled” warning. How does your code work now?

When you say that the timing is wrong, what happens when you try to measure, say, eight seconds?

-Adam

Sweet, will try that, just been testing the potentiometer one…

I changed that config option, timed two 5 second intervals, and got 5.354 and 10.584 - is it adding the last time to it? in other words is it not restarting the timer after the 1st set of timing has been done?

The potentiometer one, is flicking through numbers without me even moving it! ADC7 is the one with the built in pot on yeah?

I cant tell what the numbers are - whether they are in order or out of order because they’re random… they should appear in order (1,2,3,4,5…) shouldnt they…

You need to make sure you have your “clock divided by 8” (CKDIV8) fuse unchecked.

- Ben

Thanks guys, the pot on the orangutan is pretty hard to turn cos of size, so bought this one

rapidonline.com/Electronic-C … entiometer

the 10 k one, and planned on wiring it up, but the data sheet is close to useless. It has 4 pins, and the data sheet doesnt mention which ones do what??? it also mentions rated voltage of 350v! surely not!

That’s probably just the rating on it’s insulation. At 350 volts a 10Kohm resistor would only draw 35 ma, but it would have to dissipate 12.25 watts as heat, well over the 0.5 watt rating.

You can figure out which pins are which with your multimeter’s resistance measuring setting. One pin is probably just connected to the metal case for easy ground-sheilding, so you can ignore this one. You should measure 10Kohm between two of the pins, these pins are the two ends of the resistor, and you’ll want to connect one of them to +5V and the other to ground. The the last pin is the wiper, which slides along the resistor. You should measure a resistance <=10Kohm between this pin and either of the end pins, and it will change as you move the slide. You will connect the wiper pin to an analog input pin.

-Adam

sweet did you see my post a couple above about the pot problem?

Yes, ADC7 has the built-in trim pot. If you want to post the current state of your code I’ll check it out on my Orangutan.

-Adam

Cool, Here is the whole code…

If i add the slide pot to the circuit, on ADC6, do i just need to change the 7 to a 6?

// F_CPU tells util/delay.h our clock frequency
#define F_CPU 8000000UL // Orangutan frequency (8MHz)
//#define F_CPU 20000000UL // Baby Orangutan frequency (20MHz)
#include <avr/io.h>
#include <util/delay.h>

void delayms( uint16_t millis ) {
while ( millis ) {
_delay_ms( 1 );
millis--;
}
}


const unsigned char single_zero_wheel[37]={0,32,15,19,4,21,2,25,17,34,6,
                                 27,13,36,11,30,8,23,10,5,24,
                                 16,33,1,20,14,31,9,22,18,29,
                                 7,28,12,35,3,26};

const unsigned char single_zero_order[37]={0,23,6,35,4,19,10,31,16,27,18,
                        14,33,12,25,2,21,8,29,3,24,5,
                        28,17,20,7,36,11,32,30,15,26,
                        1,22,9,34,13};


void analog_init(void)
{

ADMUX = (1 << REFS0);

ADCSRA = (6 << ADPS0);


ADCSRA |= (1 << ADEN);
}

unsigned int analog10(unsigned char channel)
{

ADMUX &= ~0x1F;

ADMUX |= channel;

ADCSRA |= (1 << ADSC);

while (bit_is_set(ADCSRA, ADSC));


return (ADCL | ADCH << 8); // read ADC (full 10 bits);
}

unsigned int analog8(unsigned char channel)
{
return(analog10(channel) >> 2);
}


 //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[8] = {0,0,0,'.',0,0,0,'s'};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
          
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------


// And now for our main routine:


int main( void )
{

		//--------------------------------------
        //LCD STUFF TO GO IN MAIN FUNCTION
        //--------------------------------------
         

               // Make sure all our registers are clear
               DDRB = 0;
               DDRC = 0;
               DDRD = 0;

               PORTB = 0;
               PORTC = 0;
               PORTD = 0;

          // Initialize the LCD
          lcd_init();
          //-----------------------------
          //END MAIN FUNCTION LCD STUFF
          //------------------------------

unsigned char i;
while(1)
		{



// Initialize the ADC:
		analog_init();


// The endless loop
   while(PINC&(1<<PC5)){//while button PC5 is not pressed
     // scale the potentiometer ADC value (0 - 255) to be a number from 0 - 36
     unsigned char pot_idx=(unsigned char)(analog8(7)*36/255);

     lcd_line2();
     lcd_int(pot_idx);
     
     _delay_ms(25);
   }
   
   unsigned char pot_idx=single_zero_order[pot_idx];
   
   while(pot_idx<=37){
     lcd_line2();
     lcd_int(single_zero_wheel[pot_idx]);
     
     pot_idx++;//increment pot_idx
     
     for(i=0;i<10;i++){
       _delay_ms(25);
     }

}
}
}

P.S wheres the divide by 8 fuse, the only one there relevent is 8mz start up time +6CK

my soldering iron is sooo bad, it cant melt solder on the tip…