7 years, 7 months ago.

char not casting to type int........really stuck here!

My programs compile successfully but what I see on the lcd screen as type int for AxB, AyB, AzB is not what I see on TeraTerm having passed the pointer to the array? I'm pretty sure I'm reading the correct array locations but I can't seem to read the values as integers, really neeed a more experienced programmers help here.

I'm just trying to make the accelerometer parts of the program work first so ignore the rest

Many thanks for any and all suggestions.

main.cpp

/*

*/
 
#include "mbed.h"
#include "TextLCD.h"
#include "ADXL345_I2C.h"
#include "ITG3200.h"
#include "RecordData.h"
#include "GetAccelerometer.h"
#include "GetGyro.h"


// Use this if using Tera Term
Serial pc(USBTX, USBRX);

//Set up I2C comms and devices
I2C i2c(p9,p10);//p28,p27
I2C i2c_lcd(p9,p10); // sda, scl
 
DigitalOut Status_1(LED1);
#define LED_ON 1
#define LED_OFF 0

//float gyro_buffer[480];
int err;
int samples = 120; //(check wait in while loop)
int file_open = 0;
   
TextLCD_I2C lcd(&i2c_lcd, 0x4E, TextLCD::LCD20x4); // I2C bus, 2004A Slaveaddress 0x4E, LCD Type

//Function declaration
void calibrateAccelerometer();

//Global Variables
int readings[3] = {0, 0, 0};

char buffer_a[] = {0, 0, 0}; //was int
char *buffer_aptr; //was int

int buffer_g[] = {0, 0, 0};
int *buffer_gptr;
int a_xBias, a_x = 0;
int a_yBias, a_y = 0;
int a_zBias, a_z = 0;
float gx, gy, gz = 0;
    
int main() {
     
    // ...... you will need to set time first!
      set_time(1490126860);  // Set RTC time from unixtimestamp.com --1489651200
         
    // These are here to test whether any of the initialization fails. It will print the failure
    if (accelerometer.setPowerControl(0x00)){ 
         //pc.printf("didn't intitialize power control\n");
         lcd.printf("didn't intitialize power control\n");
         return 0;  }
     //Full resolution, +/-16g, 4mg/LSB.
     wait(0.1);
     
     if(accelerometer.setDataFormatControl(0x0B)){
        //pc.printf("didn't set data format\n");
        lcd.printf("didn't set data format\n");
        return 0;  }
     wait(0.1);
     
     //3.2kHz data rate.
     if(accelerometer.setDataRate(ADXL345_3200HZ)){
        //pc.printf("didn't set data rate\n");
        lcd.printf("didn't set data rate\n");
        return 0;    }
     wait(0.1);
     
     //Measurement mode.
     if(accelerometer.setPowerControl(MeasurementMode)) {
        //pc.printf("didn't set the power control to measurement\n");
        lcd.printf("didn't set the power control to measurement\n");
        return 0;   }
     
    //First calibrate your device. The ADXL350 datasheet explains about offset.
    calibrateAccelerometer();
       
    //GYRO set up starts here!
    //Set highest bandwidth.
    gyro.setLpBandwidth(LPFBW_42HZ); //was gyro1.seLpBandwidth
    //Set LCD integrted backlight to ON
    lcd.setBacklight(TextLCD::LightOn);
    
    while (1){
                
        accelerometer.getOutput(readings);
        
        //Put the 'raw' values into Ax,Ay and Az vaiables _nb (no bias).
        int Ax_nb = (int16_t)readings[0];
        int Ay_nb = (int16_t)readings[1];
        int Az_nb = (int16_t)readings[2];
        
        //Subtract the offset from the non biased raw values
        int Ax = Ax_nb - a_xBias; //was int
        int Ay = Ay_nb - a_yBias;
        int Az = Az_nb - a_zBias;
        
        //Put results in a buffer
        buffer_a[0] = Ax;
        buffer_a[1] = Ay;
        buffer_a[2] = Az;
              
        buffer_aptr = &buffer_a[0];
       /*
         To get acceleration due to gravity in the 3 axis multiply the 
         the offset adjusted raw value by the resolution 4mg per LSB
         noting 250 is 1g.
        */
        gx = Ax * 0.004;
        gy = Ay * 0.004;
        gz = Az * 0.004;
                
        int Gx = GyroReading_x();
        int Gy = GyroReading_y();
        int Gz = GyroReading_z();
        buffer_g[0] = Gx;
        buffer_g[1] = Gy;
        buffer_g[2] = Gz;
                      
        buffer_gptr = &buffer_g[0];
        
        Datarecord(buffer_aptr, buffer_gptr, sizeof(buffer_a), sizeof(buffer_g));
        Status_1 = LED_ON;                
                          
        //Lets look at some results if they make any sense!
        lcd.cls();
                        
        //Output of ADXL345 without calibration function
        lcd.locate(0,1);
        //Output of ADXL345 with calibration function
        lcd.printf("AxB%i AyB%i AzB%i\n", Ax, Ay, Az);
        
        lcd.locate(0,3);
        /*
         Outut of each axis in terms of force due to gravity. By looking at the
         reference document AN-177 and orientating the chip to match you should
         see each of the axis display 1g aginst its orientation.
        */ 
        lcd.printf("gx%03.2f gy%03.2f gz%03.2f\r\n", gx, gy, gz);
        //lcd.printf("gz%04.3f\n",gz);
        //lcd.printf("Gx%i Gy%i Gz%i\n\r", Gx, Gy, Gz);
        
        /*
         This temperature is included for completeness refer to the ADXL350
         datasheet for temperature effects.
        */  
        //lcd.printf("Temperature %2.1f \n",gyro.getTemperature());
        
        wait(1);
        }
}

RecordData.cpp

#include "RecordData.h"

SDFileSystem sd(p5,p6,p7,p8,"sd"); //MOSI, MISO, SCLK, CS

char buffer[42];

// LED's to know the status what's happening
//DigitalOut Status_1(LED1);
DigitalOut Status_2(LED2);
DigitalOut Status_3(LED3);
DigitalOut Status_4(LED4);
#define LED_ON 1
#define LED_OFF 0

// create an empty file pointer.
FILE *Gyro_Accelerometer_LogFile = NULL;

//Record the temperature onto SD card with timestamp    
//void Datarecord(int *ptr_A, int *ptr_G, int size_a, int size_g)//was (float data)
void Datarecord(char *ptr_A, int *ptr_G, char size_a, char size_g)
{
    // Use this if using Tera Term
    Serial pc(USBTX, USBRX);
    pc.printf("%i\n",size_a);
    
    int A=0;
    
    wait(1);
    Status_4 = LED_ON;//Data should have been recorded
    time_t seconds = time(&seconds);
    strftime(buffer, 42, "%d/%m/%y,%T", localtime(&seconds));
    //pc.printf("Time as a basic string = %s\r\n", ctime(&seconds));
    FILE *fp = fopen("/sd/Gyro_Accelerometer_Datalogger.txt", "a");   // the 'a' appends data to the existing file.
    for (char i=0; i<size_a; i++)
    {
        Status_2 = LED_ON;//Data should have been recorded
        pc.printf("%d,\n",*(ptr_A+i));
        A = (int) *(ptr_A+i);
        //A = (int)A;
        pc.printf("A%i,",A);
        wait(0.10);
        //fprintf (fp,"%04.if,",*data_ptr_Gyro+i);
        pc.printf("%s, \r\n",buffer);
        wait(0.10);
        //fprintf (fp,"%s,\r\n",buffer);
         Status_3 = LED_ON;
        }
    /*for(int i=0; i<size_g; i++)
    {
        fprintf (fp,"%0.4.if,",*data_ptr_Gyro+i);
        fprintf (fp,"%s,\r\n",buffer);
        }*/                
    fclose(fp);
    //Status_2 = LED_ON;//Data should have been recorded
    }
    
void SDreset()
{
    // creates an empty file Datalogger.txt on the SD card, old data will be lost.
    FILE *fp = fopen("/sd/Gyro_Accelerometer_Datalogger.txt", "w");  
    fclose(fp);
    }    

2 Answers

7 years, 7 months ago.

It would probably help if you isolated this to the smallest program that produces the behavior in question.

The pointer use doesn't look right. buffer_a and buffer_g are already pointers. If DataRecord wants type, char *ptr_A, you should simply pass it buffer_a or:

buffer_aptr = buffer_a;

I am pretty sure this is the problem. You are passing the address of the pointer instead of the pointer.

You also shouldn't have to resort to pointer math inside DataRecord function, you can continue to use array references, which are probably less confusing.

Some the fprintf stuff that is commented out doesn't look like it is using the pointers right. You want to do the pointer math before you dereference it.

  • data_ptr_Gyro+i, I believe should be *(data_ptr_Gyro+i)

I would leave size_a and size_g, as native data type int. You are potentially forcing extra work by declaring them as 8bit chars. Same thing with index i.

I am also concerned that buffer_a is only 8bits (i.e. char size) and you are putting int Ax into it. If Ax is every greater than 255 you will lose bits and buffer_a will contain nonsense.

I would make buffer_a and buffer_g, int's. You are using printf and fprintf to format the data output and data on the disc, so there is no need to save as 8bits.

Here is a stripped down program showing relevant parts that seems to work:

/** Datarecord Test
    Check pointer match for Datarecord function
 */

#include "mbed.h"

// Heartbeat
DigitalOut led1(LED1);

// Test Datarecord function
void Datarecord(int array_a[], int array_g[], int size_a, int size_g)
{   
    wait(1);
    //printf("buffer a = %d, %d, %d\r\n",*(ptr_A),*(ptr_A+1),*(ptr_A+2));
    
    printf("buffer a = %d, %d, %d\r\n",array_a[0],array_a[1],array_a[2]);
    printf("buffer g = %d, %d, %d\r\n",array_g[0],array_g[1],array_g[2]);
}


// main
int main() {
  
    int readings[3] = {0, 0, 0};
    int buffer_a[] = {0, 0, 0}; //was int 
    int buffer_g[] = {0, 0, 0};
    int a_xBias, a_x = 0;
    int a_yBias, a_y = 0;
    int a_zBias, a_z = 0;
    float gx, gy, gz = 0;
    
    while (1){
                
        // Fake readings
        readings[0] += 1;
        readings[1] += 2;
        readings[2] += 3;     
        
        // Put the 'raw' values into Ax,Ay and Az vaiables _nb (no bias).
        int Ax_nb = readings[0];
        int Ay_nb = readings[1];
        int Az_nb = readings[2];
        
        // Subtract the offset from the non biased raw values
        int Ax = Ax_nb;
        int Ay = Ay_nb;
        int Az = Az_nb;
        
        // Put results in a buffer
        buffer_a[0] = Ax;
        buffer_a[1] = Ay;
        buffer_a[2] = Az;           

        // Fake these readings     
        int Gx = 100;
        int Gy = 110;
        int Gz = 120;
        buffer_g[0] = Gx;
        buffer_g[1] = Gy;
        buffer_g[2] = Gz;
                         
        Datarecord(buffer_a, buffer_g, sizeof(buffer_a), sizeof(buffer_g));
       
        led1 = !led1;
        wait(1);           
    }
}

Accepted Answer

Thanks a lot Graham and Zoltan, I'll certainly review all the great tips and implement them accordingly. I've grasped the idea that pointers only refer to the memory location where data is held. I just need more practice on how to use them particulalry passing pointer references between functions, the tips above regarding use of array data is most welcome. Thanks again chaps.

posted by Derek Calland 01 Apr 2017
7 years, 7 months ago.

Hello Derek,

Try to cast to int as follows:

//A = (int) *(ptr_A+i);
A = *(int*)(ptr_A + i);    // simple 'C' style cast

or

//A = (int) *(ptr_A+i);
A = *reinterpret_cast<int*>(ptr_A + i);    // this makes it more readable

To calculate the number of elements (length) of an array (e.g. for passing it to a function):

int array_length = sizeof(array)/sizeof(*array);

Thank you so much Zoltan....this was my solution using your suggestions, it is now working that I see on TeraTerm what I see on the LCD screen.

main.cpp

int readings[3] = {0, 0, 0};

int buffer_a[] = {0, 0, 0}; 
int *buffer_aptr; 

int buffer_g[] = {0, 0, 0};
int *buffer_gptr;
int a_xBias, a_x = 0;
int a_yBias, a_y = 0;
int a_zBias, a_z = 0;
float gx, gy, gz = 0;

int array_length_a = sizeof(buffer_a)/sizeof(*buffer_aptr);
    
int main() {
     
    while (1){
        //Put results in a buffer
        buffer_a[0] = Ax;
        buffer_a[1] = Ay;
        buffer_a[2] = Az;
              
        buffer_aptr = &buffer_a[0];
       /*
         To get acceleration due to gravity in the 3 axis multiply the 
         the offset adjusted raw value by the resolution 4mg per LSB
         noting 250 is 1g.
        */
        gx = Ax * 0.004;
        gy = Ay * 0.004;
        gz = Az * 0.004;
                
        int Gx = GyroReading_x();
        int Gy = GyroReading_y();
        int Gz = GyroReading_z();
        buffer_g[0] = Gx;
        buffer_g[1] = Gy;
        buffer_g[2] = Gz;
                      
        buffer_gptr = &buffer_g[0];
        
        Datarecord(buffer_aptr, buffer_gptr, array_length_a, sizeof(buffer_g));
        wait(1);
        }
}

RecordData.cpp

#include "RecordData.h"
void Datarecord(int *ptr_A, int *ptr_G, int size_a, char size_g)
{
    pc.printf("%i\n",size_a);
    
    int A=0;
    
    wait(1);
    for (int i=0; i<size_a; i++)
    {
        pc.printf("%d,\n",*(ptr_A+i));
        A = *(int*)(ptr_A + i);    // simple 'C' style cast
        //A = *reinterpret_cast<int*>(ptr_A + i);
        //A = (int) *(ptr_A+i);
        //A = (int)A;
        pc.printf("A%i,",A);
        //fprintf (fp,"%04.if,",*data_ptr_Accelerometer+i);
        wait(0.10);
        //fprintf (fp,"%04.if,",*data_ptr_Gyro+i);
        pc.printf("%s, \r\n",buffer);
        wait(0.10);
        //fprintf (fp,"%s,\r\n",buffer);
         Status_3 = LED_ON;
        }
    /*for(int i=0; i<size_g; i++)
    {
        fprintf (fp,"%0.4.if,",*data_ptr_Gyro+i);
        fprintf (fp,"%s,\r\n",buffer);
        }*/                
    fclose(fp);
    //Status_2 = LED_ON;//Data should have been recorded
    }
    
void SDreset()
{
    // creates an empty file Datalogger.txt on the SD card, old data will be lost.
    FILE *fp = fopen("/sd/Gyro_Accelerometer_Datalogger.txt", "w");  
    fclose(fp);
    }    

posted by Derek Calland 31 Mar 2017

Hello Derek,
Graham is right that an array variable is also a pointer. It's actually a constant pointer pointing to the memory location &array[0]. So you can pass the array variables also as follows and then there is no need for casting:

...
int main() {
    ...
int buffer_a[] = {0, 0, 0}; 
int buffer_g[] = {0, 0, 0};
    ...

    Datarecord(buffer_a, buffer_g, sizeof(buffer_a)/sizeof(*buffer_a), sizeof(buffer_g)/sizeof(*buffer_g));

    ...
}


void Datarecord(int* array_a, int* array_g, int size_a, int size_g) {
    ...
    for(int i = 0; i < size_a; i++) {
        ...
        pc.printf("array_a[%d] = %d\r\n", i, array_a[i]);
        ...
    }
    ...
}

or

void Datarecord(int array_a[], int array_g[], int size_a, int size_g) {
    ...
    for(int i = 0; i < size_a; i++) {
        ...
        pc.printf("array_a[%d] = %d\r\n", i, array_a[i]);
        ...
    }
    ...
}
posted by Zoltan Hudak 31 Mar 2017