SOFT261_CW
Dependencies: X_NUCLEO_IKS01A1 mbed
main.cpp@0:d9a14a63c3ed, 2018-08-15 (annotated)
- Committer:
- jbindin
- Date:
- Wed Aug 15 15:04:32 2018 +0000
- Revision:
- 0:d9a14a63c3ed
snntst
Who changed what in which revision?
User | Revision | Line number | New 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. |