Lab 3 and 4 - University of Calgarypeople.ucalgary.ca/~smithmr/2017webs/encm511_17/... · Lab 3 and...
Transcript of Lab 3 and 4 - University of Calgarypeople.ucalgary.ca/~smithmr/2017webs/encm511_17/... · Lab 3 and...
Lab 3 and 4B02 / 04 – Tuesday 31st October Reading week – Tuesday 7th November – I will be in Labs but no TAsB01 / 03 – Tuesday 14th NovemberB02/ 04 – Tuesday 21st NovemberB01 / 03 – Tuesday 28th NovemberB02 / 04 – Tuesday 5th November
Lab 4 Part 1 is a quick “Set up the LCD and a few wires, press a few buttons (in the exactly correct order) and leave the Lab”.It is demoed by your group outside the Lab period in under an hour. I will probably do this the 27th November 8:00 tutorial for B01 / B03 and after the class on Friday 1st December for B02 / B04.Can be done at other times, say after 4 pm during a Lab.
Lab 3 and Lab 4
• You now have enough knowledge to handle the remaining Labs• So I am going to allow you to work at your own speed
• Two Choices for getting full marks on the Labs. I will get you to confirm by letter in D2L drop box which is your team’s choice by 1stDecember. • Lab 0, 1, 2, 3, 4 OR since Lab 3 is mainly Lab 2 with a twist, and Lab 4 is different
• Lab 0, 1, 2 and 4, and understand Lab 3 ideas• Reports (mainly upload code and screen shots / video) for Lab 3 / 4 or just Lab 4 will be due before the end of term
• All demos need to be completed no later than last Lab period
Temperature Gauge and BioSensor
Ideas for Lab 3
Just using the threads from Lab 2
What are the Lab 2 Threads?Your threads will be something like this• StoreBuffer_Thread( ) – You give it a signal – and it will store something in an buffer• I am now using the hardware term – BUFFER – to show that the array has some specific purpose – storing things that will continually change
• ReadBuffer_Thread( ) ‐‐ You give it a signal – and it will read something from an buffer
• ReadSwitchValue_Thread( ) – This reads the switches and stores the values in a global volatile variable currentSwitchBuffer (bits 3:0) that other threads can read
• WriteLEDValue_Thread( ) – Other threads put values into a global volatile variable nextLEDDisplayBuffer (bits 5:0) and this thread sends the value to the LEDs
• Timing_Thread( ) – Which can measure how long a GPIO bit is high and store it in a global variable timeBitHigh, or measure how long a GPIO bit is low timeBitHigh.
Using the Keep it simple principleNew words – UnitTest ‐‐ AcceptanceTest• Break project into small parts and worry about 1 part at a time• I have define the exact task each thread does• I have each task responsible for one – totally isolated – thing.
• This means I have to worry only about one thing at a time• Also – since each thing is doing just one thing – then I can easily test it “outside of uTTCOSg” with its interrupts and inside the testing framework E_Unit is it is not behaving
• Test code might look like this – Hint for Quiz 3 and Final• Test ( ) { // Same idea as first part of Lab 0 where displaying driving the car
InitializeThings( )Call_Thread( );CheckResult( ); Call_Thread( );CheckResult( );
}• Get each part to work on its own (Unit Test) before merging it with other parts (Acceptance Test)
You have a TMP03 thermal sensor in your lab kit• If you put your finger on the sensor, it will measure your finger’s temperature
• It sends out the temperature information in the form of code 1 and 0 values – PWM – digital pulse width modulated signal
• You put this signal into SW4 where it will automatically be sensed by your ReadSwitchValue_Thread( ) ‐‐ NO NEW CODE
• If you measure T1 ‐‐ the width of the high pulse (leading edge to trailing edge) and
• Measure T2 ‐‐ the width of the low pulse (trailing edge to leading edge) • You can (in C++) calculate the temperature in 3 math operation
Temperature = B ‐ A * T1 / T2• where A and B are on the TMP03 data sheet. Look for the Analog Devices start menu and you will see a folder about sensors
Thermal Sensor Project – Lab 3I imagine this in two parts• Temperature sensor part –– every 1 / 2 second
• To calculate the current temperature (in C) and place in global variable currentTemperature
• Takes the temperature from ½ second ago into global variable oldTemperature_1
• Takes the temperature from 1 second ago into global variable oldTemperature_2
• Temperature display part – every 1 / 2 second• Displays the temperature in one of two ways• The actual temperature• Bio‐sensor temperature
Part 2 ‐‐ Plan (not code) the obvious bits firstTemperature display part – every 1 / 2 second• If SW1 is pressed – then display actual temperature
• Action – move currentTemperature to nextLEDDisplayBuffer• Lab 4 action ‐‐move currentTemperature to the LCD display using industry SPI interface
• If SW1 is not pressed – then display biosensor temperature (default mode)• Bio sensors are intended to calm you down but taking your thoughts away from every day life• Code a desiredTemperature (say 27 C or 30 or ? ) above room temperature (24C)• Start (calmly) thinking about warming your fingers – the blood flow will change and the currentTemperature will increase
• If the current temperature is equal to the desired temperature Make the LED display steady unchanging
• If the current temperature is rising then make the LED display look like it is moving up• If the current temperature is falling then make the LED display look like it is moving down• As the current temperature gets closer to desired temperature make the LED display brighter
• You may be the sort of bio‐sensor person who likes things to go dimmer – that’s okay, your design
Part 2 ‐‐ I can image that being done by
• A SW1 Thread that has two MAIN states• display actual temperature• biosensor temperature (default mode)
• The biosensor state has three states• Steady LED• UP moving LEDs• DOWN moving LEDS
• And the extra control• Brighter and Not brighter
Part 1A ‐‐ Temperature sensor partNew words – “IN‐LINE”, “DOUBLE BUFFERING”• The TMP03 sensor sends in a stream of 1’s and 0’s and the width between the 1’s and 0’s tells you the temperature
• I can imagine SW4_TimingThread( ) that 1. measures the time between a leading edge and a trailing edge and stores it in a
firstT1Buffer using a version of the StoreArray_Thread( ) PERHAPS an “in‐line” version coded directly inside SW4_TimingThread(
2. measures the time between a trailing edge and a leading edge and stores it in a firstT2Buffer
3. When it has 10 values stored – it starts a TemperatureCalculateThread (RUN ONCE) and tells it to calculate the temperature from firstT1Buffer and firstT2Buffer
4. And then starts “DOUBLE BUFFERING” by allowing the other thread to calculate from firstBuffer while you fill secondBuffer
5. measures the time between a leading edge and a trailing edge and stores it in a secondT1Buffer
6. measures the time between a trailing edge and a leading edge and stores it in a secondT2Buffer
7. When it has 10 values stored – it starts a TemperatureCalculateThread (RUN ONCE) and tells it to calculate the temperature from secondT1Buffer and secondT2Buffer
8. Goes back to state 1 and use the firstBuffer again while the temperature calculation uses the secondBuffer
Part 1B ‐‐ Temperature sensor partNew words – “DOUBLE BUFFERING” “OPTIMIZE”• TemperatureCalculateThread• REQUIREMENT FOR DOUBLE BUFFERING • This task MUST complete the calculation on one buffer of the double buffer BEFORE the other thread fills the other buffer 1. This means there is “plenty of time” but this code must still be reasonably
fast as it is the longest thread to run and might block the other threads.2. Perhaps – use the IDE to “automatically” OPTIMIZE this thread for speed.
This is just one click of a button 3. Remember when optimizing, make sure all global variables EVERYWHERE
are defined volatile or extern volatile
Part 1B ‐‐ Temperature sensor partNew words – “DOUBLE BUFFERING” “OPTIMIZE”• TemperatureCalculateThread
1. Using a version of the StoreArray_Thread( ) or an “in‐line” version coded directly inside SW4_TimingThread( )
2. Examine all T1’s and T2’s to check if valid.3. Throw away the noisy ones4. Take the average of the good ones – Calculate the temperature
• One not‐so‐great way of doing that – okay to test out the idea• Take the values in the buffer and arrange from highest to lowest• Throw away the highest and lowest which are assumed to be noisy• Average what is left – calculate the temperature
• Know a better way even if not used in this lab• Calculate average and standard deviation (sd) of values in the buffer• Throw away values that are more than 1 sd from average (you will only keep 68% of the data on average) – or 2 sd from average (keep 96%)
• Calculate a new average to use with temperature
Lab 3• Uses all the threads from Lab 1 and 2 with ideas from Lab 0• Only trouble is
• The accuracy for measuring is insufficient. • uTTCOSg probably has a TIC of 10 ms and the TMP03 sends signals out at around 30 Hz which means the edges changes at 60 Hz – ever 62.5 ms
• This means you can measure the width of T1 and T2 with an accuracy of 20 ms – which means each width is accurate at best 33%
• The full math calculation is at the end of the slide show that the error in measuring the temperature is 200 * 66%
So what to change
• The Blackfin is DESIGNED to measure PWM signals using one of three timer peripherals – check the sheet TIMER0, TIMER1 and TIMER2
• Check your data sheet to examine the control bits for TIMER0, TIMER1 and TIMER2
• These are like the WATER, LED and HEAT controls from assignment 1, all three are activated by one control register
• Unlike the CORE‐TIMER, these TIMERX have a connection to the outside world
• Look at the logic lab to see the timer inputs – just above PF11 and just below PF8
• We will cover initializing timers in other lectures
Change 1 ‐‐ needed for accuracyNEW WORD – BACKGROUND TASK• We set up a TIMERX to be in capture mode – check your reference sheet• We start it, after initializing uTTCOSg, but before starting the uTTCOSscheduler
• TimerX runs as a background task. • It can capture the length of time when the input signal is high into one of its registers
• It captures the length of time between two leading edges of the input signal into another register ‐‐ PERIOD
• It then sets a ready bit – called an interrupt bit ‐‐ different from the GPIO interrupt bits of PF8 – PF11
• Since we ARE NOT ENABLING TIMER interrupts, the ready (interrupt) bit just stays one AND DOES NOT CAUSE AN INTERRUPT
• The TIMERX then starts to measure the next “high time” and “period time”• If another task does not read the ready bit (and set it to zero), then TIMERX probably sets an error bit to warn the system there is a problem
Part 1A ‐‐ Temperature sensor partNew words – “IN‐LINE”, “DOUBLE BUFFERING”• The TMP03 sensor sends in a stream of 1’s and 0’s and the width between the 1’s and 0’s tells you the temperature
• I can imagine SW4_TimingThread( ) TimerX_Thread( ) 1. This runs very slowly – once every 1 / 30 second is speed of PWM signals2. If the TIMERX ready signal is not set ‐‐ do nothing – exit from thread3. Otherwise – read TIMERX registers and put them firstT1Buffer and firstT2Buffer
VERY IMPORTANT – CLEAR THE TIMERX READY BIT4. When it has 10 values stored – it starts a TemperatureCalculateThread (RUN ONCE) and
tells it to calculate the temperature from firstT1Buffer and firstT2Buffer5. And then starts “DOUBLE BUFFERING” by allowing the other thread to calculate from
firstBuffer while you fill secondBuffer6. If the TIMERX ready signal is not set ‐‐ do nothing – exit from thread7. Otherwise – read TIMERX registers and put them secondT1Buffer and secondT2Buffer
VERY IMPORTANT – CLEAR THE TIMERX READY BIT8. When it has 10 values stored – it starts a TemperatureCalculateThread (RUN ONCE) and
tells it to calculate the temperature from secondT1Buffer and secondT2Buffer9. Goes back to state 1 and use the firstBuffer again while the temperature calculation uses
the secondBuffer
Part 1 ‐‐ How to calculate measurement accuracy from timing measurements
Temp = B ‐ A * (T1) / (T2) Let T1 be wrong by amount dT1 and T2 wrong by dT2
making T wrong by dTempDO partial differentiationdTemp = ‐ A * dT1 / T2 + A * T1 * dT2 / (T2 ^ 2)
No calculus way to calculate measurement accuracy from timing measurements
Temp = B ‐ A * (T1) / (T2)Let T1 be wrong by amount dT1 and T2 wrong by dT2
making T wrong by dTempTemp + dTemp = B ‐ A * (T1 + dT1) / (T2 + dT2)Rearrange equation ready for Taylor expansion of 1 / (1+ dX)Temp + dTemp = B ‐ A * (T1 + dT1) / { T2 (1 + dT2 / T2)
= B ‐ A * (T1 + dT1) / T2} * (1 ‐ dT2 / T2) = B ‐ A * T1 / T2 ‐ A * dT1 / T2 + A T1 dT2 / T2 + O(dT1 * dT2)
Now subtract Temp = B ‐ A * (T1) / (T2) from both sides and ignore small stuff
dTemp = ‐ A * dT1 / T2 + A T1 dT2 / T2^2
Part 1 ‐‐ How to calculate measurement accuracy from timing measurements• dTemp = ‐ A * dT1 / T2 + A T1 dT2 / (T2 ^ 2)• Multiply both sides by T2• T2 * dTemp = ‐ A * dT1 + A T1 dT2 / T2• Divide both sides by A, then by T1• T2 * dTemp / T1 / A = ‐ dT1 / T1 +‐ dT2 / T2• Rearrange • dTemp /{ ( (A * T1) / T2)} = ‐ dT1 / T1 + dT2 / T2• and make WORSE case with dT1 negative (too small)• dTemp /{B ‐ Temp} = dT1 / T1 + dT2 / T2
Part 1 ‐‐ How to calculate measurement accuracy from timing measurements• dTemp /{B ‐ Temp} = dT1 / T1 + dT2 / T2• dTemp = {B ‐ Temp} * { dT1 / T1 + dT2 / T2}
• Let the temperature be 20 degrees• Let there be 1% error in T1 and T2• = 1 / 60 / 100 s inaccuracy in T1 and T2 signals of time 1 /60 s• dTemp = ‐ 215 * 2% = 400% error• So – small error in T1 and T2 causes large error in Temperature