0

Here I am reading from a UART that is communicating with another device that is sending it bytes. If I am getting an integer value in 3 bytes, how best to convert it to something I can send using cJSON. I can get the value and iterate over it, but once I put it in a char array, i cannot even see the value any longer. Thoughts?

{
  uint8_t buf[BUF_SIZE];
  memset(buf, 0, sizeof(buf));
  // Read data from the UART
  int checkIt = uart_write_bytes(UART_NUM_2, (const char *)hex, 
  strlen(hex));
  ESP_LOGI(LOG_TAG, "this is the length of transmit: %i: ", checkIt);
   int len2 = uart_read_bytes(UART_NUM_2, buf, BUF_SIZE - 1, 1000 
  portTICK_RATE_MS);

  ParseData(buf);

}

 ParseData(char * data)
{
 //initialize char array to zeros
 char temporary[4] = {0};

 for(int i=0; i<3; i++)
 {
  //first two bytes are not needed, so skip them for now
   temporary[i] = data[i+2];
   ESP_LOGI(LOG_TAG, " temporary # %i %i ", i, temporary[i]);
 }
temporary[3] = '\0';
ESP_LOGI(LOG_TAG, " temp char contents update %s ", temporary;

}

The for loop will show me each of the values, like 1, 2, 3 (individual integers sent as individual bytes, not a string and not '1', '2', '3' - but I wan't to combine it into 123 which is why I setup the temporary array. It is printing out nothing, even if I don't add the null character to it. If I can get it to a single value (123), or even a char (string type), then I can add it to a cJSON object and send it.

wegunterjr
  • 141
  • 2
  • 9
  • The integers `1,2,3` or the characters `'1','2','3'`? – Shawn Dec 31 '18 at 07:08
  • Are you reading a character string? Or are you reading individual bytes from multibyte integer? If the latter, then you probably want to be doing something like `(firstByte << 16) | (secondByte << 8) | thirdByte` if bytes are transmitted in big-endian order or `(thirdByte << 16) | (secondByte << 8) | firstByte)` if little-endian. – jamesdlin Dec 31 '18 at 07:12
  • ah..good point. I clarified in my question. It is individual bytes. I will try the suggestion, but are you suggesting I put it in the char array I created temporary = (firstByte << 16) | (secondByte << 8) | thirdByte – wegunterjr Dec 31 '18 at 07:25
  • I tried a couple of ways: `char thisWay[4]; thisWay[0] = (data[0] << 16: thisWay[1] = (data[1] << 8; thisWay[2] = data[2];` but that didn't provide a value I could use. I also tried: `int justInt; justInt = (data[0] <<16) | (data[1] << 8) | data;` i tried it both ways to check for endianness, but it returns two values I cannot use: something like 1545 or 592128. – wegunterjr Dec 31 '18 at 08:34
  • First you need to convert ASCII codes back to values - for example, if you only have decimal digits you would subtract `'0'` or 48 from each character to get the value of that digit. Or if you already have a null terminated string you may in some cases be able to use `atoi()`. Also you probably want to be more careful that you are operating on the intended sequence of characters - you seem to be making some dubious assumptions about arrival. – Chris Stratton Dec 31 '18 at 17:55

2 Answers2

0

If the line:

ESP_LOGI(LOG_TAG, " temporary # %i %i ", i, temporary[i]);

is indicating integer values 1, 2, 3 then the data is integer data not character data. To represent the data as a string of decimal digit characters change:

temporary[i] = data[i+2];

to

temporary[i] = '0' + data[i+2];

However it seems unlikely that the data is intended to be interpreted in that manner - it is a very inefficient and wasteful method of transferring integer data. Are you sure that he data is not in fact a single 24 bit integer, where rather then the loop and array, you in fact need:

int value = data[2] << 16 | data[3] << 8 | data[4] ;

or

int value = data[4] << 16 | data[3] << 8 | data[2] ;

depending on the byte order of the data?

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • yeah, efficiency is out the window with this. It is definitely 3 different bytes that combined make the single integer 123. The following gives me the correct values. I am converting it from bytes to an integer. Strange and wish I was doing the byte shift as you suggested, but this is what I have for now. void ParseData(uint8_t * data) { uint32_t val = (data[0] * 100) + (data[1] * 10) + data[2]; ESP_LOGI(LOG_TAG, " val # %i ", val); } – wegunterjr Jan 03 '19 at 23:44
  • @wegunterjr your question was about converting to a string; in which case the first part is an acceptable answer. You did not ask about conversion to an integer. If your suggested solution works, then the code I. The question cannot produce the result you claim. – Clifford Jan 04 '19 at 08:11
  • Ah phoeey. Right. My solution morphed once I realized I could convert it to an integer. I will update my question with those details. Thanks. – wegunterjr Jan 04 '19 at 14:36
0

So, it appears that for my situation, I am converting individual bytes read from a UART to an integer

char data[3]  = {0};
data[0] = 0x01
data[1] = 0x02
data[2] = 0x03

ParseData(data);

void ParseData(uint8_t * data)
{
    uint32_t val = (data[0] * 100) + (data[1] * 10) + data[2];
    ESP_LOGI(LOG_TAG, " val # %i ", val);
} 
wegunterjr
  • 141
  • 2
  • 9