Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi All,
This is being used as how do I do this thinking exercise.
I have a union that returns a value from a Balance sensor. Works fine in the serial monitor but I am trying to display it on LCD, some poking around has shown that the function to diplay
C++
lcd.print()
will only print a single character to the screen.

What I have tried:

Converting the union's output to string, issue is string doesn't exist on this system,
C++
char[]
does exist, so can I do
C++
char readOut[8];  
for(int a =0; a<=7; a++) 
  gyro.output.z = readOut[a];

The issue is how to split the array to individual values that can then be uploaded to the char[]??

You get the idea of where I am trying to go here...
I am trying to use a balance sensor to accurately report if a 'press' is level (it isn't the floor slopes) so muggins was given the task of proving it... the balance sensor returns (accel_t_gyro.value.z_gyro) which is a union made from the following:
C
typedef union accel_t_gyro_union
{
struct {
uint8_t x_accel_h;
uint8_t x_accel_l;
uint8_t y_accel_h;
uint8_t y_accel_l;
uint8_t z_accel_h;
uint8_t z_accel_l;
uint8_t t_h;
uint8_t t_l;
uint8_t x_gyro_h;
uint8_t x_gyro_l;
uint8_t y_gyro_h;
uint8_t y_gyro_l;
uint8_t z_gyro_h;
uint8_t z_gyro_l;
} reg;

struct {
int16_t x_accel;
int16_t y_accel;
int16_t z_accel;
int16_t temperature;
int16_t x_gyro;
int16_t y_gyro;
int16_t z_gyro;
} value;
};

so it gives a four digit number 4988 for example. Fine. The LCD I am using will only show one character at a time, if for instance you send '4988' you get a '4' so I was thinking if I convert the int to a char[] array I can use a for() to count the positions and output from there
C
for(int a = 0; a <= 7; a++) {
  // char[a] to int[a] type thing
}
lcd.print(a);
Posted
Updated 19-Jan-24 2:38am
v2
Comments
Richard MacCutchan 19-Jan-24 5:08am    
That last sentence does not make sense, as you refer to two different arrays. And if that is so then a simple loop will move them from one to the other. But maybe that is not what you are asking. What exactly is gyro.output.z?
glennPattonWork3 19-Jan-24 6:19am    
Sorry insufficient caffine :java: it should be "accel_t_gyro.value.y_gyro" I am trying to upload to a char array!
CPallini 19-Jan-24 6:21am    
Could you please provide the declaration of the data? I mean: What is the type of y_giro ?
CPallini 19-Jan-24 6:19am    
You are right: It is not well explained :-D
Could you please detail your scenario?
glennPattonWork3 19-Jan-24 7:01am    
OK you asked for it, I am trying to use a balance sensor to accurately report if a 'press' is level (it isn't the floor slopes) so muggins was given the task of proving it...the balance sensor returns
(accel_t_gyro.value.z_gyro) which is a union made from typedef union accel_t_gyro_union
{
struct
{
uint8_t x_accel_h;
uint8_t x_accel_l;
uint8_t y_accel_h;
uint8_t y_accel_l;
uint8_t z_accel_h;
uint8_t z_accel_l;
uint8_t t_h;
uint8_t t_l;
uint8_t x_gyro_h;
uint8_t x_gyro_l;
uint8_t y_gyro_h;
uint8_t y_gyro_l;
uint8_t z_gyro_h;
uint8_t z_gyro_l;
} reg;
struct
{
int16_t x_accel;
int16_t y_accel;
int16_t z_accel;
int16_t temperature;
int16_t x_gyro;
int16_t y_gyro;
int16_t z_gyro;
} value;
};

so it gives a four digit number 4988 for example. Fine. The LCD I am using will only show one character at a time, if for instance you send '4988' you get a '4' so I was thinking if I convert the int to a char[] array I can use a for() to count the positions and output from there
for(int a = 0; a <= 7; a++)
{
char[a] to int[a] type thing
}
lcd.print(a);

you get the idea of where I am trying to go...

In C, a char[] is effectively a string: add a null value '\0' on the end and it's a string for all practical purposes - these are called "null terminated strings"

To output to the string, you'd have to assign to readOut[a] rather than read from it, and split your value into characters - which isn't difficult but will depend on what the input is actually stored in.

Google for "C convert integer to string" and "C convert integer to hex string" for some ideas.
 
Share this answer
 
Comments
glennPattonWork3 19-Jan-24 6:15am    
Thank You!
OriginalGriff 19-Jan-24 7:23am    
You're welcome! Didn't realize it was you - I don't look at usernames much to avoid unconscious bias.
glennPattonWork3 19-Jan-24 7:59am    
Don't worry, this is for a microcontroller I was using it more as a rubber duck than anything else...
glennPattonWork3 19-Jan-24 8:15am    
Hmmm, itoa(), integer to ASCII???
OriginalGriff 19-Jan-24 8:27am    
Yep. Silly name, comes from Linux, I think.
According to the data types presented, the sensor stores the result as a binary number in a 16-bit integer. The first step would be to find out what the maximum and minimum value for z_gyro is. If it turns out to be 4-digit values with a sign, at least 6 char would be required for the conversion into a character string. If the buffer readOut is declared with 8 bytes, there is no harm in using the string length for the output.
I suggest converting the integer value into a string first. If you can use the C command sprintf(), this is easy:
C
sprintf(readOut, "%d", sensor.value.z_gyro);

Then use a for-loop to pass all characters individually to the end of the string to the print() function.
C
for (int i = 0; i < strlen(readOut); i++)
    lcd.print(readOut[i]);

If the sprintf() function is not available, itoa() would still be possible or you could program the conversion yourself in a loop.

With the additional information "sprintf, infact all f functions (print, scan) do not exist!" it would be possible to write a simple generic function yourself. It could look like this:
C
void intToCString(int num, char* str) {
    if (num < 0) {
        *str++ = '-';
        num = -num;
    }

    int divisor = 1;
    while (num / divisor > 9) {
        divisor *= 10;
    }

    while (divisor > 0) {
        *str++ = '0' + (num / divisor);
        num %= divisor;
        divisor /= 10;
    }

    *str = '\0';
}
 
Share this answer
 
v3
If you don't have itoa, you could use sprintf(), but that's quite heavy for such a light task. The following should work for you
C
int magnitude(int x)
{
    int i;
    x = abs(x);
    for(i = 0; x > 0; x /= 10, ++i);
    return i;
}

char *i2cstr(int i, char *buff) 
{
    int n = magnitude(i);

    /*  The following is only needed if i may be negative */ 
    int last = 0;
    if(i < 0) {
        i *= -1;
        buff[0] = '-';
        n += 1;
        last = 1;
    }
    /* end of dealing with negative numbers */
    
    buff[n] = 0;
    for(--n; n >= last; --n ) {
        buff[n] = i%10 + '0';
        i/= 10;
    }
    return buff;
}
Caveat: parameter buff for i2cstr() must be suitably sized. For uint16_t that's 6 chars, including terminating nul.
 
Share this answer
 
Comments
glennPattonWork3 19-Jan-24 13:09pm    
Thanks, I will give that a go later, you are right sprintf, infact all f functions (print, scan) do not exist!
merano99 19-Jan-24 14:45pm    
With a 16 - bit integer as used in the union (int16_t), the worst - case estimate would be a five - digit negative number such as - 32768. Including the sign, the resulting string requires a minimum of 7 characters.
If just need to output the value, you don't need to convert to a string first.
C
void putaschar(int16_t n)
{
    if( n == 0 ) {
        /* special case for n == 0 */
        putchar('0');
    } else {
        if(n < 0) {
            /* oputput sign, and make n +ve */
            putchar('-');
            n *= -1;
        }

        /* determine largest power of 10 smaller than n */
        int16_t divisor = 10000;  /* maximum power of 10 that will fit in int16 */
 
        while( n / divisor == 0) {
            divisor /= 10;
        }

        /* send chars to the output device */
        do {
            putchar(n/divisor + '0');
            n %= divisor;
            divisor /= 10;
        } while(divisor > 0);
    }
}
in the above, assume that putchar() stands in for whatever magic you need to do to send a char to the display.
 
Share this answer
 
Comments
merano99 19-Jan-24 14:48pm    
The restriction with divisor = 10000 could be avoided. See my suggestion in Solution 2.
Hi All,

Thanks for that, I have managed to get a solution I think using itoa(). Will try later on this afternoon
C++
Serial.println(a);
Serial.println(aValue);

Serial.println("--------");
itoa(a,aValue,10);    //itoa() itoa(a,aValue,10) a integer value wanted as char[], aValue char[] to have value stuffed in, 10 base for the number!!
Serial.print(" value now: ");
Serial.println(aValue);
Serial.println("--------");
for(int j = 0; j <= 4; j++)
  Serial.println(aValue[j]);
This should give what I want. Oh for a copy of K&R!
Glenn
 
Share this answer
 
Comments
Richard MacCutchan 22-Jan-24 11:11am    
glennPattonWork3 22-Jan-24 12:37pm    
I have the white book, just not with me

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900