Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
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); } }
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 01 Apr 20177 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); }
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]); ... } ... }