SOFT261_CW

Dependencies:   X_NUCLEO_IKS01A1 mbed

Committer:
jbindin
Date:
Wed Aug 15 15:04:32 2018 +0000
Revision:
0:d9a14a63c3ed
snntst

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jbindin 0:d9a14a63c3ed 1 /*
jbindin 0:d9a14a63c3ed 2 This programme reads an accelerometer every 1/10 of a second.
jbindin 0:d9a14a63c3ed 3 The data is then stored in a ring buffer, for each sample the previous sample
jbindin 0:d9a14a63c3ed 4 is subtraced away from the current sample and a moving average of the past 10
jbindin 0:d9a14a63c3ed 5 samples are taken.
jbindin 0:d9a14a63c3ed 6
jbindin 0:d9a14a63c3ed 7 this moving average is then passed to a struct which is then passed to a message
jbindin 0:d9a14a63c3ed 8 queue. thread1 passes a signal to thread2 so it can process the values from the
jbindin 0:d9a14a63c3ed 9 struct.
jbindin 0:d9a14a63c3ed 10
jbindin 0:d9a14a63c3ed 11 thread2 works out the mean of the past 10 values and outputs it serially to a
jbindin 0:d9a14a63c3ed 12 console. This works out as one output per second (althouch not exact).
jbindin 0:d9a14a63c3ed 13
jbindin 0:d9a14a63c3ed 14 the project was made with MBEDs online compiler
jbindin 0:d9a14a63c3ed 15 */
jbindin 0:d9a14a63c3ed 16
jbindin 0:d9a14a63c3ed 17 // imports
jbindin 0:d9a14a63c3ed 18 #include "mbed.h"
jbindin 0:d9a14a63c3ed 19 #include "rtos.h"
jbindin 0:d9a14a63c3ed 20 #include "x_nucleo_iks01a1.h"
jbindin 0:d9a14a63c3ed 21
jbindin 0:d9a14a63c3ed 22 //to pass signal from threads (easier to read)
jbindin 0:d9a14a63c3ed 23 #define READ 1
jbindin 0:d9a14a63c3ed 24
jbindin 0:d9a14a63c3ed 25 //to show maximum ammount of samples stored
jbindin 0:d9a14a63c3ed 26 #define COUNTMAX 10
jbindin 0:d9a14a63c3ed 27
jbindin 0:d9a14a63c3ed 28 //declarations
jbindin 0:d9a14a63c3ed 29 Serial pc(USBTX, USBRX);
jbindin 0:d9a14a63c3ed 30 Thread* thread1;
jbindin 0:d9a14a63c3ed 31 Thread* thread2;
jbindin 0:d9a14a63c3ed 32
jbindin 0:d9a14a63c3ed 33 //struct to store x, y and z values from the accelerometer.
jbindin 0:d9a14a63c3ed 34 typedef struct {
jbindin 0:d9a14a63c3ed 35 float xVal;
jbindin 0:d9a14a63c3ed 36 float yVal;
jbindin 0:d9a14a63c3ed 37 float zVal;
jbindin 0:d9a14a63c3ed 38 } accMessage_t;
jbindin 0:d9a14a63c3ed 39
jbindin 0:d9a14a63c3ed 40 //declarations of additional functions used.
jbindin 0:d9a14a63c3ed 41 float movingAverage(float newSample, float previousSample, float rBuffer[]);
jbindin 0:d9a14a63c3ed 42 float average(float values[10]);
jbindin 0:d9a14a63c3ed 43
jbindin 0:d9a14a63c3ed 44 //used to collect samples from the expantion boards sensors
jbindin 0:d9a14a63c3ed 45 static X_NUCLEO_IKS01A1 *expBoard = X_NUCLEO_IKS01A1::Instance(D14, D15);
jbindin 0:d9a14a63c3ed 46 static MotionSensor *accelerometer = expBoard->GetAccelerometer();
jbindin 0:d9a14a63c3ed 47
jbindin 0:d9a14a63c3ed 48 //array to store x,y,z values in thread1
jbindin 0:d9a14a63c3ed 49 int accVals[3];
jbindin 0:d9a14a63c3ed 50
jbindin 0:d9a14a63c3ed 51 //used to store samples
jbindin 0:d9a14a63c3ed 52 float valuesX[COUNTMAX];
jbindin 0:d9a14a63c3ed 53 float valuesY[COUNTMAX];
jbindin 0:d9a14a63c3ed 54 float valuesZ[COUNTMAX];
jbindin 0:d9a14a63c3ed 55
jbindin 0:d9a14a63c3ed 56 //flag to discard the first output. the array is not populated yet so this output
jbindin 0:d9a14a63c3ed 57 //is not as accurate
jbindin 0:d9a14a63c3ed 58 bool arrayPopulated = false;
jbindin 0:d9a14a63c3ed 59
jbindin 0:d9a14a63c3ed 60 //queue and memory pool to create structs and pass messages efficiently
jbindin 0:d9a14a63c3ed 61 Queue<accMessage_t, 20> que;
jbindin 0:d9a14a63c3ed 62 MemoryPool<accMessage_t, 20> memPool;
jbindin 0:d9a14a63c3ed 63
jbindin 0:d9a14a63c3ed 64 /*this function is used by thread1, it samples values, passes them to the
jbindin 0:d9a14a63c3ed 65 movingAverage function, uses the memory pool to store them as structs
jbindin 0:d9a14a63c3ed 66 the structs are passed to a queue and sets a message to thread2 to allow it to
jbindin 0:d9a14a63c3ed 67 be active*/
jbindin 0:d9a14a63c3ed 68 void producer()
jbindin 0:d9a14a63c3ed 69 {
jbindin 0:d9a14a63c3ed 70 //collects data as previous values to make average more accurate
jbindin 0:d9a14a63c3ed 71 accelerometer->get_x_axes(accVals);
jbindin 0:d9a14a63c3ed 72 float previousX = accVals[0];
jbindin 0:d9a14a63c3ed 73 float previousY = accVals[1];
jbindin 0:d9a14a63c3ed 74 float previousZ = accVals[2];
jbindin 0:d9a14a63c3ed 75
jbindin 0:d9a14a63c3ed 76 //thread loop involves a 10ms delay
jbindin 0:d9a14a63c3ed 77 while(1) {
jbindin 0:d9a14a63c3ed 78 Thread::wait(100);
jbindin 0:d9a14a63c3ed 79 //sample data from accelerometer
jbindin 0:d9a14a63c3ed 80 accelerometer->get_x_axes(accVals);
jbindin 0:d9a14a63c3ed 81
jbindin 0:d9a14a63c3ed 82 float newAverageX = movingAverage((float)accVals[0], (float)previousX, valuesX);
jbindin 0:d9a14a63c3ed 83 float newAverageY = movingAverage((float)accVals[1], (float)previousY, valuesY);
jbindin 0:d9a14a63c3ed 84 float newAverageZ = movingAverage((float)accVals[2], (float)previousZ, valuesZ);
jbindin 0:d9a14a63c3ed 85 previousX = accVals[0];
jbindin 0:d9a14a63c3ed 86 previousY = accVals[1];
jbindin 0:d9a14a63c3ed 87 previousZ = accVals[2];
jbindin 0:d9a14a63c3ed 88
jbindin 0:d9a14a63c3ed 89 //adds values to struct
jbindin 0:d9a14a63c3ed 90 accMessage_t *message = memPool.alloc();
jbindin 0:d9a14a63c3ed 91 message->xVal = newAverageX;
jbindin 0:d9a14a63c3ed 92 message->yVal = newAverageY;
jbindin 0:d9a14a63c3ed 93 message->zVal = newAverageZ;
jbindin 0:d9a14a63c3ed 94
jbindin 0:d9a14a63c3ed 95 //passes structs to queue and sets thread2s signal
jbindin 0:d9a14a63c3ed 96 que.put(message);
jbindin 0:d9a14a63c3ed 97 thread2->signal_set(READ);
jbindin 0:d9a14a63c3ed 98 }
jbindin 0:d9a14a63c3ed 99 }
jbindin 0:d9a14a63c3ed 100
jbindin 0:d9a14a63c3ed 101 /*
jbindin 0:d9a14a63c3ed 102 function is used by thread2. it gets structs to the queue. Every 10 stucts
jbindin 0:d9a14a63c3ed 103 recieved calls the average function which returns the mean of the past 10 values.
jbindin 0:d9a14a63c3ed 104 this is done for the x,y and z axes.
jbindin 0:d9a14a63c3ed 105 the average is outputted although the first output is discarded to ensure the
jbindin 0:d9a14a63c3ed 106 first set of data is populated.
jbindin 0:d9a14a63c3ed 107 */
jbindin 0:d9a14a63c3ed 108 void consumer()
jbindin 0:d9a14a63c3ed 109 {
jbindin 0:d9a14a63c3ed 110 int count = 0;
jbindin 0:d9a14a63c3ed 111 //stores structs data in arrays so the values can be averaged later
jbindin 0:d9a14a63c3ed 112 float valuesReadX[10];
jbindin 0:d9a14a63c3ed 113 float valuesReadY[10];
jbindin 0:d9a14a63c3ed 114 float valuesReadZ[10];
jbindin 0:d9a14a63c3ed 115
jbindin 0:d9a14a63c3ed 116 while(1)
jbindin 0:d9a14a63c3ed 117 {
jbindin 0:d9a14a63c3ed 118 //waits for thread1
jbindin 0:d9a14a63c3ed 119 Thread::signal_wait(READ);
jbindin 0:d9a14a63c3ed 120
jbindin 0:d9a14a63c3ed 121 osEvent evt = que.get();
jbindin 0:d9a14a63c3ed 122 if(evt.status == osEventMessage)
jbindin 0:d9a14a63c3ed 123 {
jbindin 0:d9a14a63c3ed 124 accMessage_t *message = (accMessage_t*)evt.value.p;
jbindin 0:d9a14a63c3ed 125 valuesReadX[count] = message->xVal;
jbindin 0:d9a14a63c3ed 126 valuesReadY[count] = message->yVal;
jbindin 0:d9a14a63c3ed 127 valuesReadZ[count] = message->zVal;
jbindin 0:d9a14a63c3ed 128
jbindin 0:d9a14a63c3ed 129 memPool.free(message);
jbindin 0:d9a14a63c3ed 130
jbindin 0:d9a14a63c3ed 131 if(count >= 9)
jbindin 0:d9a14a63c3ed 132 {
jbindin 0:d9a14a63c3ed 133 if(arrayPopulated == true){
jbindin 0:d9a14a63c3ed 134
jbindin 0:d9a14a63c3ed 135 //output averages seperated by commas to ensure data can be
jbindin 0:d9a14a63c3ed 136 //easily read and processed
jbindin 0:d9a14a63c3ed 137 pc.printf("%.2f,\t %.2f,\t %.2f\n\r", average(valuesReadX), average(valuesReadY), average(valuesReadZ));
jbindin 0:d9a14a63c3ed 138 }
jbindin 0:d9a14a63c3ed 139 count = 0;
jbindin 0:d9a14a63c3ed 140 arrayPopulated = true;
jbindin 0:d9a14a63c3ed 141 }
jbindin 0:d9a14a63c3ed 142 }
jbindin 0:d9a14a63c3ed 143 count++;
jbindin 0:d9a14a63c3ed 144 }
jbindin 0:d9a14a63c3ed 145 }
jbindin 0:d9a14a63c3ed 146
jbindin 0:d9a14a63c3ed 147 //main function
jbindin 0:d9a14a63c3ed 148 main()
jbindin 0:d9a14a63c3ed 149 {
jbindin 0:d9a14a63c3ed 150 //attaching thereads to their functions
jbindin 0:d9a14a63c3ed 151 thread1 = new Thread(&producer);
jbindin 0:d9a14a63c3ed 152 thread2 = new Thread(&consumer);
jbindin 0:d9a14a63c3ed 153
jbindin 0:d9a14a63c3ed 154 while(1) {
jbindin 0:d9a14a63c3ed 155 wait(50000);
jbindin 0:d9a14a63c3ed 156 }
jbindin 0:d9a14a63c3ed 157 }
jbindin 0:d9a14a63c3ed 158 /*
jbindin 0:d9a14a63c3ed 159 calculats the moving average for the past 10 values. it also is responsible
jbindin 0:d9a14a63c3ed 160 for keeping the array ring buffered and subtracting the previous sample from
jbindin 0:d9a14a63c3ed 161 the current.
jbindin 0:d9a14a63c3ed 162 */
jbindin 0:d9a14a63c3ed 163 float movingAverage(float newSample, float previousSample, float rBuffer[])
jbindin 0:d9a14a63c3ed 164 {
jbindin 0:d9a14a63c3ed 165 float ave = 0.0;
jbindin 0:d9a14a63c3ed 166
jbindin 0:d9a14a63c3ed 167 // to calculate the change in acceleration
jbindin 0:d9a14a63c3ed 168 newSample = newSample - previousSample;
jbindin 0:d9a14a63c3ed 169
jbindin 0:d9a14a63c3ed 170 //move up every value in the array
jbindin 0:d9a14a63c3ed 171 for(int i = (COUNTMAX-1); i > 0; i--) {
jbindin 0:d9a14a63c3ed 172 rBuffer[i] = rBuffer[i-1];
jbindin 0:d9a14a63c3ed 173 }
jbindin 0:d9a14a63c3ed 174
jbindin 0:d9a14a63c3ed 175 //add new value
jbindin 0:d9a14a63c3ed 176 rBuffer[0] = newSample;
jbindin 0:d9a14a63c3ed 177
jbindin 0:d9a14a63c3ed 178 //summing every value in the array
jbindin 0:d9a14a63c3ed 179 for(int i = 0; i < COUNTMAX; i++) {
jbindin 0:d9a14a63c3ed 180 ave = ave + rBuffer[i];
jbindin 0:d9a14a63c3ed 181 }
jbindin 0:d9a14a63c3ed 182
jbindin 0:d9a14a63c3ed 183 //divide the sum by 10 to work out the mean
jbindin 0:d9a14a63c3ed 184 ave = ave / (float)COUNTMAX;
jbindin 0:d9a14a63c3ed 185
jbindin 0:d9a14a63c3ed 186 //return the mean value
jbindin 0:d9a14a63c3ed 187 return ave;
jbindin 0:d9a14a63c3ed 188 }
jbindin 0:d9a14a63c3ed 189
jbindin 0:d9a14a63c3ed 190 /*
jbindin 0:d9a14a63c3ed 191 used to work out the final average that is to be ouputted every second
jbindin 0:d9a14a63c3ed 192 */
jbindin 0:d9a14a63c3ed 193 float average(float values[10])
jbindin 0:d9a14a63c3ed 194 {
jbindin 0:d9a14a63c3ed 195 float sum = 0;
jbindin 0:d9a14a63c3ed 196 float result = 0;
jbindin 0:d9a14a63c3ed 197 for(int i = 0; i < 10; i++)
jbindin 0:d9a14a63c3ed 198 {
jbindin 0:d9a14a63c3ed 199 sum = values[i] + sum;
jbindin 0:d9a14a63c3ed 200 }
jbindin 0:d9a14a63c3ed 201 result = sum / 10;
jbindin 0:d9a14a63c3ed 202
jbindin 0:d9a14a63c3ed 203 //returns the final mean value
jbindin 0:d9a14a63c3ed 204 return result;
jbindin 0:d9a14a63c3ed 205
jbindin 0:d9a14a63c3ed 206 }
jbindin 0:d9a14a63c3ed 207
jbindin 0:d9a14a63c3ed 208
jbindin 0:d9a14a63c3ed 209 // please note an attempt to use a Ticker as an interupt was used to make the
jbindin 0:d9a14a63c3ed 210 // samples more accurate however the command "accelerometer->get_x_axes(accVals);"
jbindin 0:d9a14a63c3ed 211 // only returned 0 so two threads were used insted.