New beginner help! (Orangutan X2 & Sharp IR sensors)

I am trying set my 2 IR sharp sensors as two inputs for portA and based on the change voltage from the sensors have my motor values change and servo turn on.But I keep getting errors for not declaring my port function. Also any suggestions for the while condition.Thanks
Errors
…/run.c:9: error: ‘DDRA’ undeclared (first use in this function)
…/run.c:9: error: (Each undeclared identifier is reported only once
…/run.c:9: error: for each function it appears in.)
…/run.c:22: error: ‘PORTA’ undeclared (first use in this function)

#include <avr/io.h>
#include "SPI.h"

int main( void ) 
{
   SPIInit(); // initialize SPI hardware module for communication with auxiliary mega168
   DDRA &= ~(1 << 1);  // make PA1 (sensorleft) an iput
   DDRA &= (1 << 2);  // make PA2 (sensorfront) an input
   DDRA |= (1 << 0);  // make PA0 (servo) an output
     
   //while()//senorleft has not changed in dc volts
   {
   setMotor1(255);
   setMotor2(255);
   delay_ms(2);
   }
      PORTA = 0x01;  // make PA0 (servo) high
       delay_ms(2); 
   setMotor1(-255);
   setMotor2(255);
   // set motor 1 forward at full speed (from SPI.h)
   while (1)//infinite loop
   ;
    return 0;
}

Hello.

My guess is that your AVR Studio project is set for the device atmega168 instead of atmega644. The mega168 does not have a port A, so references to DDRA, PORTA, and PINA will come up as undefined. Select the Configuration Menu option from AVR Studio’s Project menu. Under the General tab you can specify the device as atmega644.

Also, in your code, you have an incorrect line:

DDRA &= (1 << 2); // make PA2 (sensorfront) an input

This should be:

DDRA &= ~(1 << 2); // make PA2 (sensorfront) an input

Without the bitwise not (~), you’re just leaving PA2 unchanged while clearing all the other bits of DDRA.

Lastly, your approach is not going to work very well for Sharp IR sensors. These sensors output analog voltages, so you will want to use analog inputs rather than digital inputs. There are a number of threads on this forum that address performing analog-to-digital conversions with the X2 (perhaps do a search for something like X2 ADC).

- Ben

ADCSRA = 0x87;      // bit 7 set: ADC enabled
                  // bit 6 clear: don't start conversion
                  // bit 5 clear: disable autotrigger
                  // bit 4: ADC interrupt flag
                  // bit 3 clear: disable ADC interrupt
                  // bits 0-2 set: ADC clock prescaler is 128

   ADMUX = 0x05;      // bit 7 and 6 clear: voltage ref is Vref pin
                  // bit 5 set: right-adjust result (10-bit ADC)
                  // bit 4 not implemented
                  // bits 0-3: ADC channel (channel 5)

  while (1)         // loop forever
   {
      long sum = 0;
      unsigned int avg, i;

      for (i = 0; i < 512; i++)
      {
         ADCSRA |= ( 1 << ADSC );         // start conversion
         while ( ADCSRA & ( 1 << ADSC ))      // wait while converting
            ;
         sum += ADC;                     // add in conversion result
      }
      avg = sum >> 9;   
	}

This is the code I found, but let me make sure Im interpreting it right. The first line sets port A as the ‘10000111’ to make pin 7 the input of the sensor. I dont know what the ADMUX is or what its doing. Also the for loop it understandable, but where are the values ADSC and ADC coming from?

If you really want to understand how the mega644’s ADC hardware works, I strongly suggest you read through the ADC section of the mega644 datasheet.

The first line has nothing to do with port A. It’s setting the ADC Status Register A (ADCSRA) to configure the ADC hardware. It configures the hardware exactly as described in the comments in the code: ADC enabled, ADC interrupt disabled, ADC clock = CPU clock / 128. ADMUX is the register that determines on which channel the conversion is performed, along with whether the conversion result is left-adjusted (useful for 8-bit conversions) or right-adjusted (useful for 10-bit conversions). The code in your post configures ADMUX to use the Vref pin as the voltage reference, to right-adjust the conversion result (10-bit conversion), and to perform the conversion on channel 5 (which corresponds to pin PA5).

These are mega644-specific values that are included in your program when you use the line #include <avr/io.h>. ADSC is the number of the bit in ADCSRA that can be used to start a conversion and tell when that conversion finishes. ADC is a two-byte register (it consists of high byte ADCH and low byte ADCL) that contains the result of the last analog-to-digital conversion. Once our conversion is finished, you look to ADC to discover the result.

If this all seems a bit confusing to you and the datasheet doesn’t help clear it up, I suggest you try using Orangutan-lib’s ADC routines. It defines some convenient functions that hide away a lot of the complexities you might not need to concern yourself with. If you use Orangutan-lib, you can just call a function like:

unsigned int result = analog10(3);

to perform a 10-bit analog-to-digital conversion on the voltage on pin PA3.

- Ben

Looking at the datasheet really sheds a light on everything. Thanks I really needed that

#include <avr/io.h>
#include "SPI.h"
#include "device.h"
#include "servo.h"


int main() 
{
   SPIInit(); // initialize SPI hardware module for communication with auxiliary mega168
      
	  //declaring variables
  ADCSRA = 0x87;
   
while(1)
{	int sum = 0;
	
	unsigned char average;

	ADMUX = 0x23;//Value of bottom left sensor in PA3
	//first sensor conversion
	/////////////////////////
	for (int i = 0; i < 8; i++)
	{
	  ADCSRA |= 1 << ADSC;  // start conversion
	  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
	  sum += ADCH;
	}
	average = sum / 8;

	float sensor2 = average;
	while(average>2)
	{
		
		setMotor1(130);
		setMotor2(-130);
		int sum2=0;
		

	ADMUX = 0x23;//Value of bottom left sensor in PA3
	//first sensor conversion
	/////////////////////////
	for (int i = 0; i < 8; i++)
	{
	  ADCSRA |= 1 << ADSC;  // start conversion
	  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
	  sum2 += ADCH;
	}
	average = sum2 / 8;

	float sensor2 = average;
		
	
		
	}
		while(average<2)
	{
		
		setMotor1(130);
		setMotor2(130);
		int sum2=0;
		 

	ADMUX = 0x23;//Value of bottom left sensor in PA3
	//first sensor conversion
	/////////////////////////
	for (int i = 0; i < 8; i++)
	{
	  ADCSRA |= 1 << ADSC;  // start conversion
	  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
	  sum2 += ADCH;
	}
	average = sum2 / 8;

	float sensor2 = average;
		
	}
}
// set motor 1 forward at full speed (from SPI.h)
	return 0;
}

For some reason all this program does is, turn left; then stop, then turn left and stop; continously. And I want it to only turn when the sensor voltage is greater than 2, can someone help me?

took care of it. Thanks

This is a code to display six sensor values on the LCD screen and for some reason the value for the last sensor ‘average5’ starts off at 86 for some reason. Can someone help me with this

int sum=0;
	
		unsigned int average, average1,average2,average3,average4,average5;
	 	ADMUX = 0x20;//Value of top left sensor in PA0
		//first sensor conversion
		int i=0;
		/////////////////////////
		for (i = 0; i < 8; i++)
		{
		  ADCSRA |= 1 << ADSC;  // start conversion
		  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
		  sum += ADCH;
		}
		average = sum / 8;
		
		int sum2=0;
	
		ADMUX = 0x22;//Value of bottom right sensor in PA2
		//second sensor conversion
		/////////////////////////
		for (i = 0; i < 8; i++)
		{
		  ADCSRA |= 1 << ADSC;  // start conversion
		  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
		  sum2 += ADCH;
		}
		average1 = sum2 / 8;

		int sum3=0;
	
	 	ADMUX = 0x23;//Value of bottom left sensor in PA3
		//first sensor conversion
		i=0;
		/////////////////////////
		for (i = 0; i < 8; i++)
		{
		  ADCSRA |= 1 << ADSC;  // start conversion
		  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
		  sum3 += ADCH;
		}
		average2 = sum3 / 8;
		
		int sum4=0;
	
		ADMUX = 0x24;//Value of front left sensor in PA4
		//second sensor conversion
		/////////////////////////
		for (i = 0; i < 8; i++)
		{
		  ADCSRA |= 1 << ADSC;  // start conversion
		  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
		  sum4 += ADCH;
		}
		average3 = sum4 / 8;

		int sum5=0;
	
		
	 	ADMUX = 0x25;//Value of front right sensor in PA5
		//first sensor conversion
		
		/////////////////////////
		for (i = 0; i < 8; i++)
		{
		  ADCSRA |= 1 << ADSC;  // start conversion
		  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
		  sum5 += ADCH;
		}
		average4 = sum5 / 8;
		
		int sum6=0;
	
		
	 	ADMUX = 0x26;//Value of front right sensor in PA5
		//first sensor conversion
		
		/////////////////////////
		for (i = 0; i < 8; i++)
		{
		  ADCSRA |= 1 << ADSC;  // start conversion
		  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
		  sum6 += ADCH;
		}
		average5 = sum6 / 8;

	   	LCDHome();  // move to column 0 of row 0
	    LCDAddString("TL = ");
	    LCDUInt(average);
	    LCDAddString("  ");
	   	LCDMoveCursor(LCD_ROW_0 + 10);  // move to column 10 of row 0
	    LCDAddString("BR = ");
	    LCDUInt(average1);
	    LCDAddString("  ");
		LCDMoveCursor(LCD_ROW_1);
		LCDAddString("BL = ");
	    LCDUInt(average2);
	    LCDAddString("  ");
	    LCDMoveCursor(LCD_ROW_1 + 10);  // move to column 10 of row 0
	    LCDAddString("FL = ");
	    LCDUInt(average3);
	    LCDAddString("  ");
		LCDMoveCursor(LCD_ROW_2);
		LCDAddString("FR = ");
	    LCDUInt(average4);
	    LCDAddString("  ");
	    LCDMoveCursor(LCD_ROW_2 + 10);  // move to column 10 of row 0
	    LCDAddString("TR = ");
	    LCDUInt(average5);
	    LCDAddString("  ");

Is your last sensor connected to PA6? I/O lines PA6 and PA7 are connected to hardware on the X2 by default: PA6 is connected to the battery voltage (after it’s been decreased by a voltage divider) and PA7 is connected to the user trimpot. These connections will interfere with any analog sensors on those lines and probably are responsible for your problem.

If you want to use PA6 or PA7 as inputs for your sensors, you should disconnect those lines from their associated X2 hardware by breaking their solder jumpers on the bottom side of the board. The solder jumper for PA6 is labeled ADC6=BATLEV and the solder jumper for PA7 is labeled ADC7=TRIMPOT. They are located on the lower left part of the board, just to the right of the PD4 - PD7 I/O bank. Just touch a hot soldering iron to the solder jumper and the solder bridge should break, freeing up the analog input for your sensor.

The following picture has all of the X2’s solder-jumper locations circled:

- Ben

Besides enabling one to use A6 and/or A7, what does breaking these jumpers do?
Does it render the TrimPot useless then or the BATLEV?

Hello.

The BATLEV and TRIMPOT are analog outputs that are connected to ADC6 and ADC7 by those jumpers. Breaking the connections will disconnect their outputs to those pins. You do not need to do any additional things to the board to use A6 (ADC6) and A7 (ADC7). If you do desolder the connections on the jumpers, you can resolder them to reconnect BATLEV and TRIMPOT to those pins.

- Jeremy