Having issues while using %s - arrays

I am working on a project in which I extract data received from GPS and save it in array named rx_data_buffer:
uint8_t rx_data_buffer[84] = {0};
The result I get is as below(see rx_data_buffer) :
enter image description here
Then I extract the data from rx_data_buffer in following arrays:
uint8_t lattitude[10] = {0};
uint8_t longitude[10] = {0};
uint8_t altitude[5] ={0};
The data is extracted as follows:
for (uint8_t i =0; i < 10; i++)
{
lattitude[i] = rx_data_buffer[i+17];
}
for (uint8_t j =0; j < 10; j++)
{
longitude[j] = rx_data_buffer[j+31];
}
for (uint8_t k =0; k < 5; k++)
{
altitude[k] = rx_data_buffer[k+56];
}
The results are as follows:
enter image description here
Till here everything is working fine but when I put the latitude, longitude and altitude data in an array using %s for the purpose of saving them in SD card as follow:
snprintf(mystring, sizeof(mystring), "\n%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%s,%s,%s", readAccelerometer(X_AXIS),readAccelerometer(Y_AXIS),readAccelerometer(Z_AXIS),readGyro(X_AXIS), readGyro(Y_AXIS),readGyro(Z_AXIS),readMagnetometer(X_AXIS),readMagnetometer(Y_AXIS), readMagnetometer(Z_AXIS),heart_rate,longitude,lattitude,altitude);
I get the longitude and altitude values fine but am getting wrong latitude value in a sense that it show both the values combine as shown below:enter image description here.
What can be the issue?

In order to be used as strings, the arrays need a null terminator. Since you are initializing the arrays to zero, the simplest solution is to make them one larger than you need. eg:
uint8_t lattitude[11] = {0};
uint8_t longitude[11] = {0};
uint8_t altitude[6] ={0};
As long as you never write over the last element in the array, it will remain '\0' and you can use the string functions.

Related

float values of array are not assigned during a for loop (STM32 / arm-none-eabi-gcc)

I want to convert a bunch of uint16_t values from an ADC into floating point voltages.
For this I use a for loop to loop through the uint16_t array and write the values to a float array.
But the float array remains 0 as if no assignment is ever made.
Outside of the for loop the conversion works.
And when I step through the program with the debugger, I see reasonable float values but they do not end up being written to the array. Why?
the temporary float value is clearly 1.847:
the temporary array index is clearly 0:
so I expect the adc_voltages[0] to be 1.847 which it is not:
Code:
Global Variables:
volatile uint16_t adc_dma_buffer[SG_MK2_ADC1_CHANNELS * SG_MK2_ADC1_N_SAMPLES];
float adc_voltages[SG_MK2_ADC1_CHANNELS * SG_MK2_ADC1_N_SAMPLES];
Later in the main():
float temp = 0.0f;
uint8_t index = 0;
for(uint8_t i=0; i<8; i++){
temp = BSP_convU1(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+0]);
index = i*SG_MK2_ADC1_CHANNELS+0;
adc_voltages[index] = temp; // BSP_convU1(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+0]);
adc_voltages[i*SG_MK2_ADC1_CHANNELS+1] = BSP_convU2(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+1]);
adc_voltages[i*SG_MK2_ADC1_CHANNELS+2] = BSP_convU3(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+2]);
adc_voltages[i*SG_MK2_ADC1_CHANNELS+3] = BSP_internalTemperature(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+3]);
}
Where the functions return float:
float BSP_convU1(uint32_t adc_val){
float adc_vsense = SG_MK2_ADC_VREF/4096.0f * (float)adc_val;
return adc_vsense * BSP_CONV_U1_FACTOR + BSP_CAL_U1_OFFSET;
}
Edit:
Thanks for all the comments and good practice hints that I will use from now on. Especially with the usage of 2D arrays.
I was just able to resolve the issue.
I am still not sure why it happened.
"working outside of the loop" was not correct either, it only worked, when BSP_conv_I_MPPT() was evaluated inside the printf statement directly.
Anyhow, the following code with 2D arrays now works.
if(flag_SDADC_cplt){
flag_SDADC_cplt=0;
for(int i=0; i<SG_MK2_SDADC1_N_SAMPLES; i++){
adc_currents[i][0] = BSP_conv_I_Boost (sdadc_dma_buffer[i][0]);
adc_currents[i][1] = BSP_conv_I_MPPT (sdadc_dma_buffer[i][1]);
adc_currents[i][2] = BSP_conv_I_Solar (sdadc_dma_buffer[i][2]);
// order: adc[sample][channel]
}
printf("DCDC\tMPPT\tPV\n");
printf("%.3fA\t%.3fA\t%.3fA\n", adc_currents[0][0], adc_currents[1][0], adc_currents[2][0]); // order[channel][sample]
}
if(flag_ADC_cplt){
flag_ADC_cplt = 0;
for(int i=0; i<SG_MK2_ADC1_N_SAMPLES; i++){
adc_voltages[i][0] = BSP_convU1(adc_dma_buffer[i][0]);
adc_voltages[i][1] = BSP_convU2(adc_dma_buffer[i][1]);
adc_voltages[i][2] = BSP_convU3(adc_dma_buffer[i][2]);
adc_voltages[i][3] = BSP_internalTemperature(adc_dma_buffer[i][3]);
}
printf("\nPV\tCAN\tBat\tTemp\n");
printf("%.2fV\t%.2fV\t%.2fV\t%.1fC\n", adc_voltages[0][0], adc_voltages[0][1], adc_voltages[0][2], adc_voltages[0][3]);
}

How to change value in array and convert to RGB

I am making a project where RFID tags on 6 RFID readers will create a 6-digit HEX-code which will be converted and output through RGB.
I am converting HEX values to RGB values and print the values in serial, which works fine. E.g when I write #FFFFFF, Serial prints its respective RGB values - 255, 255, 255.
However, I want to be able to replace one of the letters in the HEX code at a time, which should change its RGB output in serial. In this example, I am attempting to replace the last letter of #FFFFFF to 3 - #FFFFF3. Serial still reads the first two values correctly, but does not convert the last value correctly.
I have read that it is better to create a new array with the new value -
instead of replacing a value and changing the array but do not really know how. Here's what I have got now:
#include <stdlib.h>
#include <string.h>
void setup() {
Serial.begin(9600);
}
char hexColor[] = "#FFFFFF";
void HEXtoRGB();
void HEXtoRGB() {
hexColor[6] = "3";
char red[5] = {0};
char green[5] = {0};
char blue[5] = {0};
red[0] = green[0] = blue[0] = '0';
red[1] = green[1] = blue[1] = 'X';
red[2] = hexColor[1];
red[3] = hexColor[2];
green[2] = hexColor[3];
green[3] = hexColor[4];
blue[2] = hexColor[5];
blue[3] = hexColor[6];
long r = strtol(red, NULL, 16);
long g = strtol(green, NULL, 16);
long b = strtol(blue, NULL, 16);
Serial.println(r);
Serial.println(g);
Serial.println(b);
Serial.println(hexColor);
}
Any sort of input would be greatly appreciated, it's the first time writing in something else than javascript.
Thank you.
The main error you're doing is confusing "3" with '3'.
"3" is a string which in C is a null-terminated array of chars while '3' is the character 3. So
hexColor[6] = "3"; means: "write the memory address of the string "3" into hexColor[6]".
What you wanted to do is:
hexColor[6] = '3';
This should work:
char hexColor[7] = "#FFFFFF";
int main(){
for(int i=0; i<7; i++)
printf("%c ", hexColor[i]);
hexColor[6]='3';
for(int i=0; i<7; i++)
printf("%c ", hexColor[i]);
}
Outout:
#FFFFFF #FFFFF3

Concatenating uint8_t to a char*

im really new to C and im having a bit of a complication creating a char* from various uint8_t
My idea is to create a char* where in each location I place a number form a matrix
For example if I have a matrix with:
[1][2][3][4]
[5][6][7][8]
[9][0][1][2]
[3][4][5][6]
id like a char* thats "01234567890123456"
what im doing bit its not working is:
char* string = malloc(sizeof(char)*matrix->height*matrix->width);
for (int i = 0; i < matrix->height ; ++i) {
for (int j = 0; j < matrix->width ; ++j) {
string[i*matrix->height+j] = matrix->value[i][j];
}
}
of course its not working but im a bit lost on how to proceed and I cant find more information regarding this problem.
Any help would be nice,
thanks
Since you're trying to print a string, you need the ASCII character for 0. So, simply add '0' to each number, like so
char* string = malloc(sizeof(char)*(matrix->height*matrix->width + 1));
for (int i = 0; i < matrix->height ; ++i) {
for (int j = 0; j < matrix->width ; ++j) {
string[i*matrix->width+j] = matrix->value[i][j] + '0';
}
}
string[matrix->height*matrix->width] = 0; //null terminator
Note however this isn't exactly the most portable solution.
Also, notice that you want to multiply i by the width, because if you didn't have a square matrix your calculation wouldn't work correctly.
It's kind of unnecessary to have sizeof(char), because the size of a char is defined to be 1 regardless of the byte size.

How to convert byte to int?

I have an Arduino which is reading in a set of three bytes from a program which correspond to degrees in which an actuator must turn. I need to convert these bytes into integers so I can pass those integers on to my actuators.
For example, I know the default rest state value I receive from the program is 127. I wrote a C# program to interpret these bytes and that can get them to a single integer value. However, I am unable to figure out how to do this in the Arduino environment with C. I have tried typecasting each byte to a char and storing that in a string. However that returns garbled values that make no sense.
void loop() {
if(Serial.available() && sw)
{
for(int j = 0; j < 3; j++)
{
input[j] = Serial.read();
}
//command = ((String)input).toInt();
sw = 0;
}
String myString = String((char *)input);
Serial.println(myString);
}
The return value of Serial.read() is an int. Therefore, if you have the following code snippet:
int input[3];
for (int i = 0; i < 3; i++) {
input[i] = Serial.read();
}
Then input should store three ints. However, the code:
char* input[3];
for (int i = 0; i < 3; i++) {
input[i] = Serial.read();
}
Will just store the byte conversion from int to char.
If you want to store this as a string, you need to do a proper conversion. In this case, use itoa (see Arduino API description).
The code snippet would be:
#include <stdlib>
char* convertedString = itoa(input[i]);
This should work:
int command = input[0]*256*256 + input[1]*256 + input[2];
By the way the default language you use to program your an Arduino is C++, not C. Although they have some similarities.
Below logic will help you
iDst = (cSrc[0] << 16) | (cSrc[1] << 8) | cSrc[2]
or else you can use union for this case
union byte2char
{
char c[4];
int i;
};
But union implementation needs to consider little and big endian systems

Save integer value as a byte value in char in ansi c

I want to save a ppm file as a P6. That mean bytes only. Also I want to save it in parallel way, so this is why I am using mmap to map memory.
This is a part of code where I am trying to save everything:
char* map;
//...
int offset = sprintf(map,"P6\n%d %d\n%d\n",x,y,k);
int counter = offset;
for(i = 0; i < x; i++)
{
for(j = 0; j < y; j++)
{
map[counter] = outputRed[i][j];
map[counter+1] = outputGreen[i][j];
map[counter+2] = outputBlue[i][j];
counter++;
}
}
The problem is that I am unable to save those values from Red, green and blue array (all are int) into map values.
Earlier I've simply used fputc with fopen(FILE,"wb") and that was doing everything nice, but now I cannot do it like this.
Can someone tell me how I can do it?
You have to increment the counter by 3 for each pixel:
map[counter] = outputRed[i][j];
map[counter+1] = outputGreen[i][j];
map[counter+2] = outputBlue[i][j];
counter += 3;
You can increment the counter after copying data for each pixel. This may be more easy to understand.
map[counter++] = outputRed[i][j];
map[counter++] = outputGreen[i][j];
map[counter++] = outputBlue[i][j];
Make sure the enough memory is allocated to map.

Resources