Cannot get the DEC data to ASCII

Hello everybody,

I am struggeling quite a while now. I would like to read out some canbus value’s.
Which is going quite good in HEX.

But the usefull data i need should be in ASCII.

I will get for example the value 33E4 but i need 13.284 or 13284 would be also good enough

Ill ope you guys could help me out. I tried quit a lot but i cannot get it working properly.

#include <SPI.h>
#include <mcp2515.h>


struct can_frame canMsg;
MCP2515 mcp2515(10);



void setup() {
  Serial.begin(115200);
  
  mcp2515.reset();
  mcp2515.setBitrate(CAN_250KBPS);
  mcp2515.setNormalMode();
  
  Serial.println("------- CAN Read ----------");
  Serial.println("ID  DLC   DATA");
}

void loop() {
  
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    Serial.print(canMsg.can_id,HEX); // print ID
    Serial.print(" "); 
    Serial.print(canMsg.can_dlc, HEX); // print DLC
    Serial.print(" ");
    
    for (int i = 0; i<canMsg.can_dlc; i++)  {  // print the data
      Serial.print(canMsg.data[i]);
      Serial.print(" ");
    }

      if ((canMsg.data[1] == 33)&& (canMsg.data [2] == 17)){    
       Serial.println();
      Serial.print("voltage");
      Serial.print(canMsg.data[4],HEX);
      Serial.print(canMsg.data[5],HEX);
                                            // i will get 33E4 in a converter to ascii it would be 13284
      Serial.println();}
      
     }
  }

With kind regards,
Marc

Without the HEX specifier, print() will print in decimal. Isn't that what you want? If not, how do you think that anyone could guess what this means...

// i will get 33E4 in a converter to ascii it would be 13284

"33E4" is ASCII. Do you want a decimal representation? Then don't print it in hex.

If this is the part that produces "33E4"

      Serial.print("voltage");
      Serial.print(canMsg.data[4],HEX);
      Serial.print(canMsg.data[5],HEX);

Then you have some conversion work to do before you can print it. What is your level of programming knowledge?

That code would fail anyway. print() doesn't print leading zeros, so a hex value pair like 04,0e would be printed as "4e" which is incorrect.

Try something like

      Serial.print("voltage");
      unsigned int printValue = canMsg.data[4] * 256 + canMsg.data[5];
      Serial.print(printValue);

Welcome to the forum

You need to learn about data types and data representation.

ASCII is a standard for character representation. When you use Serial.print every character is displayed using ASCII. 33E4 is 4 ASCII characters and 13284 is 5 ASCII characters.

In your Arduino data is not stored in ASCII but as bits and bytes. They can mean all kind of things. What they mean is controlled by the data types (char, int, long) and there modifiers (e.g. unsigned). But also by byte order called little-endian vs big-endian.

For your case

CAN sends bytes, so for a 16-bit integer you need two bytes.

to get an unsigned int you need to combine the two bytes. This has been discussed many times in the forum. A quick Google search will get you many examples. e.g.

Once you have the value in a 16-bit variable you can use Serial.print to display the value any way you like.

Hex, decimal, binary are just ways to represent the number. It's all the same to the processor.
I've never worked with CAM data, but this may help with how you can convert the hex string to an unsigned integer:

/*
   Demo of hex to int conversion
*/

void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.println();

  char hexValue[] = "33E4";
  int x = strtol(hexValue, NULL, 16);
  Serial.print(F("x in HEX= "));
  Serial.println(x, HEX);
  Serial.print(F("x in DECIMAL= "));
  Serial.println(x, DEC);
}

void loop() {
}

Thank you guys verry much for the help.
I will check and try everything this evening.
Let you know how it it goes.

To clarify my issue.
The reading is printed in HEX as the code shows.
My output is variable. But in this case it is 33E4.
When i put the 33E4 value in a app (ASCII CONVERTER) HEX> ASCII i will get the value 13284 (this value is the one i need :slight_smile: )

I can print the output in DEC,OCT,HEX but could not seem to find the same results as the converter app gives me.

in other words:

“forget” about hex, dex or binary - it’s just a representation for you as human. It’s all the same.

when you have a number splitted in two bytes canMsg.data[4] and canMsg.data[5], the first step is to get it into one variable

i.e.
int yourNumber = canMsg.data[4]<<8 | canMsg.data[5];

you shift the bits of data[4] to the left and add the bits of data[5]
and then it doesn’t matter, how you represent the data, it’s all the same:

Serial.println(yourNumber, DEC);
Serial.println(yourNumber, BIN);
Serial.println(yourNumber, HEX);

When you are dealing with CAN you should take some time to read about bit shifting, bit masking, and basic AND and OR operations.

Thanks all!!
It worked well for me. Now i can start cleaning up and organize the code!

#include <SPI.h>
#include <mcp2515.h>


struct can_frame canMsg;
MCP2515 mcp2515(10);



void setup() {
  Serial.begin(115200);
  
  mcp2515.reset();
  mcp2515.setBitrate(CAN_250KBPS);
  mcp2515.setNormalMode();
  
  Serial.println("------- CAN Read ----------");
  Serial.println("ID  DLC   DATA");
}

void loop() {
  
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    Serial.print(canMsg.can_id,HEX); // print ID
    Serial.print(" "); 
    Serial.print(canMsg.can_dlc, HEX); // print DLC
    Serial.print(" ");
    
    for (int i = 0; i<canMsg.can_dlc; i++)  {  // print the data
      Serial.print(canMsg.data[i],HEX);
      Serial.print(" ");
    }
    Serial.println();

      if ((canMsg.data[1] == 33)&& (canMsg.data [2] == 17)){   
      int yourNumber = canMsg.data[4]<<8 | canMsg.data[5]; 
     int Volt = yourNumber /1000;
      Serial.print("voltage");  
      Serial.println(yourNumber, DEC);
       Serial.print(Volt,DEC);
      Serial.print(".");    
      Serial.print(yourNumber%1000,DEC);

      Serial.println();
      }
      
     }
  }

, DEC

is the default. You don't need to write it...

Serial.print(Volt); // will print Volt in DEC representation

noiasca:
, DEC
is the default. You don't need to write it...

But it does make the code more readable.