A little Attiny 13 C-code Help Please

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm having a little trouble with this piece of code.

If I run the code without adding values to a list and aveverging the total. Then the LEDS light up and blink as voltage changes occur :?

A little help please :lol:

#include  
#include  
#include  
// define F_CPU to CPU clock frequency before including delay.h 
#define F_CPU 575000UL 
#include 

//Define Fuel LEDs
#define LEDS PORTB // Port B
#define CHANNEL 1
#define Full_Tank 0x04 //0b00000100 
#define Three_Quater_Full 0x14 //0b00010100 
#define Half_Full 0x1C //0b00011100 
#define Quater_Full 0x1E //0b00011110 

//				*****	 Global Variables	*****

static unsigned int on_time_duration = 800;
static unsigned int off_time_duration = 500;

volatile uint16_t ADC_Readings[10];
unsigned char ADC_Readings_Count = 0;

/****************************************************************************************
***********************************   Functions  ****************************************
****************************************************************************************/
void blink_led(void)
{
	LEDS= 0x1F;		//0b00011111
	DDRB = 0xFB;	// No Pull-up Resistors
	//Delay needed for the stabilization of the ADC
	_delay_ms(off_time_duration);
	LEDS= 0x1E;		//0b00011110;
	DDRB = 0xFB;	// No Pull-up Resistors
	//Delay needed for the stabilization of the ADC
	_delay_ms(on_time_duration);
}


//Get ADC values from list

uint16_t get_adc_readings (void)
{ 
	int i; 
	uint16_t readings_value = 0;
	
	for (i=0; ADC_Readings[i] <= 9; i++)
	{
		readings_value = readings_value + ADC_Readings[i-1];
	}
	readings_value = readings_value / 10;
	
	
	return readings_value;
	
}	

//Add ADC values to list

void set_adc_reading (uint16_t adc_value)
{
	if (ADC_Readings_Count <= 8)
	{
		ADC_Readings[ADC_Readings_Count] = adc_value;
		++ ADC_Readings_Count;
	}
	else
	{
		ADC_Readings[ADC_Readings_Count] = adc_value;
		ADC_Readings_Count = 0;
	
	}
}

//Light up LEDS according to the averaged ADC value from list

void update_display (void)
{
	uint16_t adc_data = get_adc_readings();
	
	if (adc_data >= (4*1023)/5)
		LEDS = Full_Tank;
			else if	(((adc_data < (4*1023)/5)) && (adc_data  >=(3*1023)/5))
				LEDS = Three_Quater_Full;							
				else if	(((adc_data < (3*1023)/5)) && (adc_data  >=(2*1023)/5))
					LEDS = Half_Full;					
					else if (((adc_data < (2*1023)/5)) && (adc_data  >=(1023)/5))
						LEDS = Quater_Full;
						else 
						blink_led();
						
			
			DDRB = 0xFB; // No Pull-up Resistors
			
			//Delay needed for the stabilization of the ADC
			asm("nop");
}


/****************************************************************************************
*********************************   End Functions  **************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
**************************	 Interrupt Service Routines		*****************************
*****************************************************************************************/

ISR(TIM0_OVF_vect) //Timer0 OverFlow Interrupt
{
	ADCSRA = 0xEE; // Start ADC conversion
	ADCSRB = 0x04;
}



 ISR(ADC_vect) // ADC Interrupt Service Routine
{

// Set to Read Channel 1 Only  
		ADMUX=CHANNEL;
		
		set_adc_reading(ADCW);
	
		
		if(ADC_Readings_Count == 0)
			update_display ();
			
		// Reset Clock
		TCNT0=0x00;	
}	
/****************************************************************************************
************************** End Interrupt Service Routines	*****************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************   Initialization Routine	*********************************
*****************************************************************************************/

void initialization_routine (void)
{		
	//  ADC Setup
		ADMUX = CHANNEL;		// ADC Read Channel 1, Pin PB2
		
		DIDR0 = 0xFD;			/*Disable all ADC Input Buffers 
								  Except for Channel 1, Pin PB2*/
		
	//  Timer/Counter Setup
		TCCR0A=0x00;			/*Clock Mode: Normal top=FFh*/
		TCCR0B |= (1<<CS02);	/*Start Timer with 256 pre-scaler*/ 
		TIMSK0 |= (1<<TOIE0);	/*Enable Timer/Counter 0 Interrupt(s) initialization*/
		TCNT0=0x00;				/*Set Timer Counter Initial Value*/ 
 
		sei();					/*Set Global Interrupts*/
}
/****************************************************************************************
***************************   End Initialization Routine  *******************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
**********************************   Main Program  **************************************
*****************************************************************************************/
int main(void)
{
	//  Initialize Chip
		initialization_routine(); 

	    while(1)
		{
		/*Wait On Interrupts*/
			;;
		}
		return(0);
}

Thanks,

Bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   ADCSRA = 0xEE; // Start ADC conversion
   ADCSRB = 0x04; 

Without knowing which AVR this is it's impossible to tell what those lines are doing but let's guess it's mega168 so those lines say:

   ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1); // Start ADC conversion
   ADCSRB = (1<<ADTS2); 

Do you not think it maybe a little unwise to start the conversion (ADSC) and only then set ADTS2?

Also you are doing long display work out of an ISR - this seems very unwise.

Your whole structure of clocking the ADC from the T0 overflow but then setting TCNT0 in the ADC ISR seems "odd". What is your thinking behind this?

Also you set no Aref bits in ADMUX. If this were a 168 that would mean the reference is the Aref pin - is that set up correctly?

Finally what exactly does happen: "Then the LEDS light up and blink as voltage changes occur" is not much of a fault report.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The title post says TINY13 so presumably that's the CPU he's using....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you are using a Tiny13 and ADC0 i.e. the RESET pin.
All your other i/o pins are tied up with LEDs.

Life is very difficult if you develop with the RESET pin.
You cannot use debugWire. You cannot ISP twice.

Surely you develop on a bigger AVR, or perhaps use ADC1, and miss out LED2.
You only blow the RSTDISBL fuse at the final compilation.

I definitely agree with Cliff about the symbolic bit-names. It makes life easier. Those Tiny AVRs are almost as complex as a Mega.

Incidentally, how much flash and SRAM are you using ?

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   for (i=0; ADC_Readings[i] <= 9; i++) 

Surely you wanted to write this:

   for (i=0; i <= 9; i++) 

Or

   for (i=0; I < 10; i++) 

[/code]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's been some time since I've wrote code, but the chip is a tiny 13A.

PB2 is input voltage from the pot to simulate a sending unit while it's on the board. All four Leds are to be on at maximum voltage and at minimum voltage only one should blink.

I have the reset disabled and the pin is unused.

ADMUX is set for channel 1.

When I first wrote the code, before storing ADC values in the array[10] everthing functioned as expected. Now it just blinks at minimum voltage.

The ARef is set to use Vcc.

I reset the counter back to zero at the end of the adc_interrupt. I guess that's not needed from Cliffs statement.

I think my flash is at 34% and the SRAM is at 51%, but this is only from the array.

I hope this answers your questions, I just stumped.

Thanks,

Bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry. I had misread your DDRB value.

You start with i = 0 !!

      readings_value = readings_value + ADC_Readings[i-1]; 

As a question of style, choice of variable name helps.

uint16_t get_adc_readings (void)
{
   int i;
   uint16_t readings_total = 0;
   for (i=0; i < 10; i++)
   {
      readings_total = readings_total + ADC_Readings[i];
   }
   return readings_total / 10;
   
}

Use your array index 0..9 or count 1..10
Since your variable is global, I have not changed the name. However ADC_Readings_Index would be more appropriate.

void set_adc_reading (uint16_t adc_value)
{
   if (++ADC_Readings_Count >= 10)
      ADC_Readings_Count = 0;
   ADC_Readings[ADC_Readings_Count] = adc_value;
}

Your memory usage should be fine.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

   for (i=0; ADC_Readings[i] <= 9; i++) 

Surely you wanted to write this:

   for (i=0; i <= 9; i++) 

Or

   for (i=0; I < 10; i++) 

[/code]

That's fixed it, What can I say besides Dha!!! :oops:

Thanks Everyone!

Bill