Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Electronics newbie


#1

Hi everyone again… New to electronics but here to learn. So after following a couple of tutorials and buying a load of conponents, i have on a bread boardand led with a 270ohm resistor, hopefully, on a 5volt input to output 20mA., I am using the orangutan mega8 controller, and am having trouble reading the schematic for the pin2 of one of the i/o ports…
Does every conponent even sensors need a resisor in series?, how do you know the max current a conponent can take…?

How do i go about accessing the built in AD converter for say a humidity sensor? Does any one know of where theres an example piece of code for something like this?

Thanks

Alex


#2

Hello.

You need to have resistors in series with components where you need to limit current, such as LEDs. You don’t need to limit current when you are connecting your orangutan’s outputs to inputs of other microcontrollers, which are the typical connections you make to most advanced sensors. A microcontroller’s input already has a very high impedance that limits current to something very small (microamps, usually). The only time you might get into trouble is if you are driving a line one way (e.g. high) while the other microcontroller is driving that same line as an output the other way (e.g. low), in which case a current-limiting resistor might save you from having an I/O line burn out. Ideally, with careful programming and wiring, such a situation would never arise, though. Does this make sense?

To find out how much current a component can take you need to refer to that component’s datasheet. They’re easy to find (search digikey for the part or just google the part number), but they can be a little thick on the technical terminology. You’d want to look for tables describing electrical characteristics and maximum ratings. Every component has a datasheet, even resistors!

The analog-to-digital converter (ADC) on the mega8 is connected to general I/O pins PC0 through PC5 and to dedicated ADC pins ADC6 and ADC7. There are numerous code samples on this forum for using the ADC with the mega168 (I expect this code would also work on the mega8) and mega644. I suggest you download demo project #3 from the Orangutan LV-168 resources tab and look at the section that performs the analog-to-digital conversion of the trimpot. The interface to the AVR ADC hardware exactly what you want, though you might have to change the code around slightly to use different pins. The LCD and motor code from that example is specific to the Orangutan LV-168 and will not work on the Orangutan mega8. Please let me know if you have any questions about the code or any trouble getting it to work.

- Ben


#3

Thanks Ben, very detailed reply. I have just made a small circuit with an LED though on a breadboard, but I cant figure out which of the input sockets, at the front of the board(with three little breadboard like holes - 12 long) is on what pin - from the schematic or anywhere, do you know?

When I make the cicuit on the Bread board, do i need to power the led sepearately or will it get power from the board. Which of the three holes should i use, my breadboard circuit has each end of a circuit, i.e 2 wires…
Thanks
Alex


#4

Page 1 of the Orangutan quickstart sheet shows the pin assignments for the 12x3 I/O header block. The outside (bottom) row is ground, the middle row is power (Vcc or Vbat depending on the bank’s power jumper), and the inside (top) row connects to the AVR’s I/O pins (signal). The eight left-most pins can be used as analog inputs.

- Ben


#5

PD0 ----MM—|>|---- GND

You can power your LED using an AVR output. For example, connect pin PD0 to a resistor in series with an LED and connect the other lead of your LED to your Orangutan’s ground. In my crude ASCII diagram above, MM is the resistor and |>| is the LED. Configure PD0 to be an output and the LED should light whenever you drive PD0 high (assuming you have the LED oriented in the proper direction and your current limiting resistor is in the right range). In general, you want to choose a resistor so that perhaps 10 to 20 mA passes through your LED. If the resistor is too big, there won’t be enough current and the LED will be too dim to see. If the resistor is too small, you risk burning out the LED.

- Ben


#6

Thanks Ben,
I feel i need to show you my set up so see pic below, I think according to the datasheet of the orangutan v168 this is PC5. for PC5 i assume i just open PORTC. Anyway, i have turned the led round but still nothing. Can you see what I;ve done wrong?

Thanks
Alex

P.S Code is here - the bits where there is either PORTC or PC5 are the bits to do with the breadboard circuit, the rest works…

// 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--;
	}
}

int main( void ) 
{
	while(1)
	{
	DDRB |= (1 << PB0);		// set buzzer pin PB0 to output
	DDRC |= (1<< PC5);// led breadboard
	DDRB &= ~(1 << PB3);  // make PB3 (button SW3 pin) an input
	DDRD |= (1<<PD1); //Led output
	while ( 1 ) {
	if (PINB & (1 << PB3))
	{
		PORTB &= ~( 1 << PB0 );	// buzzer off
		PORTD |= (1 << PD1);//LED ON
		PORTC |= (1<< PC5);
		delayms( 5 );			// delay 50 ms
		PORTB |= (1 << PB0); //BUZZER ON
		PORTC &= ~(1 << PC5);
		PORTD &= ~(1 << PD1); 		// LED OFF
		delayms( 5 );			// delay 50 ms
		}
	else
      PORTB &= ~(1 << PB0);  
	  PORTD &= ~(1 << PD1);
	}
	}
	return 1;
	

}

P.P.S I tried to upload the photo but it says could not upload attachment…???


#7

We’ve enabled picture uploading (we think) so please try to upload it again. If that doesn’t work, you can host it using a free service such as imageshack or photobucket and link to it from here.

- Ben


#8

I suggest you try the following as your first program:

#include <avr/io.h>

int main( void ) 
{
   DDRC |= (1<< PC5);  // led pin set as output
   PORTC |= (1 << PC5);  // drive LED pin PC5 high
   while(1)  // loop forever
      ;
   return 0;
}

This should just turn your LED on and keep it on. After you get that working you should be able to easily modify this code to blink the LED or turn it on in response to a button press.

I recommend your first test be to just connect your LED-resistor pair so that one end is tied to the Orangutan’s 5V (Vcc) line and the other is tied to the Orangutan’s ground. If this works, you have set up your LED-resistor circuit correctly and you can move on to trying to control the LED with an I/O line.

- Ben


#9

Great I have the led fully working now. So can i do the same with a sensor such as a ultra sound or temperature sensor, then use the onboard a/d convertor to convert it to a number, and when that number is over a certain number, the led comes on? Or is there different theory for wiring sensors?


#10

You should be fine wiring sensor outputs directly to your Orangutan’s I/O pins so long as they’re configured as inputs. When set as inputs, their high input impedance will cause them to draw almost no current. Which outputs you use and how you use them will depend on the specific sensor. You would connect sensors that output analog voltages to your ADC inputs. Sensors that output digital signals would go to any of your digital inputs. Some sensors communicate with more advance protocols such as serial (UART), SPI, or I2C (TWI); you would want to connect these to the mega8 pins that correspond to the AVR’s UART, SPI, or I2C hardware. Does this make sense?

Internally, you would capture the input and perform some logic on it. That logic could easily be something like:

  1. Take in raw sensor data
  2. Convert raw data to a number between 0 and 255
  3. If number is greater than x, turn LED on, else turn LED off

The Orangutan has a 10k trimpot wired directly to pin ADC7 (one of the two dedicated ADC inputs). You can try using this as a sensor upon which your LED’s state depends. For example, use the mega8’s analog-to-digital converter to read the position of the trimpot and turn on the LED if this value exceeds some threshold.

- Ben


#11

Yeah i think that makes sense, i havent bought any digital sensors - thats step 2, for now i am just changing the led for a humidity sensor, and wiring it to adc7. There is a resistor in circuit - does that make any difference?

I’m not sure i understand how it knows there is a sensor though. Can i just ask for the value of the sensor to be saved as a variable? is there a basic example anywhere you know of of this being done?


#12

I downloaded that orangutan.lib example and see what you mean now. The following is the code from the initialisation of the ADC, there are a couple of questions though?

#define F_CPU 8000000UL

// The Baby-Orangutan is a 20MHz device
// So is the Orangutan-X2

// #define F_CPU 20000000UL


#include <avr/io.h>

// We're not actually using any delays in this program, so setting
// F_CPU is optional, as is including <util/delay.h>.  I'm not
// including it in this example, but it's a good idea to get in
// the habit of telling the compiler what speed device you're using.
// In the event that you DO need delays, that's one fewer thing to
// trip you up in your debugging effort.



// Initialize the ADC to do 10-bit conversions:
void analog_init(void) 
{
	// The Orangutans have an external reference voltage on the AREF
	// pin tied to our +5V regulated Vcc.  We want to set our ADC to
	// use this as our reference.  The ADMUX register needs REFS0
	// set to 1, and REFS1 set to zero for this mode.
	ADMUX = (1 << REFS0);

	// The ADC Control and Status Register A sets up the rest of 
	// what we need.  Three bits ADPS0, 1, and 2, set the prescale
	// for how fast our conversions are done.  In this example
	// we use CPU/64, or mode 6:

	ADCSRA = (6 << ADPS0);

	// Conversions take 13 ADC cycles to complete the sample and hold.
	// Dividing our CPU by 64 gives us the following samples/sec for
	// our devices:
	//
	// Orangutan	 9615
	// Baby-O		24038
	// X2			24038

	// Finally, we enable the ADC subsystem:

	ADCSRA |= (1 << ADEN);
}


// Read out the specified analog channel to 10 bits
unsigned int analog10(unsigned char channel) 
{
	// Begin by setting up the MUX so it knows which channel
	// to connect to the ADC:

	// Clear the channel selection (low 5 bits in ADMUX)
	ADMUX &= ~0x1F;
	// Select the specified channel
	ADMUX |= channel;

	// Now we initiate a conversion by telling the ADC's
	// control register to start conversion (ADSC):

	// ADC stert conversion
	ADCSRA |= (1 << ADSC);

	// We wait for conversion to complete by watching the
	// ADSC bit on the ADCSRA register.  When it goes away,
	// the conversion is done:
	while (bit_is_set(ADCSRA, ADSC));

	// Since we're reading out ten bits, we have to read 
	// the results out of two different registers: ADCL for
	// the low byte, and ADCH for the high byte.  Caution
	// here:  We have to read ADCL before we read ADCH.
	// Since they're both just bytes, we have to shift the
	// high byte over by 8-bits and or the two together
	// to make the full 10-bit value:

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


// And now for the maximum in cheesiness:  How do you do an
// 8-bit conversion if you're in 10-bit mode?  Simple!  Do a
// 10-bit conversion and ditch the two least significant bits.
// Laugh all you want, that's how AVRLIB does it, too.

// Read out the specified analog channel to 8 bits
unsigned int analog8(unsigned char channel) 
{
	return(analog10(channel) >> 2);
}

Somewhere there, it is saying tha it is using the adc channel with the pot meter on it, but i cant quite figure out where, unless its really obvious and i missed it, and hence how to change it to sat ADC6. If i wanted to use the ADC7 - the one with the pot meter, for a sensor, could i just turn the pot meter to full, and then attach a sensor?

What is VCC and Vbat, do they make a difference when attaching components,

and last question,

DDRC |= (1 << PC5);
PORTC |=(1<<PC5);

Quick reminder, this sets PCS as an output then turns it on, where as this:
DDRC |= (1 << PC5);
PORTC &=~(1 <<PC5);
Sets PC5 as output and turns it off.

Does:
DDRC |=(0 << PC5);
PORTC |=(0 << PC5);

set PC5 as input and then read from it?

Thanks
Alex


#13

Since I don’t know the specs for your sensor, I don’t know how it’s supposed to be wired up. If it has three leads (as I’m guessing it does), I imagine one would be connected to Vcc (5 V), one would be connected to ground, and the third would connect to your Orangutan’s I/O line. A small resistor on the signal line probably won’t hurt you too much, but it shouldn’t be necessary.

Pretty much any question you have about using the mega8’s hardware can be answered by looking at the mega8 datasheet, although it can be a bit difficult to follow if you’re new to AVRs. I suggest you take a quick look at the ADC section to see if its explanation of the mega8’s ADC hardware makes sense to you.

To answer your specific question: the low five bits of the ADMUX register determine the adc channel. In the code you posted you can see this here (especially since it’s well commented):

// Read out the specified analog channel to 10 bits
unsigned int analog10(unsigned char channel) 
{
   // Begin by setting up the MUX so it knows which channel
   // to connect to the ADC:

   // Clear the channel selection (low 5 bits in ADMUX)
   ADMUX &= ~0x1F;
   // Select the specified channel
   ADMUX |= channel;
   ...

PC0 is channel 0, PC1 is channel 1, …, PC5 is channel 5, ADC6 is channel 6, and ADC7 is channel 7. I suggest you connect your humidity sensor to a ADC6 and then call analog10(6) or analog8(6), depending on whether you want a 10-bit or 8-bit result.

Vbat is the voltage of your power supply (often this is a battery). Vcc is the regulated voltage used for digital logic. On the Orangutan Vcc is 5 V, but some devices use a Vcc of 3.3 V. Many sensors that use integrated circuits will expect a regulated 5 V as an input from which they will draw the power they need to operate. If you supply Vbat to them instead of Vcc, you could easily destroy them (since Vbat can often be much higher than 5 V).

[quote]Does:
DDRC |=(0 << PC5);
PORTC |=(0 << PC5);

set PC5 as input and then read from it?[/quote]
I understand the temptation to replace a 1 with a 0 when your goal is to set a bit to zero, but unfortunately this isn’t right. The << operator performs a “bit shift”. That is to say, it takes all the bits in a byte and shifts them left by the number of specified spaces. For example, imagine the byte 01101001:

01101001 << 1 = 11010010 (bit shift this number left by one bit)
01101001 << 3 = 01001000 (bit shift this number left by three bits)
01101001 >> 3 = 00001101 (bit shift this number right by three bits)

Because of the nature of binary numbers, bit shifting left is the same as multiplying by a power of two and bit shifting right is the same as dividing by a power of two. For example, take an arbitrary byte referred to as x that we will bit shift by n bits:

x << n can also be written as x * 2^n
x >> n can also be written as (int)(x / 2^n)

Now, in this light, if we look at 0 << PC5, we see that’s the same as 0 * 2^PC5, which is always zero. It doesn’t even matter what the value of PC5 is. Bit shifting zero will always just get us zero, so we’re going to need a different approach. It turns out that the correct way to clear (set to zero) a single bit in a byte while leaving all the other bits unchanged is the following:

DDRC &= ~(1 << PC5);

The ~ operator is “bitwise not” and will turn all 1 bits to 0 and all 0 bits to 1. If (1 << PC5) = (1 << 5) = 00100000, then ~(1 << PC5) = 11011111. When we AND this with DDRC, only bit 5 gets set to zero since 1 & x = x and 0 & x = 0. For a more detailed explanation of this, please see nexisnet’s fantastic post in this thread:

Something else I should note here is that the effect of the PORT register differs depending on whether the pin in question is an output or an input. If the DDR bit for the pin is 1, the pin is an output and the PORT bit for the pin determines if the pin is driven high (PORT bit = 1) or driven low (PORT bit = 0). If the DDR bit for the pin is 0, the pin is an input and the PORT bit for the pin determines if the pin weakly pulled high (PORT bit = 1) or floating (PORT bit = 0). Do you understand what I mean by “pulled high” and “floating”?

Note that when you are working with an AVR digital I/O pin, you set its output behavior with the PORT register and you read its input value with its PIN register. So, putting it all together, if I want to know what the value is of pin PC5, I would do the following:

DDRC &= ~(1 << PC5); // set PC5 as a digital input
unsigned char value = PINC & (1 << PC5); // use (1 << PC5) to mask away all of PINC except for bit PC5

If value = 0, I know that the input value on pin PC5 was low. If value = 1 << PC5, I know that the input value on pin PC5 was high.

- Ben


#14

Yeah I’m getting this now. (whoever designed it couldn;t have come up with something simpler?)

So I am understanding that this bit of code at the begining of the orangutan.lib example, is not reffering to a certain port, but to the onboard ADC overall:

void analog_init(void) 
{
	// The Orangutans have an external reference voltage on the AREF
	// pin tied to our +5V regulated Vcc.  We want to set our ADC to
	// use this as our reference.  The ADMUX register needs REFS0
	// set to 1, and REFS1 set to zero for this mode.
	ADMUX = (1 << REFS0);

	// The ADC Control and Status Register A sets up the rest of 
	// what we need.  Three bits ADPS0, 1, and 2, set the prescale
	// for how fast our conversions are done.  In this example
	// we use CPU/64, or mode 6:

	ADCSRA = (6 << ADPS0);

	// Conversions take 13 ADC cycles to complete the sample and hold.
	// Dividing our CPU by 64 gives us the following samples/sec for
	// our devices:
	//
	// Orangutan	 9615
	// Baby-O		24038
	// X2			24038

	// Finally, we enable the ADC subsystem:

	ADCSRA |= (1 << ADEN);
}


// Read out the specified analog channel to 10 bits
unsigned int analog10(unsigned char channel) 
{
	// Begin by setting up the MUX so it knows which channel
	// to connect to the ADC:

	// Clear the channel selection (low 5 bits in ADMUX)
	ADMUX &= ~0x1F;
	// Select the specified channel
	ADMUX |= channel;

	// Now we initiate a conversion by telling the ADC's
	// control register to start conversion (ADSC):

	// ADC stert conversion
	ADCSRA |= (1 << ADSC);

	// We wait for conversion to complete by watching the
	// ADSC bit on the ADCSRA register.  When it goes away,
	// the conversion is done:
	while (bit_is_set(ADCSRA, ADSC));

	// Since we're reading out ten bits, we have to read 
	// the results out of two different registers: ADCL for
	// the low byte, and ADCH for the high byte.  Caution
	// here:  We have to read ADCL before we read ADCH.
	// Since they're both just bytes, we have to shift the
	// high byte over by 8-bits and or the two together
	// to make the full 10-bit value:

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


// And now for the maximum in cheesiness:  How do you do an
// 8-bit conversion if you're in 10-bit mode?  Simple!  Do a
// 10-bit conversion and ditch the two least significant bits.
// Laugh all you want, that's how AVRLIB does it, too.

// Read out the specified analog channel to 8 bits
unsigned int analog8(unsigned char channel) 
{
	return(analog10(channel) >> 2);
}


// That's it for the ADC stuff.  Remember, there are lots of other
// ways the ADC subsystem can be used.  This is just ONE way.  If it
// doesn't meet your needs, read the data sheet and experiment.


// And now for our main routine:

In the main routine if i then specify a port such as how they do here:

// A variable to store our converted analog value in:
	int pot;

	// Initialize the ADC:
	analog_init();

	// Set up our LED as an output:
	DDRD |= (1 << PD1);

	// The endless loop
	for(;;)
	{
		// Store the value of our analog input:
		pot = analog10(7);

Setting the pot variable to the value of ADC7, then if i just change pot to:

pot = analog10(6);

then job done…?

If thats correct then i think ive got it, if i am supposed to change something in the function i posted just above, i cant see where because nothing there seems to refer to ADC7 specifically…

I have done that (what i’ve written above), but do i need to set ADC6 to an input, or is that standard, if so is its input line
DDRADC &= ~(1 << ADC6);
PORTADC &=~(1 <<ADC6);

The code i have is (look at main function because the initialisation of ADC is pasted…

// 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--;
	}
}

void analog_init(void) 
{
	// The Orangutans have an external reference voltage on the AREF
	// pin tied to our +5V regulated Vcc.  We want to set our ADC to
	// use this as our reference.  The ADMUX register needs REFS0
	// set to 1, and REFS1 set to zero for this mode.
	ADMUX = (1 << REFS0);

	// The ADC Control and Status Register A sets up the rest of 
	// what we need.  Three bits ADPS0, 1, and 2, set the prescale
	// for how fast our conversions are done.  In this example
	// we use CPU/64, or mode 6:

	ADCSRA = (6 << ADPS0);

	// Conversions take 13 ADC cycles to complete the sample and hold.
	// Dividing our CPU by 64 gives us the following samples/sec for
	// our devices:
	//
	// Orangutan	 9615
	// Baby-O		24038
	// X2			24038

	// Finally, we enable the ADC subsystem:

	ADCSRA |= (1 << ADEN);
}


// Read out the specified analog channel to 10 bits
unsigned int analog10(unsigned char channel) 
{
	// Begin by setting up the MUX so it knows which channel
	// to connect to the ADC:

	// Clear the channel selection (low 5 bits in ADMUX)
	ADMUX &= ~0x1F;
	// Select the specified channel
	ADMUX |= channel;

	// Now we initiate a conversion by telling the ADC's
	// control register to start conversion (ADSC):

	// ADC stert conversion
	ADCSRA |= (1 << ADSC);

	// We wait for conversion to complete by watching the
	// ADSC bit on the ADCSRA register.  When it goes away,
	// the conversion is done:
	while (bit_is_set(ADCSRA, ADSC));

	// Since we're reading out ten bits, we have to read 
	// the results out of two different registers: ADCL for
	// the low byte, and ADCH for the high byte.  Caution
	// here:  We have to read ADCL before we read ADCH.
	// Since they're both just bytes, we have to shift the
	// high byte over by 8-bits and or the two together
	// to make the full 10-bit value:

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


// And now for the maximum in cheesiness:  How do you do an
// 8-bit conversion if you're in 10-bit mode?  Simple!  Do a
// 10-bit conversion and ditch the two least significant bits.
// Laugh all you want, that's how AVRLIB does it, too.

// Read out the specified analog channel to 8 bits
unsigned int analog8(unsigned char channel) 
{
	return(analog10(channel) >> 2);
}


// That's it for the ADC stuff.  Remember, there are lots of other
// ways the ADC subsystem can be used.  This is just ONE way.  If it
// doesn't meet your needs, read the data sheet and experiment.


// And now for our main routine:


int main( void ) 
{
	while(1)
	{

// A variable to store our converted analog value in:
   int pot;

   // Initialize the ADC:
   analog_init();

	DDRB |= (1 << PB0);		// set buzzer pin PB0 to output
	DDRC |= (1<< PC5);// led breadboard
//	DDRB &= ~(1 << PB3);  // make PB3 (button SW3 pin) an input
	DDRD |= (1<<PD1); //Led output

   // The endless loop
   for(;;)
   {
      // Store the value of our analog input:
      pot = analog10(6);
if (pot > 512)
{
	
		PORTB &= ~( 1 << PB0 );	// buzzer off
		PORTD |= (1 << PD1);//LED ON
		PORTC |= (1<< PC5);// turn on breadboard
		delayms( 5 );			// delay 50 ms
		PORTB |= (1 << PB0); //BUZZER ON
		PORTC &= ~(1 << PC5);//turn off bread boar
		PORTD &= ~(1 << PD1); 		// LED OFF
		delayms( 5 );			// delay 50 ms
		}

	else
      PORTB &= ~(1 << PB0);  
	  PORTD &= ~(1 << PD1);
	  
	}
	}
	return 1;
	

}

#15

Heh, yeah, bit manipulation in C can be a tad confusing at first. There are probably a number of libraries out there that hide the complexities of it behind simpler interfaces. For example, you could define at the top of your program:

#define set_register_bit(reg, bit) reg |= (1 << bit)
#define clear_register_bit(reg, bit) reg &= ~(1 << bit)
#define is_bit_set(reg, bit) ((reg & (1 << bit)) == (1 << bit))  // returns 1 if register bit is 1, 0 if register bit is 0

Then in your program you could do things like:

int main()
{
  set_register_bit(DDRD, PD1);  // make pin PD1 (LED) an output
  clear_register_bit(DDRB, PB5);  // make pin PB5 an input
  while (1)
  {
    if (is_bit_set(PINB, PB5))  // if input on pin PB5 is high
      set_register_bit(PORTD, PD1);  // drive pin PD1 high (LED on)
    else
      clear_register_bit(PORTD, PD1);  // drive pin PD1 low (LED off)
  }
  return 0;
}

Something like this might make your programming easier and would probably make your code more readable.

DDR, PORT, and PIN registers are only used for digial I/O. The ADC hardware will perform a conversion on the specified channel regardless of its digital I/O state. In general, you want to set pins PC0 - PC5 as digital inputs if you plan to use them as analog inputs so that they aren’t trying to drive to a voltage. ADC6 and ADC7 are designated analog inputs (they cannot be used as digital I/O lines), so you don’t have to do anything to configure their I/O states.

I looked over your code briefly and it seems like that’s all you need to do. Let me know if it works out!

- Ben


#16

back to the good old asci diagrams,on adc6 i have
ADC6–Humidity sensor–grnd
the follwing program:

// 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--;
	}
}

void analog_init(void) 
{
	// The Orangutans have an external reference voltage on the AREF
	// pin tied to our +5V regulated Vcc.  We want to set our ADC to
	// use this as our reference.  The ADMUX register needs REFS0
	// set to 1, and REFS1 set to zero for this mode.
	ADMUX = (1 << REFS0);

	// The ADC Control and Status Register A sets up the rest of 
	// what we need.  Three bits ADPS0, 1, and 2, set the prescale
	// for how fast our conversions are done.  In this example
	// we use CPU/64, or mode 6:

	ADCSRA = (6 << ADPS0);

	// Conversions take 13 ADC cycles to complete the sample and hold.
	// Dividing our CPU by 64 gives us the following samples/sec for
	// our devices:
	//
	// Orangutan	 9615
	// Baby-O		24038
	// X2			24038

	// Finally, we enable the ADC subsystem:

	ADCSRA |= (1 << ADEN);
}


// Read out the specified analog channel to 10 bits
unsigned int analog10(unsigned char channel) 
{
	// Begin by setting up the MUX so it knows which channel
	// to connect to the ADC:

	// Clear the channel selection (low 5 bits in ADMUX)
	ADMUX &= ~0x1F;
	// Select the specified channel
	ADMUX |= channel;

	// Now we initiate a conversion by telling the ADC's
	// control register to start conversion (ADSC):

	// ADC stert conversion
	ADCSRA |= (1 << ADSC);

	// We wait for conversion to complete by watching the
	// ADSC bit on the ADCSRA register.  When it goes away,
	// the conversion is done:
	while (bit_is_set(ADCSRA, ADSC));

	// Since we're reading out ten bits, we have to read 
	// the results out of two different registers: ADCL for
	// the low byte, and ADCH for the high byte.  Caution
	// here:  We have to read ADCL before we read ADCH.
	// Since they're both just bytes, we have to shift the
	// high byte over by 8-bits and or the two together
	// to make the full 10-bit value:

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


// And now for the maximum in cheesiness:  How do you do an
// 8-bit conversion if you're in 10-bit mode?  Simple!  Do a
// 10-bit conversion and ditch the two least significant bits.
// Laugh all you want, that's how AVRLIB does it, too.

// Read out the specified analog channel to 8 bits
unsigned int analog8(unsigned char channel) 
{
	return(analog10(channel) >> 2);
}


// That's it for the ADC stuff.  Remember, there are lots of other
// ways the ADC subsystem can be used.  This is just ONE way.  If it
// doesn't meet your needs, read the data sheet and experiment.


// And now for our main routine:


int main( void ) 
{
	while(1)
	{

// A variable to store our converted analog value in:
   int pot;

   // Initialize the ADC:
   analog_init();

	DDRB |= (1 << PB0);		// set buzzer pin PB0 to output
	DDRC |= (1<< PC5);// led breadboard
//	DDRB &= ~(1 << PB3);  // make PB3 (button SW3 pin) an input
	DDRD |= (1<<PD1); //Led output

   // The endless loop
   for(;;)
   {
      // Store the value of our analog input:
      pot = analog10(6);
if (pot < 50)
{
	
		//PORTB &= ~( 1 << PB0 );	// buzzer off
		PORTD |= (1 << PD1);//LED ON
		PORTC &=~ (1<< PC5);// turn off breadboard
		delayms( 20 );			// delay 50 ms
		//PORTB |= (1 << PB0); //BUZZER ON
		PORTC |= (1 << PC5);//turn on bread boar
		PORTD &= ~(1 << PD1); 		// LED OFF
		delayms( 20 );			// delay 50 ms
		}

	else
      PORTB &= ~(1 << PB0);  
	  PORTD &= ~(1 << PD1);
	  
	}
	}
	return 1;
	

}

now i know it works because if i change it back to adc7 and adjust the potentiometer it works, but for some reason its not changing as humidity changes(by me breathing on it). so i think it must have somthing to do with my circuit…


#17

I think it’s more likely that the problem is with your code in the sense that it’s giving you such low resolution feedback. As you’ve posted it, the only time you’re going to get any sort of feedback is if the result of the analog-to-digital conversion (a number that ranges from 0 - 1023) is less than 50. That would correspond to a voltage less than 244 mV. I could imagine that your sensor is always outputing a voltage higher than this just due to ambient humidity.

Since you have the ADC working for the trimpot, I think maybe it’s time for you to bring the LCD into the equation. Ultimately, the easiest way to figure out what’s going on is to display the ADC result on the Orangutan’s LCD. Then, as you breath on the sensor, you might see the displayed number change from perhaps 553 to 642, for example. Orangutan-lib should have everything you need to easily integrate LCD functionality into your code.

- Ben

Edit: I would expect your humidity sensor to have a power connection as well as a ground connection, but you don’t show it in your ASCII schematic. Also, make sure your Orangutan and sensor share a common ground.