(classic) ADC result to LCD issue

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

Hi all,

I want to display the ADC result to an LCD.
LCD library works well so far for static display.

I use Atmel Studio 7 and External Tools option to program an arduino (atmega328p).

I might problem also with the delay but let put it aside for now.

 

below is the code.

the expected result would be in this format : x.xx

I change the variable type to float or long, but still I cannot get the wanted result.

The result I got this far are

 

//ADCHv = xxxxxx; sometimes -xxxxx

or

//ADCHv = 0-5;

 

 

Could you show me where I made mistake here?

 

int main(void)
{
   lcd_init();
   //uint32_t ADCHv; //ADCHv = 0-5;
   float ADCHv; //ADCHv = xxxxxx; sometimes -xxxxx
   //long ADCHv; //ADCHv = 0-5;
   static const float ADC_REF = 5.00;
   static const int ADC_MAX = 255;
   //static const float ADC_MAX = 255.00; //same issue

   while (1)
   {
      ADC_run();
//       _delay_ms(40);
      char ADCHs[20];
      ADCHv = ADCH*ADC_REF/ADC_MAX;
      sprintf(ADCHs,"ADCH value=%d", ADCHv); 

      _delay_ms(2);
      lcd_xy( 0, 0 );
      lcd_puts( ADCHs );

   }
}

 

This topic has a solution.
Last Edited: Thu. Sep 28, 2017 - 05:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avocado26 wrote:
I want to display the ADC result to an LCD.

Before combining those 2 things, have you got them working separately?

 

atmega328p

has on-chip debug - use it!

 

I might problem also with the delay but let put it aside for now.

Correct timing can be important for proper LCD driving

 

below is the code.

How to properly post code: http://www.avrfreaks.net/comment...

 

I cannot get the wanted result.

So what result are you getting?

 

What have you done to track down the problem?

 

 

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

You own an Arduino. It has libraries for LCD and functions for reading the ADC.
Write and debug an Arduino sketch that does what you want.
.
Post your working sketch. Then post your attempt at the equivalent C program.
.
Ask specific questions about any line of your sketch and how to do it in C.
We will be happy to help.
.
David.

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

Read documentation for the sprintf(,) routine to discover what the % format-codes do.
(hint, %d formats an integer)

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

awneil wrote:
Before combining those 2 things, have you got them working separately? 

 

Yes, the LCD library works well on displaying static characters.

 

awneil wrote:
has on-chip debug - use it! 

did you mean hardware debug? if yes, I do not have the ICE debugger/programmer.
if it is about software debug, I still dont know how to do it since I do not know how to simulate a real voltage.
I know we can put certain value in the ADC register window by putting hex number or toggling the bit, but still I do not know to use it as a debug tool.

I will google it now anyway.

 

awneil wrote:
Correct timing can be important for proper LCD driving

Yes it is important.

 

awneil wrote:
How to properly post code: http://www.avrfreaks.net/comment...

Sorry and thank you.

 

I cannot get the wanted result.

awneil wrote:
So what result are you getting?

so far the result is like this, depend on the variable type I use.

//ADCHv = xxxxxx (like 041529); sometimes -xxxxx (like -46743), float

or

//ADCHv = 0-5; uint32_t or long

 

awneil wrote:
What have you done to track down the problem?

I tried to look for the same problem in this forum and other forum, so far they were casting problem.
After applying the correct variable type, they got the result.

I applied that to my code, still I do not get what I expected.
I also tried to change the division by 5 into division by 5.00, still I have the problem.

 

 

 

Last Edited: Thu. Sep 28, 2017 - 07:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was making a serious suggestion. Develop and debug on the Arduino. It should only be a few lines of code.
You will understand the logical steps involved in a real program.
.
Translate each step into C.
It is far easier to explain how to do this when you refer to a specific statement in your Arduino sketch.
.
David.

Last Edited: Thu. Sep 28, 2017 - 07:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avocado26 wrote:
, the LCD library works well on displaying static characters.

And have you tried it with floats ... ?

 

 

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

As well as the defects that have been noted, you’ll have the problem on characters remaining displayed.
Eg:
Display 12345
Display 45, lcd shows 45345
Why? Because you didn’t clear the previous chars.
You can use the pad features of printf/sprintf to ensure the value is displayed correctly.
Eg
%6.6f for float
Or %5d

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

avocado26 wrote:
did you mean hardware debug?

Yes.

 

 I do not have the ICE debugger/programmer.

So get one! (or use a board with one built-in)

 

As someone said here recently, trying to do software without a debugger is like trying to be a mechanic without spanners!

 

Otherwise, why not just use Arduino?

 

EDIT:

 

I found the quote:

 

js wrote:
[not having a debugger is] like a mechanic not having any spanners.

 

http://www.avrfreaks.net/comment...

 

 

EDIT2

 

Correct link

Last Edited: Thu. Sep 28, 2017 - 12:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I disagree. You can manage quite well with print statements. Especially since an Arduino has always got a Serial Terminal.
.
The most important tip is to design your program on paper.
If you have a problem, think about it. Write your ideas down on paper. That is why God invented cigarette packets.
.
Yes, if you delve into very low level hardware, an ATMEL-ICE or XMINI is useful.
But for high level logic, print statements are convenient. And you don't need to know about the inner workings of AVR special function registers.
.
You can even print most SFR values if required.
.
David.

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

david.prentice wrote:
I was making a serious suggestion. Develop and debug on the Arduino. It should only be a few lines of code. You will understand the logical steps involved in a real program. . Translate each step into C. It is far easier to explain how to do this when you refer to a specific statement in your Arduino sketch. . David.

 

I did and it works.

I just want to learn how to program it in C.

I use the code below and got x.xx as result.
 

OK, I will look my C code again.
Thanks.

 #include <LiquidCrystal.h>
// constants won't change. They're used here to
// set pin numbers:
const int analog_X_Pin = A0;
const int analog_Y_Pin = A1;

// variables will change:
int analog_X_Value = 0;
int analog_X_Voltage = 0;
int analog_Y_Value = 0;
int analog_Y_Voltage = 0;

//LiquidCrystal(rs, enable, d4, d5, d6, d7)
//LiquidCrystal(rs, rw, enable, d4, d5, d6, d7)
LiquidCrystal lcd(3,2,4,5,6,7);

void setup() {
  // initialize the LED pin as an output:
  Serial.begin(9600);

  lcd.begin(16,2);
  }

void loop() {
  int analog_X_Value = analogRead(analog_X_Pin);
  float analog_X_Voltage = analog_X_Value * (5.0/1023.0);
  int analog_Y_Value = analogRead(analog_Y_Pin);
  float analog_Y_Voltage = analog_Y_Value * (5.0/1023.0);

  Serial.print("X_Value = ");
  Serial.print(analog_X_Value);
  Serial.print("\t X_Voltage = ");
  Serial.print(analog_X_Voltage);

  Serial.print("\t Y_Value = ");
  Serial.print(analog_Y_Value);
  Serial.print("\t Y_Voltage = ");
  Serial.println(analog_Y_Voltage);

  lcd.setCursor(0,0);
  lcd.print("X: ");
  lcd.setCursor(3,0);
  lcd.print(analog_X_Value);
  lcd.print("    ");
  lcd.setCursor(7,0);
  lcd.print(" vX: ");
  lcd.print(analog_X_Voltage);
  delay(100);

  lcd.setCursor(0,1);
  lcd.print("Y: ");
  lcd.setCursor(3,1);
  lcd.print(analog_Y_Value);
  lcd.print("    ");
  lcd.setCursor(7,1);
  lcd.print(" vY: ");
  lcd.print(analog_Y_Voltage);
  delay(100);

 }

 

mikech wrote:
Read documentation for the sprintf(,) routine to discover what the % format-codes do.
(hint, %d formats an integer)
 

Now the course in C during college flashes back in my mind.
I change it to %f and my result become a question mark in LCD.
I think it is related with the LCD library that I used.
see my repy to awneil below.
Thanks.

ADCHv=?

 

awneil wrote:
And have you tried it with floats ... ?
 
I tried to isolate my code just to deal with the LCD.
And the result is a questionmark, just like my reply to mikech above.

 

int main(void)
{
   lcd_init();
   float ADCHv;
   static const float ADC_REF = 5;
   static const int ADC_MAX = 255;
   static const float CONST = 3.45;

   while (1)
   {
	  ADC_run();

	  char ADCHs[20];
	  ADCHv = CONST*ADC_REF/ADC_MAX;
	  sprintf(ADCHs,"ADCH value=%f", ADCHv); 

	  _delay_ms(2);
	  lcd_xy( 0, 0 );
	  lcd_puts( ADCHs );

   }
}

This is the LCD library that I use. I got it from this forum as well.
I will check it again.

void lcd_putchar( uint8_t d )
{
	LCD_RS = 1;
	lcd_byte( d );
	switch( ++lcd_pos )
	{
		case LCD_LINE1 + LCD_COLUMN:
		#ifdef LCD_LINE2
		d = LCD_LINE2;
		break;
		case LCD_LINE2 + LCD_COLUMN:
		#ifdef LCD_LINE3
		d = LCD_LINE3;
		break;
		case LCD_LINE3 + LCD_COLUMN:
		#ifdef LCD_LINE4
		d = LCD_LINE4;
		break;
		case LCD_LINE4 + LCD_COLUMN:
		#endif
		#endif
		#endif
		d = LCD_LINE1;
		break;

		default:
		return;
	}
	lcd_command( d );
}

void lcd_puts( void *s )                        // display string from SRAM
{
	for( uint8_t *s1 = s; *s1; s1++ )             // until zero byte
	lcd_putchar( *s1 );
}

Thanks.

Last Edited: Thu. Sep 28, 2017 - 11:09 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avocado26 wrote:
I change it to %f and my result become a question mark in LCD. I think it is related with the LCD library that I used.
You are right about the library. avr-gcc comes with three versions of lib_printf. One is minimal and basically just does plain integers and is intended for low resource environments. The one already in libc.a for AVR is "mid range" and does some other formats with the notable exception of %f which it just shows as "?" and then there is a high end one that contains full float/double printing support. To use either the minimal one or the full float one you have to do two things. One is to link with libprintf_min.a or libprintf_flt.a and the other is to say "and don't use the one in libc.a". The latter is done using -Wl,-v,vfprintf

 

If using Studio 7 it has a tick box for the -Wl thing and for the lib you right click the "libraries" section of your project and in the dialog that appears you put a tick against libprintf_flt.a

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

david.prentice wrote:
I disagree.

I disagree with your disagreement!

 

IF the chip has on-chip debug, it is folly not to use it.

Not having & using a debugger is like tying one hand behind your back.

 

Sure, prints are a valuable tool - but a proper debugger gives you so much more visibility & control.

 

Prints are always intrusive; a debugger is only intrusive when you do something intrusive with it.

 

The most important tip is to design your program on paper.

With that, I totally agree!

 

Some may prefer "virtual" paper - but the point is to have a design!

 

if you delve into very low level hardware

A debugger is not just for the low-level stuff.

 

you don't need to know about the inner workings of AVR special function registers.

You don't need that to use a debugger for high-level debugging.

 

 

EDIT

 

and, of course, part of the OP's trouble here was not using the print formats properly - so prints wouldn't have helped here!

 

 

Last Edited: Thu. Sep 28, 2017 - 12:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

All this trouble stems from trying to display the voltage as a floating point value, when it is so easy to keep the result as an integer and just display it as miliVolts.

i.e.   0.000 - 5.000 volts becomes 0 - 5000 mV

Much easier to calculate, and display, and to verify your ADC measurements and conversion to real world value.

Then, once that works, change to a floating point value if you must by just dividing by 1000.0 and display result!

 

Jim

 

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

ki0bk wrote:
Then, once that works, change to a floating point value if you must by just dividing by 1000.0 and display result!

 

Or not. instead keep as an integer "all the way", convert to string and insert decimal point into that just before (or while) displaying.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

clawson wrote:

avocado26 wrote:
I change it to %f and my result become a question mark in LCD. I think it is related with the LCD library that I used.
You are right about the library. avr-gcc comes with three versions of lib_printf. One is minimal and basically just does plain integers and is intended for low resource environments. The one already in libc.a for AVR is "mid range" and does some other formats with the notable exception of %f which it just shows as "?" and then there is a high end one that contains full float/double printing support. To use either the minimal one or the full float one you have to do two things. One is to link with libprintf_min.a or libprintf_flt.a and the other is to say "and don't use the one in libc.a". The latter is done using -Wl,-v,vfprintf

 

If using Studio 7 it has a tick box for the -Wl thing and for the lib you right click the "libraries" section of your project and in the dialog that appears you put a tick against libprintf_flt.a

 

Thank you so much. Your comment leads me to this.

This is my code now and it works.
 

int main(void)
{
   lcd_init();
   float ADCHv;
   char ADCHs[18]; 
	  
	  while(1)
	  {
		  ADC_run();
		  ADCHv = ADCH*5.00/255;
		  sprintf(ADCHs,"ADCH value=%.2fV", ADCHv);
		  
		  
		  lcd_xy( 0, 0 );
		  lcd_puts( ADCHs );
		  _delay_ms(300);
	  }
}