Pages: [1]   Go Down
 Author Topic: Decimal number on a 4x20 Hitachi LCD  (Read 1195 times) 0 Members and 1 Guest are viewing this topic.
Sweden, Malmö
Offline
Full Member
Karma: 2
Posts: 200
Rooky
 « on: August 07, 2008, 01:15:24 pm » Bigger Smaller Reset

Hi,

So i need to display a decimal value on a Hitachi LCD in 4 bit mode.
Have been reading true some old posts using the search function but can not find a complete and proper code example. Or at least not one i can understand, sorry...

So i am reading a value from a analog port from 0-1023 and want convert and display that in volts with at least two decimals such as example 4,54 volts.
Well, never mind the converting part, just need to understand what is needed to print the decimal form of value.
Is it possible to do with allready existin library such as the neillzero library?

I did manage to do that with serial communication, see code example below.
Code:
int analogPin = 0;
double z;

void printDouble( double val, unsigned int precision){

Serial.print (int(val));  //prints the int part
Serial.print("."); // print the decimal point
unsigned int frac;
if(val >= 0)
frac = (val - int(val)) * precision;
else
frac = (int(val)- val ) * precision;
int frac1 = frac;
while( frac1 /= 10 )
precision /= 10;
precision /= 10;
while(  precision /= 10)
Serial.print("0");
Serial.println(frac,DEC) ;
}

void  setup(){

Serial.begin(9600);
}

void loop(){

printDouble(z,100);  // two decimal places
delay(100);
}

By the way, not my code for the decimal handling, thank you who ever it was i stole it from  .
 « Last Edit: August 07, 2008, 01:20:13 pm by HULK » Logged

Sweden, Malmö
Offline
Full Member
Karma: 2
Posts: 200
Rooky
 « Reply #1 on: August 07, 2008, 01:28:24 pm » Bigger Smaller Reset

I can see that it is possible and that it is done in the code below, but can not understand the logic in it

Code:
* ---------
* This example uses 4 less pins on the Arduino than the 8 bit example.
* It will take a reading from a 'K' Type thermocouple ice point reference chip
* One can also set a target temperature for turning a relay off, say for a heater,
* at a given setpoint temperature. This is done on digital pin 4.
*
* These are the pins used on the LCD:
*
* - DI(register select), RW, DB4..DB7, Enable (7 in total)
*
* the pinout for LCD displays is standard and there is plenty
* of documentation to be found on the internet.
*
* 2006, Dave Sopchak  glasspusher at outofoptions dot net
*
*/

int DI = 12; // register select
int RW = 11;
int DB[] = {7, 8, 9, 10};
int Enable = 6;

int temperaturePin = 2;    // select the input pin for the temperature
int ledPin = 13;           // pin for the LED

void tickleEnable()
{
// send a pulse to enable
digitalWrite(Enable,HIGH);
delayMicroseconds(1);  // pause 1 ms according to datasheet
digitalWrite(Enable,LOW);
delayMicroseconds(1);  // pause 1 ms according to datasheet
}

void cmdWriteSet()
{
digitalWrite(Enable,LOW);
delayMicroseconds(1);  // pause 1 ms according to datasheet
digitalWrite(DI,0);
digitalWrite(RW,0);
}
void LcdCommandWrite(int value)
{
int i = 0;

for (i=DB[3]; i >= DB[0]; i--) // high nybble first
{
digitalWrite(i, value & 128);
value <<= 1;
}
cmdWriteSet();
tickleEnable();

for (i=DB[3]; i >= DB[0]; i--) // low nybble next
{
digitalWrite(i, value & 128);
value <<= 1;
}
cmdWriteSet();
tickleEnable();
}

void LcdDataWrite(int value)
{
int i = 0;

digitalWrite(DI, HIGH);
digitalWrite(RW, LOW);

for (i=DB[3]; i >= DB[0]; i--) // high nybble first
{
digitalWrite(i, value & 128);
value <<= 1;
}
tickleEnable();

for (i=DB[3]; i >= DB[0]; i--) // low nybble next
{
digitalWrite(i, value & 128);
value <<= 1;
}
tickleEnable();
}

void setup (void)
{
int i;
for (i=Enable; i <= DI; i++)
pinMode(i,OUTPUT);

delay(100);
// initiatize lcd after a short pause
// needed by the LCDs controller
LcdCommandWrite(0x28);  // function set:
delay(64);             // 4-bit interface, 2 display lines, 5x7 font
// other interaces:
// 0x20 = 4 bit, 1 display line

LcdCommandWrite(0x28);  // function set:
delay(64);             // 4-bit interface, 2 display lines, 5x7 font

LcdCommandWrite(0x06);  // entry mode set:
// increment automatically, no display shift
delay(20);
LcdCommandWrite(0x0E);  // display control:
// turn display on, cursor on, no blinking
delay(20);
LcdCommandWrite(0x01);  // clear display, set cursor position to zero
delay(100);
LcdCommandWrite(0x80);  // display control:
// turn display on, cursor on, no blinking
delay(20);
}

void loop (void)
{
int i, val = 0;

for(i = 0; i < 20; ++i)
{
delay(50);
}

val /= 4.06;      // conversion value to millivolts

digitalWrite(ledPin, HIGH);  // turn the ledPin on
delay(500);                  // stop the program for some time
digitalWrite(ledPin, LOW);   // turn the ledPin off

if(val > 175 * 10)   // temperature in deg C times 10, since we're measuring to tenths of a degree
digitalWrite(4,LOW);
else
digitalWrite(4,HIGH);

LcdCommandWrite(0x02);  // set cursor position to zero
delay(10);
firstDisplay(val);
}

void firstDisplay(int value)
{
int first,second, third, fourth;

first = value / 1000;    //
second = (value - 1000 * first)/ 100;
third = (value - 1000 * first - 100 * second)/ 10;
fourth = (value - 1000 * first - 100 * second - 10 * third);

LcdDataWrite('T');
LcdDataWrite('e');
LcdDataWrite('m');
LcdDataWrite('p');
LcdDataWrite(' ');
LcdDataWrite('=');
LcdDataWrite(' ');

LcdDataWrite(value > 999 ? first + 48 :  ' ');  // begin onscreen
LcdDataWrite(value > 99 ? second + 48 : ' ');
LcdDataWrite(third + 48);
LcdDataWrite('.');
LcdDataWrite(fourth + 48);

LcdDataWrite(' ');
LcdDataWrite('C');
LcdDataWrite(' ');
LcdDataWrite(' ');
}

Have also found the command "itoa()" but can it be used with decimals?
 Logged

London
Offline
Tesla Member
Karma: 10
Posts: 6250
Have fun!
 « Reply #2 on: August 07, 2008, 01:30:04 pm » Bigger Smaller Reset

Here is my version.

I used a later version of the printDouble code, note that the second argument is a little different. No problems borrowing it, that's what I posted it for

Code:
void printInt(long n){
byte buf[10];  // prints up to 10 digits
byte i=0;
if(n==0)
lcd.print('0');
else{
if(n < 0){
lcd.print('-');
n = -n;
}
while(n>0 && i <= 10){
buf[i++] = n % 10;  // n % base
n /= 10;   // n/= base
}
for(; i >0; i--)
lcd.print((char) (buf[i-1] < 10 ? '0' + buf[i-1] : 'A' + buf[i-1] - 10));
}
}

void printDouble( double val, byte precision){
// prints val with number of decimal places determine by precision
// precision is a number from 0 to 6 indicating the desired decimial places
// example: printDouble( 3.1415, 2); // prints 3.14 (two decimal places)

printInt( (long)val);  //prints the int part
if( precision > 0) {
lcd.print('.'); // print the decimal point
unsigned long frac;
unsigned long mult = 1;
while(precision--)
mult *=10;

if(val >= 0)
frac = (val - int(val)) * mult;
else
frac = (int(val)- val ) * mult;
unsigned long frac1 = frac;
while( frac1 /= 10 )
lcd.print('0');
printInt(frac) ;
}
}
 « Last Edit: August 07, 2008, 01:38:16 pm by mem » Logged

London
Offline
Tesla Member
Karma: 10
Posts: 6250
Have fun!
 « Reply #3 on: August 07, 2008, 01:36:27 pm » Bigger Smaller Reset

Quote
I can see that it is possible and that it is done in the code below, but can not understand the logic in it

Code:

void firstDisplay(int value)   // gets a floating point of form xxx.y as xxxy
{
int first,second, third, fourth;

first = value / 1000;    //
second = (value - 1000 * first)/ 100;
third = (value - 1000 * first - 100 * second)/ 10;
fourth = (value - 1000 * first - 100 * second - 10 * third);

LcdDataWrite('T');
LcdDataWrite('e');
LcdDataWrite('m');
LcdDataWrite('p');
LcdDataWrite(' ');
LcdDataWrite('=');
LcdDataWrite(' ');

LcdDataWrite(value > 999 ? first + 48 :  ' ');  // begin onscreen
LcdDataWrite(value > 99 ? second + 48 : ' ');
LcdDataWrite(third + 48);
LcdDataWrite('.');
LcdDataWrite(fourth + 48);

LcdDataWrite(' ');
LcdDataWrite('C');
LcdDataWrite(' ');
LcdDataWrite(' ');
}
That code works by multiplying the floating point value by ten, printing all but the last digit, printing a decimal point, and then printing the last digit (which was the value in tenths before it got multiplied.

The code in my previous post is a little more flexable
 « Last Edit: August 07, 2008, 01:36:56 pm by mem » Logged

Sweden, Malmö
Offline
Full Member
Karma: 2
Posts: 200
Rooky
 « Reply #4 on: August 07, 2008, 02:24:38 pm » Bigger Smaller Reset

Mem,

I am trying to run your code but can not really get what command i should use in the void loop() area to print a value?

This value will not be constant by the way.
 Logged

London
Offline
Tesla Member
Karma: 10
Posts: 6250
Have fun!
 « Reply #5 on: August 07, 2008, 02:32:46 pm » Bigger Smaller Reset

try:

void loop(){

float z = analogRead(analogPin) * 0.00491;
printDouble(z,4);  // four decimal places
delay(100);
}
 « Last Edit: August 07, 2008, 02:33:28 pm by mem » Logged

Sweden, Malmö
Offline
Full Member
Karma: 2
Posts: 200
Rooky
 « Reply #6 on: August 09, 2008, 11:14:40 am » Bigger Smaller Reset

Your code works fine, but i am finding it hard to tun it with the If comando.
Listed code below will allways print the c value when executing the if comando. It will never see p as greater then c.
Something i am missing ?

Code:
void loop() {

float c = analogRead(analogPin0) * 0.00491;
lcd.cursorTo(1,6);
printDouble(c,2);

if (c > p){
lcd.cursorTo(1,16);
printDouble(c,2);
float p = c;
}

 « Last Edit: August 09, 2008, 11:15:52 am by HULK » Logged

London
Offline
Tesla Member
Karma: 10
Posts: 6250
Have fun!
 « Reply #7 on: August 09, 2008, 01:07:38 pm » Bigger Smaller Reset

You need to move the  float p = c outside the if statement

either outside the loop function (its then a global variable) or if declared just after the start of the loop function, make it static:

void loop() {
static float p;

(existing code here...)

p = c;
 Logged

Sweden, Malmö
Offline
Full Member
Karma: 2
Posts: 200
Rooky
 « Reply #8 on: August 09, 2008, 05:37:51 pm » Bigger Smaller Reset

Yes, finally i sorted that out thanks to your help Mem.
But i had to do it with p=c inside the statement, otherwise it would after two seconds again not see p as greater then c. So my code ended up like this and works great now.

Code:
void loop() {

static float p;

float c = analogRead(analogPin0) * 0.00491;
lcd.cursorTo(1,6);
printDouble(c,2);

if (c > p){
lcd.cursorTo(1,16);
printDouble(c,2);
p= c;
}

 Logged

London
Offline
Tesla Member
Karma: 10
Posts: 6250
Have fun!
 « Reply #9 on: August 09, 2008, 05:45:23 pm » Bigger Smaller Reset

The code you posted is what I was suggesting, Good to hear you have it working now.
 Logged

Denmark
Offline
Newbie
Karma: 0
Posts: 6
Arduino rocks
 « Reply #10 on: August 30, 2008, 01:58:59 am » Bigger Smaller Reset

Hey HULK..

Tack for linket til denne side, men jeg fatter intet af hvor den kode skal ind for at få mit til at virke, som jeg skrev i den anden tråd har jeg ingen programmeringserfaring !?!

Hvad bruger du denne kode til, jeg skal bruge den til en akvariecomputer..
 Logged

Sweden, Malmö
Offline
Full Member
Karma: 2
Posts: 200
Rooky
 « Reply #11 on: September 02, 2008, 07:34:10 am » Bigger Smaller Reset

Solow,

Let us do this in English so more people will get a way of reading and also correcting there code if needed.
Remember that this code was created by Mem and i only adapted it to my code so that i could print the turbo presure decimal number on a LCD.

So try to enter this code in the setup area or just before so the doublePrint function will work, this will print a number in a decimal form.

Code:
void printInt(long n){
byte buf[10];  // prints up to 10 digits
byte i=0;
if(n==0)
lcd.print('0');
else{
if(n < 0){
lcd.print('-');
n = -n;
}
while(n>0 && i <= 10){
buf[i++] = n % 10;  // n % base
n /= 10;   // n/= base
}
for(; i >0; i--)
lcd.print((char) (buf[i-1] < 10 ? '0' + buf[i-1] : 'A' + buf[i-1] - 10));
}
}

void printDouble( double val, byte precision){
// prints val with number of decimal places determine by precision
// precision is a number from 0 to 6 indicating the desired decimial places
// example: printDouble( 3.1415, 2); // prints 3.14 (two decimal places)

printInt( (long)val);  //prints the int part
if( precision > 0) {
lcd.print('.'); // print the decimal point
unsigned long frac;
unsigned long mult = 1;
while(precision--)
mult *=10;

if(val >= 0)
frac = (val - int(val)) * mult;
else
frac = (int(val)- val ) * mult;
unsigned long frac1 = frac;
while( frac1 /= 10 )
lcd.print('0');
printInt(frac) ;
}
}

Then use printDouble command in the loop area.

Code:

float c = analogRead(analogPin0) ; //reading the value from a analog pin