Turning Led's On and Off with Tiny85

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

//Sets up variable for storing bits from inputs and outputs      
int TCharge,FAssist,BBDetect;

//Begins Main Program
int main(void) 
{ 
     DDRB = 0b00000011;  		//Sets Port Bit 0 and 1 as outputs

     ADCSRA |= (1 << ADPS2) | (1 << ADPS1);  //ADC Prescalar set to 64 - 125kHz@8MHz 
	 ADMUX |= (1 << ADLAR);		//Changes to 8-bit resolution, read from ADCH
	 ADCSRA |= (1 << ADEN);  	// Enable ADC 

while (1)	//loop while 1
	{ 


//Push Button    
ADMUX |= (1 << MUX1) | (0 << MUX0);		//Selects Pin 3
ADCSRA |= (1 <<ADSC);					//Starts ADC conversion
while (ADCSRA & (1 << ADSC) );
  if(ADCH > 235)
	  {
		FAssist=1;
		BBDetect=0;
	  }


//Photo Diodes
ADMUX |= (1 << MUX1) | (1 << MUX0);		//Selects Pin 2
ADCSRA |= (1 <<ADSC);					//Starts ADC conversion
  if(ADCH < 25)
	  {
		BBDetect=1;
		FAssist=0;
	  }


//Detection Logic  
  if (FAssist==1)
      { 
        PORTB |= (1 << 0); 	// Green ON
		PORTB &= ~(1 << 1);	// Red OFF
      }

  if (BBDetect==1)
	  {  
        PORTB &= ~(1 << 0); 	// Green OFF
		PORTB |= (1 << 1);  	// Red ON
      } 


	} 

} 

This is all the code I have in my program so far. But for some reason it will not the Green LED on and I do not understand why. What am I missing in my code? I am thinking that I am not switching channels correctly as I can make both leds work with a single input, but when I try to use a combination of two it doesn't work. Normall what I can do is press a button and have one led turn on, then I let go and it turns off. I want to press one button to make it go on and press another to make it go off, kind of like a light switch. And I want to use stored bits to do that, in this case FAssist and BBDetect.

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

Alright, I have discovered what is the cause of my problems, when I enable ADC 0011 it stays enabled so it is only reading that input and it will do one function but the other does not respond. I tried ADMUX &= ~(0 << MUX0); to turn it off, but no luck, how do I set the channel back again?

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

do, never mind, typo, should have been ADMUX &= ~(1 << MUX0);, i had a 0 not a 1. Problem solved.

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

If you keep on answering yoursef they will come and lock you up.... :shock: but as long as you found the problem all is well I guess. :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

//Sets up variable for storing bits from inputs and outputs------------      
int TCharge,FAssist,BBDetect;

//Begins Main Program--------------------------------------------------
int main(void) 
{ 
     DDRB = 0b00000011;  	//Sets Port Bit 0 and 1 as outputs
     ADCSRA |= (1 << ADPS2) | (1 << ADPS1);  //ADC Prescalar set to 64 - 125kHz@8MHz 
	 ADMUX |= (1 << ADLAR);		//Changes to 8-bit resolution, read from ADCH
	 ADCSRA |= (1 << ADEN);  	// Enable ADC 

//---------------------------------------------------------------------
while (1)								//loop while 1
	{ 
while (ADCSRA & (1 << ADSC) );

//PUSH BUTTON----------------------------------------------------------
ADMUX |= (1 << MUX1);		//Selects Pin 3 (Push Button)
ADMUX &= ~(1 << MUX0); 		//Selects Pin 3 after other pins have been selected
ADCSRA |= (1 <<ADSC);					//Starts ADC conversion
  if(ADCH > 235)						//Determines if Pin 3 is > 4.6V
	  {
		FAssist=1;
		BBDetect=0;
	  }


//PHOTO DIODES---------------------------------------------------------
ADMUX |= (1 << MUX1) | (1 << MUX0);		//Selects Pin 2 (Photo Diodes)
ADCSRA |= (1 <<ADSC);					//Starts ADC conversion
  if(ADCH < 25)							//Determines if Pin 2 is < 0.45V
	  {
		BBDetect=1;
		FAssist=0;
	  }


//DETECTION LOGIC------------------------------------------------------
  if (FAssist==1)
      { 
        PORTB |= (1 << 0); 				// Green ON
		PORTB &= ~(1 << 1);				// Red OFF
      }
  if (BBDetect==1)
	  {  
        PORTB &= ~(1 << 0); 			// Green OFF
		PORTB |= (1 << 1);  			// Red ON
      } 
//---------------------------------------------------------------------
	}
} 

Although I solved the issue with the channels not changing, I am still not reading correctly for some reason, I get no response and I do not understand why. Any ideas?

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

Yet another problem along with what I'm still trying to figure out, I went into debug mode to watch the bits in the AD converted, now when I hit the little blue stop button and try to program it gives them that ISP error message every time, this has happened to 3 TIN85's now, I thought I was killing them ,but I think its stuck in debug, how do I get it out of debug mode?

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

Quote:
how do I get it out of debug mode?
Well you could start by reading the Studio's help file for the DW debugger you are using, Dragon or JTAGICE Mk2. :shock:

But usually it invoves just going into a debug session and then go to debug > dragon (or JTAG Mk2 ) options and turn off DW from there.

Or you can plug it into a STK500 or Dragon and do a HVPP...much easier doing the first thing above.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Thanks, I did look at the help file for debugging using the dragon in studio, but all I was able to find on it was how to set up the debug from a physical standpoint. I could not find anything useful on settings and procedures in software other than how to start debug process.

Back to the question 3 posts above, if you look at my code, do you understand why I am not reading my inputs? What happens is I get the light to turn off using the photo diodes hooked to one input, but it won't respond to my push button signal, so its not reading from the other input once it goes through the loop once, or there is a timing issue, however according to the specs the tiny85 only needs one clock cycle to switch channels, which it should have that time due to location I have for channel switching, I experimented with placing the channel switch in different parts of the loop to give it more clock cycles in between to ensure a switch, but it made no difference. So I'm stumped as to why its doing this.

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

Quote:
do you understand why I am not reading my inputs?
Are you talking about reading ADC values? If so I don't see you doing anything with the most important bit in the ADC, the ADIF bit. :wink:

And as far as disabling DW you will find this in the docs for the Dragon:

Quote:
6.2.3 Re-enabling the ISP interface
By following the description below, the ISP Interface is re-enabled.

Connect the AVR Dragon to the target with ISP (6-pin connection) as described above.

Load a project and Start a debug session using the "Start Debugging" command (found under the Debug pulldown-menu in AVR Studio)

Open "AVR Dragon Options" (found under the Debug pulldown-menu in AVR Studio) and select the "Connections" tab.

Click on the button "disable DebugWIRE" as shown in the figure below. And click "Yes" in the next message box.

Figure 6.8.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Your logic is totally wrong. The first thing you do in your while loop is wait for a conversion to finish, but you haven't yet even started a conversion. You then go on to change channels and start conversions twice, but neither time do you wait for the conversions to finish. The logic should be:

Set the channel
Start a conversion
Wait for the conversion to finish
Read the result
Set the second channel
Start a conversion
Wait for the conversion to finish
Read the result

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:
If so I don't see you doing anything with the most important bit in the ADC, the ADIF bit.

The ADIF bit is totally unnecessary if you are not using the ADC interrupt.

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:
The ADIF bit is totally unnecessary if you are not using the ADC interrupt.
Really? I have been using it since I have used AVR's to find out when the conversion has been completed. :shock:

OK so some prefer to look at the ADSC bit returning to zero to check for conversion complete but I have always used ADIF, don't know where I got that from. :wink:

Quote:
When a conversion
is complete, the result is written to the ADC Data Registers, and ADIF is set. In
Single Conversion mode, ADSC is cleared simultaneously

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

The loop is wrong, I see what you mean, it should be at the end.
I am not sure how my logic is out of order though, I have it in that order in what I posted above:
1. ADMUX |= (1 << MUX1); is channel selection
2. ADCSRA |= (1 <<ADSC); is start the conversion
3. using the ADIF or ADSC sounds like a good idea to ensure the conversion is finished, that is the only thing I don't have implemented. So I will try that first.

Last Edited: Sun. Mar 22, 2009 - 08:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

OK so some prefer to look at the ADSC bit returning to zero to check for conversion complete but I have always used ADIF, don't know where I got that from.

Either obviously works but the advantage of ADSC is thta it is self-clearing as well. With ADIF you then have to write '1' to reset it. You obviously know this but 10's of previous posters to this board clearly didn't and wonder why they only ever got one reading.

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

//Sets up variable for storing bits from inputs and outputs------------      
int TCharge,FAssist,BBDetect;

//Begins Main Program--------------------------------------------------
int main(void) 
{ 
     DDRB = 0b00000011;  	//Sets Port Bit 0 and 1 as outputs
     ADCSRA |= (1 << ADPS2) | (1 << ADPS1);  //ADC Prescalar set to 64 - 125kHz@8MHz 
	 ADMUX |= (1 << ADLAR);		//Changes to 8-bit resolution, read from ADCH
	 ADCSRA |= (1 << ADEN);  	// Enable ADC 

//---------------------------------------------------------------------
while (1)								//loop while 1
	{ 

//PUSH BUTTON----------------------------------------------------------	
ADMUX |= (1 << MUX1);		//Selects Pin 3 (Push Button)
ADMUX &= ~(1 << MUX0); 		//Selects Pin 3 after other pins have been selected
ADCSRA |= (1 <<ADSC);					//Starts ADC conversion
 if(ADSC == 0)				//Waits for AD conversion to finish before reading ADCH
 {
	if(ADCH > 235)						//Determines if Pin 3 is > 4.6V
	  {
		FAssist=1;
		TCharge=0;
	  }
 }

//HALL AFFECT SENSOR---------------------------------------------------
ADMUX |= (1 << MUX0);		//Selects Pin 2 (HALL AFFECT SENSOR)
ADMUX &= ~(1 << MUX1); 		//Selects Pin 2 after other pins have been selected
ADCSRA |= (1 <<ADSC);					//Starts ADC conversion
 if(ADSC == 0)				//Waits for AD conversion to finish before reading ADCH
  {	
	if(ADCH > 133)						//Determines if Pin 2 is < 0.45V
	  {
		TCharge=1;
		FAssist=0;
	  }
  }

while (ADCSRA & (1 << ADSC) );
//---------------------------------------------------------------------

//DETECTION LOGIC------------------------------------------------------
  if (FAssist==1)
      { 
        PORTB |= (1 << 0); 				// Green ON
		PORTB &= ~(1 << 1);				// Red OFF
      }
  if (TCharge==1)
	  {  
        PORTB &= ~(1 << 0); 			// Green OFF
		PORTB |= (1 << 1);  			// Red ON
      } 
//---------------------------------------------------------------------
	}
} 


//Notes: 2.56v/256 = 10mV resolution in 8-Bit mode
//		 5v/256 = 19.5mV resoltuion in 8-bit mode

That is what I have come up with based on your suggestions, I should be able to read ADSC directly shouldn't I? However what I really need are a sort of GOTO type function so if ADSC is not = 0 then it will keep looping unil it is, whats up there now obviously will not work yet because it will just keep starting a new conversion and never reading it. I was thinking of looping that with a while statement any other ideas that would work better?

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

I can't seem to think of any way to do a loop that will just repeat checking if ADSC = 1 and then go to the next line of code when ADSC = 0.
If I write:
do
if(ADCH > 235)
{
FAssist=1;
TCharge=0;
}
while(ADSC == 1)

it will terminate once ADSC = 0 and not read the value from ADCH in the if statement, if I use
do
while(ADSC == 1)
if(ADCH > 235)
{
FAssist=1;
TCharge=0;
}
I get compile errors. Not sure how to implement a while loop to wait for ADSC to equal 0 then go the next line.

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

You have to tell the compiler the register (ADCSRA) and the bit just like you are doing here while (ADCSRA & (1 << ADSC) ); and elsewhere.

You can also use the loop_until_bit_is_set or loop_until_bit_is_clear macros. This is the messy way I do it with ADIF

	ADCSRA |= (1<<ADSC);					//Start conversion
	loop_until_bit_is_set(ADCSRA, ADIF);	//Wait for conversion complete
	ADCSRA |= (1<<ADIF);					//Clear conversion flag

untested using ADSC..

	ADCSRA |= (1<<ADSC);					//Start conversion
	loop_until_bit_is_clear(ADCSRA, ADSC);	//Wait for conversion complete

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Ok, that's what I was looking for, because I looked through do while, while, and for loops and they are essentially all the same, I could use those to wait until ADSC was no longer 1, but as soon as that happened with the while loops it would then skip reading, if I used <= then it would obviously get stuck on reading in a loop because we are only dealing with 0 or 1 states.

I am not fully understanding the macro part loop_until_bit_is_clear(ADCSRA, ADSC);, I know what it does, but how do I create the macro? Is it created from a series of commands such as loop, until, bit etc? or are is that just a name designation to a macro in AVR studio? And if its a macro already created I should be able to just plug it in correct?

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

Quote:

I am not fully understanding the macro part loop_until_bit_is_clear(ADCSRA, ADSC);, I know what it does, but how do I create the macro?

Which is the downside of using that kind of macro. If you simply use:

ADCSRA |= (1<<ADSC);               //Start conversion 
while (ADCSRA & (1<<ADSC));        // wait while ADSC still 1

it'll have exactly the same effect and it's totally visible what's going on as it's completely standard C.

Without looking it up I'm guessing loop_until_bit_is_clear() is probably nothing more than:

#define loop_until_bit_is_clear(reg, bit) while(reg & (1<<bit))

EDIT: OK, curiosity got the better of me, the definition in sfr_defs.h is actually the slightly more sensible:

#define loop_until_bit_is_clear(sfr, bit) do { } while (bit_is_set(sfr, bit))

which relies on:

#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))

which in turn relies on:

#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))
#define _BV(bit) (1 << (bit))

but that's just a case of "same meat, different gravy"

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

Quote:
it's completely standard C.
.. :wink:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly