X2 using LCD routines

Im trying to see will the program below will it work. I want the robot to traverse staight until the left sensor voltage jumps high, then turn left and go straight from there

int main( void )
{
SPIInit(); // initialize SPI hardware module for communication with auxiliary mega168
analog_init(); //call to analog_init() will power up the ADC
LCDInit(); //must be called prior to all LCD commands
servo_init();
lcd_clear();
lcd_show();
while(1)
{

float sensor1 = analog10(0); //Value of front sensor in PA0
float sensor2 = analog10(1); //Value of left side sensor in PA1

unsigned char left;
string sensors_space=sensor1+sensor2;//makes this sensor value 1 'space' sensor value 2

top = servo_define(_SFR_IO_ADDR(DDRD), _SFR_IO_ADDR(PORTD), 0); // make PD0 (servo1) an output

//DDRA |= (1 << 0); // make PA0 (servo1) an output
lcd_string(sensors_space);//stores the sensor values on the lcd screen

servo_active(top); // Turn on top servo
servo_set(top, 2000); // right max top servo

setMotor1(255);
setMotor2(255);
if(sensor2<1)//senorleft voltage is still reading millivolts
{
setMotor1(255);
setMotor2(255);
}
else
{
//this makes the robot turn left
setMotor1(-255);
setMotor2(255);
delay_ms(100);
}
}
// set motor 1 forward at full speed (from SPI.h)
return 0;
}

Hello.

I moved this topic to the Orangutan forum since it is specific to the Orangutan X2 rather than a general sensor discussion.

As far as your question about whether your code will work, all I can say is try it out and see. At the very least get it to compile first before asking others to look it over. Is there a reason you haven’t just tested it?

Also, I think you’re mixing the LCD routines we supply with those from Orangutan-lib (e.g. you call LCDInit(), which is from us, but then use lcd_string(), which is from Orangutan-lib). You should be able to use either one, but you shouldn’t mix the two.

A few other things I notice on first glance:

  1. Your line “string sensors_space=sensor1+sensor2;” will not work. There are LCD functions for displaying integers; you should use those.

  2. You should make decisions based on the average of a few consecutive sensor readings. This will help prevent noisy readings from causing your robot to act in an erratic manner.

- Ben

I already compiled it and got no errors. I just wanted to make sure everything I was doing was compatible for the X2.

The reason I put LCDInit(),from my understading I had to put LCDInit() prior to any LCD commands used. I hooked up the LCD to my orangutan X2 and not too sure how to display floats on it.

So are you saying that my code she look like this:

int main( void ) 
{
	SPIInit(); // initialize SPI hardware module for communication with auxiliary mega168
   	LCDInit(); 	//must be called prior to all LCD commands
	servo_init();
	
while(1)
{
int sum = 0;
unsigned char average;
ADCSRA = 0x87;
ADMUX = 0x21;//Value of front sensor in PA0
//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 sensor1 = average;	//Value of front sensor in PA0
//second sensor conversion
sum=0;
ADCSRA = 0x87;
ADMUX = 0x22; //Value of left side sensor in PA1
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;	//Value of left side sensor in PA1
             unsigned char top;
	//string sensors_space=sensor1+sensor2;//makes this value 1 'space' value 2
	top = servo_define(_SFR_IO_ADDR(DDRD), _SFR_IO_ADDR(PORTD), 0); // make PD0 (servo1) an output
   	//DDRA |= (1 << 0);  // make PA0 (servo1) an output
	LCDInt(sensor1);//display the sensor value on the lcd screen

   	servo_active(top); // Turn on top servo
	servo_set(top, 2000); // right max left servo

   	setMotor1(255);
   	setMotor2(255);
  	if(sensor2<1)//senorleft voltage is still reading millivolts
   	{
   		setMotor1(255);
   		setMotor2(255);
   	}
	else
            {
	//this makes the robot turn left
	   	setMotor1(-255);
	   	setMotor2(255);
		delay_ms(100); 
	}
}
   	// set motor 1 forward at full speed (from SPI.h)
   	return 0;
}

Is that how I should do the conversion and my lcd display, or am I way off!!!

Then it would be helpful if you would post your entire program (e.g. don’t leave out the #includes) rather than just main(), because your code as you’re posting it will not compile.

You do have to use LCDInit() if you want to use the LCD control functions we provide. If you use Orangutan-lib, you need to call lcd_init(), I believe. Neither LCD library supports displaying floating point numbers; this is a routine you would need to write yourself. In general, I don’t recommend you use floats in your programs, though. The routines used to manipulate floats take up a lot of program space and require a lot of clock cycles. You can almost always get by with chars and ints.

Here are a few changes I would make to your code:

  1. Set ADCSRA outside the while(1) loop and remove the lines that set it inside the loop. You only need to set this register once as its value never needs to change once you initialize it. It doesn’t hurt to set it repeatedly inside the loop, but it makes your code unnecessarily complex.

  2. If you want to perform a conversion on pin PA0, you need to set ADMUX = 0x20, not 0x21. Similarly, if you want to perform a conversion on pin PA1, you need to set ADMUX = 0x21, not 0x22.

  3. Make sensor1 and sensor2 unsigned chars, not floats. You do not need floating point precision for these values, especially since you’re just setting them equal to an unsigned char.

  4. If you want to display both sensor values on the LCD without flicker, you can use something like:

LCDHome();  // move to column 0 of row 0
LCDAddString("s1 = ");
LCDUInt(sensor1);
LCDAddString("  ");
LCDMoveCursor(LCD_ROW_0 + 10);  // move to column 10 of row 0
LCDAddString("s2 = ");
LCDUInt(sensor2);
LCDAddString("  ");

I think your averaging will work fine, but you should be able to easily test it using your LCD. As far as your motor- and servo-control code, you’ll just need to try it and see how it works.

- Ben

Ok thanks for clearing that up for me. I meant to have the Mux at x21 for PA1, I guess I let that mistake slide right by be. Thanks though. I’m gone try it and see how it works. Entire code below to see if any errors:

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


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

ADMUX = 0x21;//Value of front sensor in PA1
//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 sensor1 = average;	//Value of front sensor in PA0
//second sensor conversion
sum=0;

ADMUX = 0x22; //Value of left side sensor in PA2
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;	
	//Value of left side sensor in PA1
    
    unsigned char top;
	
top = servo_define(_SFR_IO_ADDR(DDRD), _SFR_IO_ADDR(PORTD), 0); // make PD0 (servo1) an output

   	//DDRA |= (1 << 0);  // make PA0 (servo1) an output
	LCDHome();  // move to column 0 of row 0
             LCDAddString("S1 = ");
             LCDUInt(sensor1);
             LCDAddString("  ");
             LCDMoveCursor(LCD_ROW_0 + 10);  // move to column 10 of row 0
             LCDAddString("S2 = ");
             LCDUInt(sensor2);
             LCDAddString("  ");

   	servo_active(top); // Turn on top servo
	servo_set(top, 2000); // right max left servo

   	setMotor1(255);
   	setMotor2(255);
  	if(sensor2<1)//senorleft voltage is still reading millivolts
   	{
   		setMotor1(255);
   		setMotor2(255);
   	}
	else
    {
		//this makes the robot turn left
	   	setMotor1(-255);
	   	setMotor2(255);
		delay_ms(100); 
	}
}
   	// set motor 1 forward at full speed (from SPI.h)
   	return 0;
}
  1. The question is about the LCD functions you requested to use. Seems like it still displays just the integer and not the numbers after the decimal and that the numbers I want to see for clarification.

Each ADC result in your code is a byte whose value ranges from 0 to 255 (0 corresponds to 0 V and 255 corresponds to 5 V). You average these results to lessen the impact of noise, not to obtain decimal precision. You should be storing your sensor value averages as unsigned chars, not floats. If you need extra precision, you can run your ADC in 10-bit mode rather than 8-bit mode. This would give you results that range from 0 to 1023 (here 1023 corresponds to 5 V), and you would use unsigned ints instead of unsigned chars or floats.

To learn more about 10-bit ADC mode, you can consult the datasheet. If you have questions about it, I can try to answer them.

- Ben

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


int main() 
{
   SPIInit(); // initialize SPI hardware module for communication with auxiliary mega168
      servo_init();
	  //declaring variables
  // ADCSRA = 0x87;
   int count=0;
while(1)
{
	//sensor values being calculated in this whole section
	//////////////////////////////////////////
	/////////////////////////////////////////////
	//////////////////////////////////////////////
	///////////////////////////////////////////////
	int sum = 0;
	
	unsigned char average;

	ADMUX = 0x22;//Value of bottom left sensor in PA2
	//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 sensor1 = average;   //Value of front sensor in PA2
	/////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////
	//second sensor conversion
	sum=0;

	ADMUX = 0x23; //Value of front left sensor in PA3
	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;   
   	LCDHome();  // move to column 0 of row 0
    LCDAddString("S1 = ");
    LCDUInt(sensor1);
    LCDAddString("  ");
    LCDMoveCursor(LCD_ROW_0 + 10);  // move to column 10 of row 0
    LCDAddString("S2 = ");
    LCDUInt(sensor2);
    LCDAddString("  ");
 setMotor1(130);
    setMotor2(130);
		
	 
	//	servo_active(bottom); // Turn on bottom servo
   	//	servo_set(top, 2000); // right max bottom servo
		
   if(sensor1<1)// bottom left sensor voltage is still reading millivolts
    {
         //setMotor1(100);
         //setMotor2(100);
		 //delay_ms(100);
    }
   	else
    {
      //this makes the robot turn left
         setMotor1(0);
         setMotor2(0);
		do
		 {
		 	setMotor1(-130);
         	                          setMotor2(130);

		}while(sensor2<1);

running this code, all my robot does is sit there, making noise. I believe its setting up the LCD screen, but it still just sits there doing nothing.

Try simplifying your program. Just get the LCD to print a simple “hello world.” After that, maybe have it display a single sensor value. After that maybe add in motors. Get the subsystems (LCD, sensors, motors) working independently so you can work out the kinks in each more easily, and then tie them all together.

- Ben

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

int main() 
{
   SPIInit(); // initialize SPI hardware module for communication with auxiliary mega168
  // servo_init();  
  	
	unsigned int sensor1=1;
  	LCDHome();  // move to column 0 of row 0
    LCDString("S1 = ");
    LCDUInt(sensor1);
	LCDAddString("  ");
	  //declaring variables
  	

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

Tried this program above and the LCD just displays nothing

You need to call LCDInit() before using the LCD routines.

Thanks that took care of it. I just thought I only use that function if I wasing the push buttons, but thanks.

	int sum=0;
	
		unsigned int average, average1;
	 	ADMUX = 0x23;//Value of bottom left sensor in PA3
		//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;
		delay_ms(10);
		int sum2=0;
	
		ADMUX = 0x26;//Value of bottom right sensor in PA7
		//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;

	   	LCDHome();  // move to column 0 of row 0
	    LCDAddString("S1 = ");
	    LCDUInt(average);
	    LCDAddString("  ");
	    LCDMoveCursor(LCD_ROW_0 + 10);  // move to column 10 of row 0
	    LCDAddString("S2 = ");
	    LCDUInt(average1);
	    LCDAddString("  ");

I’m using this code above to display my senssor values as they change. My first sensor is changing accurately. But my second sensor just stays around 100, no matter the actual value its suppose to report. Can you help me?

After speaking to you on the phone, it seems the problem is with your second sensor. In general, a problem like this is most easily debugged by swapping the sensors and observing the result. If the same sensor fails no matter where you connect it, the problem is probably with the sensor. If the failure corresponds to a specific X2 I/O pin and is independent of the sensor, then the problem is probably with your code (or with the X2’s I/O pin).

- Ben

It was the sensor. We will just have to ordr a new one.

Thanks