Integers, characters and ascii confusion

I'm trying to manipulate a character array based on the content of two single-digit int variables, 'thisStatus' and 'deviceID'.

I can inject the variables into the char array as follows:

char msg[4] = {'M',(deviceID),(thisStatus),'#'};

However, when I then print this to the Serial Monitor, 'thisStatus' and 'deviceID' are treated as ascii codes and the relevant characters are output, instead of the desired single digit number.

I can fix this by placing this code before the line above:

thisStatus = thisStatus + 48;
deviceID = deviceID + 48;

This shifts the values in the int variables to the relevant numerical characters in the ascii table, but this feels like a very messy way to achieve something which should be quite simple - I'm obviously missing something.

How can I inject the value of these two variables into my char array so they come back out as the correct numbers?

Since they are characters because of your data definition, you need to add the ASCII offset to make it work. Post all of your code and let us see what you're trying to do.

We can't be sure without seeing the surrounding code, but it seems to me that trying to initialise the string with these values is not the best way to do it. If you're trying to generate a string containing variable values then using snprintf() would be a cleaner way to do it. For example:

char buff[16]; // make this size big enough to hold your longest string
snprintf(buff, sizeof(buff), "M%d%d#", deviceID, thisStatus);

Assuming that deviceID and thisStatus are int variables which contain the values you want to print, the format string is copied to the output buff with the first "%d" replaced by a decimal representation of deviceID and the second %d replaced by a decimal representation of thisStatus.

Thanks - the full code as it stands is below.

I’m using the VirtualWire library to poll eight slave devices (determined by deviceID) in turn, send a status (thisStatus) and listen for a response. Apart from this issue, that’s all working well.

It’s about to get more complicated with statuses changing depending on user input on each of the devices so I want to make sure this basic bit is as simple and robust as possible first.

#include <VirtualWire.h>

uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

char *controller;

int playerstatuses [] = {2,2,2,2,2,2,2,2};

int deviceID = 1;
int device;

int loopDelay = 20; //set the delay between polling the slaves

int thisStatus = 0;

void setup() {

  Serial.begin(9600);

  pinMode(13,OUTPUT);
  vw_set_ptt_pin(8);
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_set_rx_pin(7);
  vw_set_tx_pin(12);
  vw_setup(4000);// speed of data transfer Kbps

  vw_rx_start();       // Start the receiver PLL running

}



void loop(){
  
  thisStatus = playerstatuses[deviceID];
  
  // convert statuses and deviceIDs to ascii codes for same numbers
  // THERE MUST BE A BETTER WAY TO DO THIS
  
  thisStatus = thisStatus + 48;
  device = deviceID + 48;
  
  char msg[4] = {'M',(device),(thisStatus),'#'};
  
  // broadcast the data
  
  vw_send((uint8_t *)msg, 4);
  vw_wait_tx(); // Wait until the whole message is gone

  // listen for a response

  if (vw_get_message(buf, &buflen)) // Non-blocking

  {

    Serial.println("*******Hello!");

  }

    Serial.print("Device ID: ");
    Serial.println(deviceID);
    Serial.print(msg[0]);
    Serial.print(msg[1]);
    Serial.println(msg[2]);

  if (deviceID < 8) {
    deviceID ++;
  } 
  else {
    deviceID = 1;
  }

}

The string I’m sending to the slave devices is simply a letter then two single-digit numbers, e.g. “M24”.

PeterH: We can't be sure without seeing the surrounding code, but it seems to me that trying to initialise the string with these values is not the best way to do it. If you're trying to generate a string containing variable values then using snprintf() would be a cleaner way to do it. For example:

char buff[16]; // make this size big enough to hold your longest string
snprintf(buff, sizeof(buff), "M%d%d#", deviceID, thisStatus);

Assuming that deviceID and thisStatus are int variables which contain the values you want to print, the format string is copied to the output buff with the first "%d" replaced by a decimal representation of deviceID and the second %d replaced by a decimal representation of thisStatus.

This seems to do the job - thanks! I think I sort of understand why...

A quick and dirty (but very convenient) solution is to use printable character values for the playerIDs - values from 48 to 126. If you have relatively few players use the codes for upper case letters.

...R