Pages: [1] 2   Go Down
Author Topic: Print commands are not consistent  (Read 1848 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have used the Serial.print() command:
Code:
int aValue=32;
Serial.print(aValue); //give you "32"
Serial.print((uint8_t)aValue); //give you a space " "

Do this make a sense?

In my opinion each normal call should reply the bytes (byte by byte for long data types).
Print with special bases should be switched on with second parameter in all cases.
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It makes complete sense as it's currently implemented.
Print of an 8 bit character prints the character. Print of a 16 or 32 bit value prints the value. It may seem odd to have the apparent behaviour change but it would be very strange to have print('a') print anything other than the character a.
« Last Edit: July 12, 2009, 11:00:37 am by mem » Logged

Cumming, GA
Offline Offline
Edison Member
*
Karma: 20
Posts: 1663
Ultimate DIY: Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, it makes sense.  the 32 is not a number anymore... it is ASCII character for "3" and then for "2". You think you sent the value of 32... but you sent ASCII code for  "51" then "50" when using the PRINT statement.

SERIAL TRANSMISSION sends ASCII codes so that's what Serial.print does.
« Last Edit: July 12, 2009, 11:04:21 am by pwillard » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26632
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
SERIAL TRANSMISSION sends ASCII codes
Nonsense; it sends binary.
ASCII only defines 128 codes, but serial transmission allows you to transmit 256 different values.
« Last Edit: July 15, 2009, 03:44:10 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The behaviour the OP has raised is not about ASCII, extended ASCII or binary. Its about the way Arduino print routines differentiate on the type of value passed to the print function.

When printing a char or byte, Arduino will send this as a single byte (it doesn't care if its ASCII or not). When printing a 16 or 32 bit integer or a float, it will send this as the string of characters that represent the value.

If the receiving side displays these as ASCII values (as does the Arduino Serial Monitor) you would see the (extended) ASCII value of a printed character (or byte), or the numerals representing the value of integers or floats.
« Last Edit: July 15, 2009, 04:13:16 am by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Serial.print(aValue,BYTE); //is confusing because BYTE=0 and this base couldn't handled with mathematical correctness

Next Problem: In actual arduino this will print for types with n x byte (int, real, float, double etc.) only the first byte!
 
My suggestion:
Serial.print(aValue);       //should always and ever send bytes
Serial.print(aValue,DEC); //should send a number as ASCII-Char
Serial.print(aValue,HEX); //should send a number as ASCII-Char
Serial.print(aValue,8);     //should send a number as ASCII-Char

DEC=10, HEX=16

Following this logic you don't need anymore the base BYTE (=0)!
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think it works well just as it is. The parameter when non zero is treated as the base used to display value, and when zero the character rather then the value is displayed.

I think most Arduino users would be surprised if the following did something other than print the digits “1234” to the serial monitor.
int  value = 1234;
Serial.print(1234);

If I understand your suggestion, your version would print whatever is the ascii value of 0xD2 – which is not what I think most Arduino users would want to see.
« Last Edit: July 15, 2009, 11:00:38 am by mem » Logged

Dallas, Texas
Offline Offline
God Member
*****
Karma: 0
Posts: 861
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I would be surprised now that I know what is supposed to happen. I'm not that fluent in c/c++ so I don't know if Arduino's behavior is logical or not.

I'll have to admit, I found it very counter-intuitive at first.
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

what would you have expected this code to do?
  int  value = 1234;
  Serial.print(1234);
Logged

Dallas, Texas
Offline Offline
God Member
*****
Karma: 0
Posts: 861
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think I would have either expected an error or have it truncated to 0xd2. To me, a serial device is byte oriented and I would expect to have to do something special to have it print a character string.

I'm not complaining, mind you. smiley
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That example was meant to be
  int  value = 1234;
  Serial.print(value);

I guess your expectation would be the same.

But would you expect  
  int  value = 1234;
  lcd.print(value);
 to truncate to 0xd2 ?

would you want it to?
« Last Edit: July 15, 2009, 11:46:28 am by mem » Logged

Dallas, Texas
Offline Offline
God Member
*****
Karma: 0
Posts: 861
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Only because I know that the LCD class derives from Print. Otherwise, I wouldn't expect it to do anything until I wrote a driver.
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
…Otherwise, I wouldn't expect it to do anything until I wrote a driver.
I think many of the design decisions taken by the Arduino team were to ensure that users did not need to know what a driver was, let alone think about writing one  smiley-wink

Those of us that do understand the plumbing should accept that we are not the primary audience for Arduino
« Last Edit: July 15, 2009, 12:26:12 pm by mem » Logged

Dallas, Texas
Offline Offline
God Member
*****
Karma: 0
Posts: 861
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Exactly!

My background is in embedded controller/processor design and while I have written nE5 lines of assembly language having any kind of high level language support has always been a luxury. The c compilers available for 8/16 bit chips usually concentrate on port and bit manipulation and if they do arithmetic at all it's normally integer only.

Consequently, Arduino is a real M-series in my opinion and for the tasks it was designed to do, I wouldn't use anything else.

The fact that some things seem a little nonintuitive to me is of no consequence, as they are quickly learned. I discovered a long time ago that it's more productive to use the tools you have than to piss and moan about the ones you wish you had. Besides, tomorrow is another day. smiley-wink
Logged

Toronto, ON
Offline Offline
Full Member
***
Karma: 10
Posts: 233
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think the OP is trying to illustrate the inconsistency of the "print" method overloading.  Specifically, the difference between "print"ing an int versus a uint8_t.

I've already experienced this problem.  Here is some more code to clarify the problem:

Code:
uint8_t mybyte;         // this is UNSIGNED
int myword;             // an int is 16bits - explicitly: int16_t (from stdint.h)

myword = 32;
mybyte = myword;

Serial.print(myword);   // prints "32" - as expected
Serial.print(mybyte);   // prints " " - not exactly intuitive

Herein lies the problem:
What do you do with a byte?  Since a byte === unsigned char, do you print it as a series of characters in a readable format representing the number (e.g. "32")?  Do you send the direct value of the byte over the serial connection?  It's unclear, because the data type is ambiguous.

A more clearly defined Print Base Class would solve this problem.

For example, for consistency, Print::print(uint8_t n) should be:
Code:
void Print::print(uint8_t n)
{
  print((long) n);
}

and for clarity, a new method should be added:
Code:
void Print::printchar(char c)
{
  this->write(c);
}

Unfortunately, this will break a LOT of current code, since people have already accepted that Serial.print((uint8_t)32) prints a space.

The OP is saying that instead of assuming that "print"ing a uint8_t means to send a direct value over the serial connection, it should be "print"ed in the same way as a long value.  Furthermore, the OP is saying that to print a byte directly, it should be explicit, e.g. print(mybyte, BYTE).  I'm not complacent with that format (if anything BYTE should be changed to DIRECT - semantically differentiating the methods).  "print" should be consistent - i.e. always printing readable characters or such.

Again, this will break a lot of code.

b
« Last Edit: July 22, 2009, 01:16:23 pm by bhagman » Logged


Pages: [1] 2   Go Up
Jump to: