
SPI slave program to enable communication between the FPGA and the STM32L432 board.
main.cpp
- Committer:
- Zbyszek
- Date:
- 2019-02-27
- Revision:
- 8:e87027349167
- Parent:
- 7:0e9af5986488
- Child:
- 9:9ed9dffd602a
File content as of revision 8:e87027349167:
#include "mbed.h" #include "SPI.h" #include "IMUs.h" #include "Structures.h" #include "Quaternions.h" #include "DMA_SPI.h" DigitalOut myled(LED1); Serial pc(USBTX, USBRX); int masterRx = 0; int16_t slaveRx = 0; int i = 2; int k = 0; int16_t zgHigher = 0; int16_t zgLower = 0; int16_t zGyro = 0; int countx = 0; int p = 32776; double const SSF = 0.06097560975609756097560975609756f; //FSEL = 0: 0.00763358778625954198473282442748, FSEL = 3: 0.06097560975609756097560975609756f int OffsetX = 254; int OffsetY = -14; int OffsetZ = 81; int OffsetXA = -306; int OffsetYA = -131; int OffsetZA = -531; IMU IMU0 (0, -306.0f, -131.0f, -351.0f, 254.0f, -14.0f, 81.0f, 0, 3); IMU_Data Dat; vector Datt; Timer t; float dTime = 0.0f; vector vertical; vector globalAccel; vector correctionGlobalAccel; vector correctionBodyAccel; Quaternion gyroQ; vector Eangles; Quaternion CF; vector intGyro; vector GyroVals; vector AccelVals; vector accelTilt; Quaternion accelQ; void calibrateOffset(); float xx; float yy; float zz; /* */ //------------------Printing-All-values----------------------// int16_t IMUarray[12]; //Store each separate reading in an array uint16_t IDarray[12]; //Holds the identification of each data piece char idx = 0; //IMUarray Pointer char dataCount = 0; //Keeps track of how many data points have been read in using SPI uint16_t id = 0; //Used to store extracted data ID void ProcessAndPrint(); //------------------Printing-All-values----------------------// //-------------Testing-Variables-Remove-Later----------------// int blinkCounter = 0; //-------------Testing-Variables-Remove-Later----------------// int main() { pc.baud (115200); IDarray[0] = 1; IDarray[1] = 0; IDarray[2] = 9; IDarray[3] = 8; IDarray[4] = 17; IDarray[5] = 16; IDarray[6] = 3; IDarray[7] = 2; //2 IDarray[8] = 11; IDarray[9] = 10; IDarray[10] = 19; IDarray[11] = 18; init_spi1(); t.start(); gyroQ.w = 1; gyroQ.x = 0.0001; gyroQ.y = 0.0001; gyroQ.z = 0.0001; CF.w = 1; CF.x = 0.0001; CF.y = 0.0001; CF.z = 0.0001; gyroQ = normaliseQuaternion(gyroQ); CF = normaliseQuaternion(CF); vertical.x = 0.0f; vertical.y = 0.0f; vertical.z = 1.0f; pc.printf("Begin \n\r"); while(1) { if(i == 1) { for(int x = 1; x < 128; x *= 2) { slaveRx = transfer_spi_slave(x); //pc.putc(slaveRx); pc.printf("%d \n\r",slaveRx); } for(int x = 128; x > 1; x /= 2) { slaveRx = transfer_spi_slave(x); //pc.putc(slaveRx); pc.printf("%d \n\r",slaveRx); } }//if(i == 1) //------------------------------------------------------------------------------ if(i == 0) { slaveRx = transfer_spi_slave(10); countx++; if(countx == 1) { k = slaveRx; k &= ~(255 << 8); k = k << 8; // if(k == 19) { zgHigher = k; //zgHigher = zgHigher << 8; //}//if(k == 19) }//if(count == 11) else if(countx == 2) { k = slaveRx; k &= ~(255 << 8); //k = k << 8; //if(k == 18) { zgLower = k; //zgLower = zgLower << 8; zGyro = zgHigher + zgLower; pc.printf("%+d \n\r",zGyro); //}//if(k == 19) countx = 0; }//else if(count == 12) }//if(i == 0) //------------------------------------------------------------------------------ if(i == 2) { slaveRx = transfer_spi_slave(10); //get IMU data id = slaveRx; //Save sample to id for id extraction id &= ~(255); //get rid of the actual data to only be left with the id id = id >> 8; //shift the id to the right for comparison //pc.printf("ID: %d \n\r", id); //Print each id to see what sequence is obtained. Only the correct sequence will make the code run/ if(IDarray[dataCount] == id) { //compare if the order of data is right and if not wait until it is. dataCount++; //Increase dataCount as new value has been read in. IMUarray[idx] = slaveRx; //save the newly read value to current free space in the array idx++; //increment the pointer to point to next free space in the array if(dataCount == 12) { //reset idx and dataCount dataCount = 0; idx = 0; //ProcessAndPrint(); //calibrateOffset(); //IMU0.concatenateData(IMUarray); Datt = IMU0.CalculateQCFAngles(IMUarray); t.stop(); dTime = t.read(); t.reset(); t.start(); }//if(dataCount == 12) }//if(IDarray[dataCount] == id) else { //-----Code-Used-For-Testing-----// //pc.printf("Failed at: %d \n\r", dataCount); //Print an error if there is one if(blinkCounter == 10) { //Slow the blinking down to make it visible if there are errors myled = !myled; //Change state of the LED if error occurs blinkCounter = 0; //Reset Blink counter } else { blinkCounter++; } //-----Code-Used-For-Testing-----// dataCount = 0; //ID sequence is worng so reset the counter idx = 0; //ID sequence is worng so reset the counter } }//if(i == 2) } } /* -The purpose of this function */ void ProcessAndPrint() { int16_t MSB = 0; //Store Most Significant Byte of data piece in this variable for processing int16_t LSB = 0; //Store Least Significant Byte of data piece in this variable for processing char arrPointer = 0; //Array Pointer //-----------Concatentated-Data-Pieces------------------------------------------ int16_t gyroX = 0; int16_t gyroY = 0; int16_t gyroZ = 0; int16_t accelX = 0; int16_t accelY = 0; int16_t accelZ = 0; float faccelX = 0.0f; float faccelY = 0.0f; float faccelZ = 0.0f; float fgyroX = 0.0f; float fgyroY = 0.0f; float fgyroZ = 0.0f; //-----------Concatentated-Data-Pieces------------------------------------------ for(char x = 0; x <= 5; x++) { MSB = IMUarray[arrPointer]; //Odd data pieces are MSBs MSB &= ~(255<<8); //Mask the MSB bits as they are not part of data MSB = MSB << 8; //Shift the Value as its the MSB of the data piece arrPointer++; //Increment array pointer LSB = IMUarray[arrPointer]; //Even data pieces are LSBs LSB &= ~(255 << 8); //Mask the MSB bits as they are not part of data arrPointer++; //Increment array pointer switch(x) { case 0: accelX = (MSB + LSB) + OffsetXA; //Combine Accelerometer x-axis data faccelX = (float)accelX * 0.00006103515625f; //Multiply the acceleration by sensitivity scale factor to get it into g 1/16,384 break; case 1: accelY = (MSB + LSB) + OffsetYA; //Combine Accelerometer y-axis data faccelY = (float)accelY * 0.00006103515625f; //Multiply the acceleration by sensitivity scale factor to get it into g 1/16,384 break; case 2: accelZ = (MSB + LSB) + OffsetZA; //Combine Accelerometer z-axis data faccelZ = (float)accelZ * 0.00006103515625f; //Multiply the acceleration by sensitivity scale factor to get it into g 1/16,384 break; case 3: gyroX = (MSB + LSB) + OffsetX; //Combine Gyroscope x-axis data fgyroX = (float)gyroX * SSF; //Multiply the sample by sensitivity scale factor to get it into degress per second 1/16.4 break; case 4: gyroY = (MSB + LSB) + OffsetY; //Combine Gyroscope y-axis data fgyroY = (float)gyroY * SSF; //Multiply the sample by sensitivity scale factor to get it into degress per second 1/16.4 break; case 5: gyroZ = (MSB + LSB) + OffsetZ; //Combine Gyroscope z-axis data fgyroZ = (float)gyroZ * SSF; //Multiply the sample by sensitivity scale factor to get it into degress per second 1/16.4 break; default: break; }//switch(x) }//for(char x = 0; x <= 5; x++) //Quaternion-Gyro-Integration-------------------------------------------------------------- //Get the Gyro and Accel values-------------------------------------------------------- //Convert these vales to radians per second and store them in the vector GyroVals.x = fgyroX * 0.0174533f; GyroVals.y = fgyroY * 0.0174533f; GyroVals.z = fgyroZ * 0.0174533f; intGyro.x = (fgyroX * dTime); intGyro.y = (fgyroY * dTime); intGyro.z = (fgyroZ * dTime); AccelVals.x = faccelX; AccelVals.y = faccelY; AccelVals.z = faccelZ; //Get the Gyro and Accel values-------------------------------------------------------- //CF = updateQuaternion(CF, GyroVals, dTime); //CF = normaliseQuaternion(CF); //Eangles = eulerA(CF); //Quaternion-Gyro-Integration-------------------------------------------------------------- //Angle-Calculations-Based-on-Accalerometer------------------------------------------------ //https://www.dfrobot.com/wiki/index.php/How_to_Use_a_Three-Axis_Accelerometer_for_Tilt_Sensing accelTilt.x = (atan2f(AccelVals.y, AccelVals.z) * 57.29577951f); accelTilt.y = (atan2f((-AccelVals.x), sqrt(pow(AccelVals.y, 2) + pow(AccelVals.z, 2) )) * 57.29577951f); //pc.printf("%+6f, %+6f ", accelTilt.x, accelTilt.y); //Canntot calculate accel tilt for Z. Gyro date in combination with magnetometer have to be used to obtain reliable z-axis tilt. //Angle-Calculations-Based-on-Accalerometer------------------------------------------------ //pc.printf("%+6f, %+6f, %+6f ", CF.x, CF.y, CF.z); //Complementary-Filter--------------------------------------------------------------------- //CF.x = 0.98f*(Eangles.x) + 0.02f*accelTilt.x; //CF.y = 0.98f*(Eangles.y) + 0.02f*accelTilt.y; //CF.z = 0.98f*(Eangles.z) + 0.02f*accelTilt.z; CF.x = 0.98f*(CF.x + intGyro.x) + 0.02f*accelTilt.x; CF.y = 0.98f*(CF.y + intGyro.y) + 0.02f*accelTilt.y; CF.z = 0.98f*(CF.z + intGyro.z) + 0.02f*accelTilt.z; //Complementary-Filter--------------------------------------------------------------------- //Add the correction to gyro readings and update the quaternion------------------------ //pc.printf("%+6f, %+6f, %+6f %+6f\n\r ", xx, yy, zz, dTime); //pc.printf("%+6f, %+6f, %+6f, %+6f, %+6f, %+6f, %+6f\n\r ", gyroQ.w, gyroQ.x, gyroQ.y, gyroQ.z, CF.x, CF.y, Eangles.z); //pc.printf("%+6f, %+6f, %+6f \n\r", CF.x, CF.y, CF.z); //CF.x *= 0.0174533f; //CF.y *= 0.0174533f; // CF.z *= 0.0174533f; //CF = euler2Quaternion(CF); //CF = normaliseQuaternion(CF); //pc.printf("%+6f, %+6f, %+6f\n\r ",Eangles.x, Eangles.y, Eangles.z); pc.printf("Accel X: %+6f, Accel Y: %+6f, Accel Z: %+6f, Gyro X: %+6f, Gyro Y: %+6f, Gyro Z: %+6f\n\r", faccelX, faccelY, faccelZ, fgyroX, fgyroY, fgyroZ); //pc.printf("Accel X: %+6f, Accel Y: %+6f, Accel Z: %+6f, Gyro X: %+6d, Gyro Y: %+6d, Gyro Z: %+6d\n\r", faccelX, faccelY, faccelZ, gyroX, gyroY, gyroZ); }//void ProcessAndPrint() void calibrateOffset() { int16_t MSB = 0; //Store Most Significant Byte of data piece in this variable for processing int16_t LSB = 0; //Store Least Significant Byte of data piece in this variable for processing char arrPointer = 0; //Array Pointer //-----------Concatentated-Data-Pieces------------------------------------------ int16_t gyroX = 0; int16_t gyroY = 0; int16_t gyroZ = 0; int16_t accelX = 0; int16_t accelY = 0; int16_t accelZ = 0; vector accelRaw; vector accelG; vector gyroRaw; vector gyroDPS; static unsigned int sampleCounter = 1; static vector accelRawAvg; static vector accelGAvg; static vector gyroRawAvg; static vector gyroDPSAvg; for(char x = 0; x <= 5; x++) { MSB = IMUarray[arrPointer]; //Odd data pieces are MSBs MSB &= ~(255<<8); //Mask the MSB bits as they are not part of data MSB = MSB << 8; //Shift the Value as its the MSB of the data piece arrPointer++; //Increment array pointer LSB = IMUarray[arrPointer]; //Even data pieces are LSBs LSB &= ~(255 << 8); //Mask the MSB bits as they are not part of data arrPointer++; //Increment array pointer switch(x) { case 0: accelX = MSB + LSB; //Combine Accelerometer x-axis data accelRaw.x = (double)accelX; //accelRaw accelG.x = (double)accelX * 0.00006103515625f; //accelSSF break; case 1: accelY = MSB + LSB; //Combine Accelerometer y-axis data accelRaw.y = (double)accelY; accelG.y = (double)accelY * 0.00006103515625f; break; case 2: accelZ = MSB + LSB; //Combine Accelerometer z-axis data accelRaw.z = (double)accelZ; accelG.z = (double)accelZ * 0.00006103515625f; break; case 3: gyroX = MSB + LSB; //Combine Gyroscope x-axis data gyroRaw.x = (double)gyroX; //gyroRaw gyroDPS.x = (double)gyroX * SSF; //gyroSSF break; case 4: gyroY = MSB + LSB; //Combine Gyroscope y-axis data gyroRaw.y = (double)gyroY; gyroDPS.y = (double)gyroY * SSF; break; case 5: gyroZ = MSB + LSB; //Combine Gyroscope z-axis data gyroRaw.z = (double)gyroZ; gyroDPS.z = (double)gyroZ * SSF; break; default: break; }//switch(x) }//for(char x = 0; x <= 5; x++) //Take-Running-Averages------------------------------------------------------------------------ //Raw accel averages accelRawAvg.x = accelRawAvg.x + ((accelRaw.x - accelRawAvg.x)/sampleCounter); accelRawAvg.y = accelRawAvg.y + ((accelRaw.y - accelRawAvg.y)/sampleCounter); accelRawAvg.z = accelRawAvg.z + ((accelRaw.z - accelRawAvg.z)/sampleCounter); //SSF accel averages accelGAvg.x = accelGAvg.x + ((accelG.x - accelGAvg.x)/sampleCounter); accelGAvg.y = accelGAvg.y + ((accelG.y - accelGAvg.y)/sampleCounter); accelGAvg.z = accelGAvg.z + ((accelG.z - accelGAvg.z)/sampleCounter); //Raw gyroo averages gyroRawAvg.x = gyroRawAvg.x + ((gyroRaw.x - gyroRawAvg.x)/sampleCounter); gyroRawAvg.y = gyroRawAvg.y + ((gyroRaw.y - gyroRawAvg.y)/sampleCounter); gyroRawAvg.z = gyroRawAvg.z + ((gyroRaw.z - gyroRawAvg.z)/sampleCounter); //SSF gyro averages gyroDPSAvg.x = gyroDPSAvg.x + ((gyroDPS.x - gyroDPSAvg.x)/sampleCounter); gyroDPSAvg.y = gyroDPSAvg.y + ((gyroDPS.y - gyroDPSAvg.y)/sampleCounter); gyroDPSAvg.z = gyroDPSAvg.z + ((gyroDPS.z - gyroDPSAvg.z)/sampleCounter); //Take-Running-Averages------------------------------------------------------------------------ //Print Messages------------------------------------------------------------------------------- if(sampleCounter == 1) { pc.printf("Collecting Raw and Sensitivity Scale Factor multiplied Gyroscope and Accelerometer Offsets...\n\r"); }; if(sampleCounter == 5000) { pc.printf("RawAX RawAY RawAZ RawGX RawGY RawGZ SampleN\n\r"); pc.printf("%+-6.2f %+-6.2f %+-6.2f %+-6.2f %+-6.2f %+-6.2f %-10d\n\r", accelRawAvg.x, accelRawAvg.y, accelRawAvg.z, gyroRawAvg.x, gyroRawAvg.y, gyroRawAvg.z, sampleCounter); pc.printf("\n\r"); pc.printf("\n\r"); pc.printf("\n\r"); //Add the sensitivity scale factor multiplied data pc.printf("SSFAX SSFAY SSFAZ SSFGX SSFGY SSFGZ SampleN\n\r"); pc.printf("%+-6.2f %+-6.2f %+-6.2f %+-6.2f %+-6.2f %+-6.2f %-10d\n\r", accelGAvg.x, accelGAvg.y, accelGAvg.z, gyroDPSAvg.x, gyroDPSAvg.y, gyroDPSAvg.z, sampleCounter); }; sampleCounter++; //Print Messages------------------------------------------------------------------------------- } //------------------------------------------Artifacts---------------------------------------- //----------------------Insert Whole--------------------------------------------------- //Rotate the accel data Global reference frame by qvq*--------------------------------- //globalAccel = rotateGlobal(AccelVals, gyroQ); //Rotate the accel data Global reference frame by qvq*--------------------------------- //get the correction values and rotate back to IMU reference--------------------------- // correctionGlobalAccel = crossProduct(globalAccel, vertical); // correctionBodyAccel = rotateLocal(correctionGlobalAccel, gyroQ); //get the correction values and rotate back to IMU reference--------------------------- //Add the correction to gyro readings and update the quaternion------------------------ //GyroVals = sumVector(GyroVals, correctionBodyAccel); //incRot = toQuaternionNotation123(GyroVals, dTime); //gyroQ = getQuaternionProduct(gyroQ, incRot); //gyroQ = normaliseQuaternion(gyroQ); //----------------------Insert Whole--------------------------------------------------- //------------------------------------------Artifacts----------------------------------------