
{"id":821,"date":"2019-10-10T08:58:33","date_gmt":"2019-10-10T08:58:33","guid":{"rendered":"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/?page_id=821"},"modified":"2019-10-24T11:07:54","modified_gmt":"2019-10-24T11:07:54","slug":"analogue-interfacing-real-time-data-conversion","status":"publish","type":"page","link":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/microcontrollers\/mbed-os-2\/courses\/level-5-embedded-and-real-time-systems\/analogue-interfacing-real-time-data-conversion\/","title":{"rendered":"Analogue Interfacing &#8211; Real Time Data Conversion"},"content":{"rendered":"<p><a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/microcontrollers\/mbed-os-2\/courses\/level-5-embedded-and-real-time-systems\/\">Table of Contents<\/a><\/p>\n<hr \/>\n<p>In this section we look at interfacing with the analogue world using mbed. You will use a simple <a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/potentiometer-glossary-entry\/\">potentiometer<\/a> to generate analogue voltages, and measure that voltage using an <a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/analogue-to-digital-converter-adc-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">Analogue to Digital Converter (ADC)<\/a> to perform sampling. Analogue signals suffer problems with noise and uncertainty. Analogue filters are used to prevent a phenomena known as aliasing when sampling a signal. For simple threshold detection, <a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/hysteresis-and-the-schmitt-trigger-glossary-entry\/\">hysteresis<\/a> is introduced to manage signal noise and avoid output jitter.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-830\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/potentiometer.png\" alt=\"Image of a potentiometer\" width=\"175\" height=\"247\" \/><\/p>\n<p>We then look at digital to analogue conversion, using both pulse-width modulation (crude, but useful for motor speed control) and a Digital-to-Analogue Converter (<a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/digital-to-analogue-converter-dac-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">DAC<\/a>) for more precise applications.<\/p>\n<p>The mechanisms for conversion in mbed are very simple.<\/p>\n<blockquote><p>What is more important are the techniques for determining an accurate sampling rate and reducing aliasing noise.<\/p><\/blockquote>\n<p>For accurate sampling, we will use the <code>Ticker<\/code> component to generate interrupts driven by a hardware timer.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-831\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-1.png\" alt=\"\" width=\"599\" height=\"210\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-1.png 725w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-1-300x105.png 300w\" sizes=\"auto, (max-width: 599px) 100vw, 599px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-832\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/pot-as-analogue-input.png\" alt=\"\" width=\"300\" height=\"291\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/pot-as-analogue-input.png 443w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/pot-as-analogue-input-300x291.png 300w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-833\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-1b.png\" alt=\"\" width=\"600\" height=\"453\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-1b.png 935w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-1b-300x227.png 300w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-1b-768x580.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>For a simple threshold detection task such as this, we might can use \u201c<a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/hysteresis-and-the-schmitt-trigger-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">hysteresis<\/a>\u201d to address the problem of noise.<\/p>\n<h2>Hysteresis<\/h2>\n<p>This is a technique for reducing (and sometimes effectively eliminating) the effects of noise when detecting if a signal crosses a threshold. Consider the figure below. This shows an analogue signal <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-0dc782a6afdc3bd89c6b52fd82f79ba1_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#86;&#95;&#123;&#105;&#110;&#125;&#40;&#116;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"43\" style=\"vertical-align: -5px;\"\/> varying with respect to time <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-6b97bb0f65c75b6cc0fba1868749478d_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#116;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"6\" style=\"vertical-align: 0px;\"\/>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-834\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/hysteresis-signal.png\" alt=\"\" width=\"600\" height=\"339\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/hysteresis-signal.png 717w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/hysteresis-signal-300x169.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Consider the example of the blue waveform in the figure. The signal is below the lower threshold at <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-82471c1f597280d17ec570a21a5adb05_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#116;&#61;&#48;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"39\" style=\"vertical-align: 0px;\"\/>, so the output is GREEN. <a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/hysteresis-and-the-schmitt-trigger-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">Hysteresis<\/a> works as follows:<\/p>\n<ul>\n<li>In the <strong>GREEN<\/strong> (lower) state, the system will only switch to the <strong>RED<\/strong> state when the signal crosses above the <strong>upper<\/strong> threshold of 1.98V.<\/li>\n<li>Once in the <strong>RED<\/strong> (upper) state, the system will now only switch to the <strong>GREEN<\/strong> state when the signal crosses below the <strong>lower<\/strong> threshold of 1.32V.<\/li>\n<\/ul>\n<p class=\"p1\"><span class=\"s1\">As the signal rises above the upper threshold of 1.98V, the output state changes state to <strong>RED<\/strong>. Note that signal noise causes the signal to dip down below 1.98V shortly after, but that is ignored as it is still above the (revised) lower threshold. <\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Later, the signal drops below the lower threshold causing a state change. Again due to noise, the signal rises above the lower threshold but is once again ignored as it does not exceed the upper threshold.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">For this example, the noise margin is <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-49b2ab45a17b02f4aaed98b463d4587d_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#40;&#49;&#46;&#57;&#56;&#86;&#45;&#49;&#46;&#51;&#50;&#86;&#41;&#61;&#48;&#46;&#54;&#54;&#86;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"196\" style=\"vertical-align: -5px;\"\/><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">A device that employs this technique in this way is known as a Schmitt Trigger <a href=\"https:\/\/en.wikipedia.org\/wiki\/Schmitt_trigger\"><span class=\"s2\">https:\/\/en.wikipedia.org\/wiki\/Schmitt_trigger<\/span><\/a><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-836\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-3.png\" alt=\"\" width=\"600\" height=\"228\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-3.png 935w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-3-300x114.png 300w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-3-768x292.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-837\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-3-fsm.png\" alt=\"\" width=\"653\" height=\"333\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-3-fsm.png 653w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-1-3-fsm-300x153.png 300w\" sizes=\"auto, (max-width: 653px) 100vw, 653px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h3>Light Dependent Resistor (LDR)<\/h3>\n<p>In this task we are going to use a new passive component, the <a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/light-dependent-resistor-ldr-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">Light Dependent Resistor<\/a> (LDR).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-838\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/LDR-image.png\" alt=\"\" width=\"22\" height=\"48\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-839\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/LDR-schematic.png\" alt=\"\" width=\"45\" height=\"68\" \/><\/p>\n<p>The resistance decreases as light is increased**. In the dark, resistance in the order of <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-bedf32a5c64901a3b60d7bbe6a803f4f_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#77;&#32;&#92;&#79;&#109;&#101;&#103;&#97;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"31\" style=\"vertical-align: 0px;\"\/> can be achieved. In very bright light, a resistance in the order of 100s of are <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-ec0c546b6596f336d8e1d41bb064b951_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#79;&#109;&#101;&#103;&#97;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"12\" style=\"vertical-align: 0px;\"\/> typical.<\/p>\n<p>**Note &#8211; The resistance is also partly dependent on temperature, so these devices are not ideally suited to accurate measurement or instrumentation. <a href=\"https:\/\/en.wikipedia.org\/wiki\/Photoresistor\">https:\/\/en.wikipedia.org\/wiki\/Photoresistor<\/a><\/p>\n<p>Used in a potential divider circuit, a simple light-to-voltage can be created, as shown:<\/p>\n<figure id=\"attachment_840\" aria-describedby=\"caption-attachment-840\" style=\"width: 181px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-840 size-full\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/LDR-as-analogue-input.png\" alt=\"\" width=\"181\" height=\"193\" \/><figcaption id=\"caption-attachment-840\" class=\"wp-caption-text\">Light dependent resistor input. \u2028Connected to the analogue input A1<\/figcaption><\/figure>\n<h2>Sampling with a polling loop<\/h2>\n<p>I the next task you will sample the light level using a simple polling loop.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-841\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1.png\" alt=\"\" width=\"500\" height=\"532\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1.png 725w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1-282x300.png 282w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<pre class=\"lang:c++ decode:true\">#include \"mbed.h\"\r\n\r\n#define kRED    (1 &lt;&lt; 2)    \/\/4\r\n#define kYELLOW (1 &lt;&lt; 1)    \/\/2\r\n#define kGREEN  (1 &lt;&lt; 0)    \/\/1\r\n#define kALL (kRED | kYELLOW | kGREEN)\r\n\r\n\/\/Global objects\r\nBusOut binaryOutput(D5, D6, D7);\r\nDigitalIn SW1(D3);\r\nDigitalIn SW2(D4);\r\n\r\nAnalogIn POT_ADC_In(A0);\r\nAnalogIn LDD_ADC_In(A1);\r\nfloat fPOT, fLDR = 0.0;\r\n\r\n\/\/Main function\r\nint main() {\r\n   \r\n   while(1) {\r\n      \r\n      \/\/Read ADC\r\n      fPOT = POT_ADC_In;\r\n      fLDR = LDD_ADC_In;\r\n      \r\n      \/\/Write to terminal\r\n      printf(\"POT = %6.4f\\tLDR = %6.4f\\n\", fPOT, fLDR);\r\n      \r\n      if (fLDR &gt; fPOT) {\r\n         binaryOutput = 0;      \/\/Binary 000\r\n      } else {\r\n         binaryOutput = kALL;   \/\/Binary 111\r\n      }\r\n      \r\n      \/\/Wait\r\n      wait(0.1);\r\n      \r\n   } \/\/end while(1)\r\n} \/\/end main<\/pre>\n<p><strong>Note:<\/strong> In effect, you are using the POT to set the threshold for the light sensor.<\/p>\n<p>The time around the loop, and hence the sampling interval is dependant on the wait statement <strong>+ time to execute the loop body<\/strong>.<\/p>\n<p>The sampling rate is therefore not constant. The time between each sample read depends on the execution time of the code each time around the loop. This varies for a number of reasons:<\/p>\n<ul>\n<li>The conditional statements (if) causes branches in the code which take different times.<\/li>\n<li>Every time the code is modified, the time is likely to change.<\/li>\n<li>If the compiler \u201coptimisation settings\u201d are changed, or the compiler is updated, this will again impact on code execution time.<\/li>\n<\/ul>\n<h3>Some Perspective<\/h3>\n<p>If you are not concerned with a consistent sampling rate (measured in samples\/s or Hz), then the simplicity of the code above is in itself an advantage over other more complex approaches. The power efficiency is something that might need to be checked of course.<\/p>\n<p>There are many\u00a0<a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/digital-signal-processing-dsp-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">Digital Signal Processing<\/a>\u00a0(DSP) applications that do rely on samples being acquired at strictly even time intervals. <em>For such applications, the approach above is naive<\/em>.<\/p>\n<blockquote><p>The degree to which the sampling interval varies is known as jitter. We try and minimise jitter for DSP applications, although it can never be eliminated (even crystal clocks frequencies will have some variance).<\/p><\/blockquote>\n<p>One way to address achieve a low jitter is to use a timer <a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/interrupt-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">interrupt<\/a>.<\/p>\n<h2>Sampling with Interrupts<\/h2>\n<p>A technique used by nearly every microprocessor and micro-controller to cause a branch in execution upon the occurrence of a hardware or software event.<\/p>\n<p>There are two broad categories:<\/p>\n<p><strong>Hardware interrupt<\/strong> &#8211; whereby the code is forced to branch when a hardware device (e.g. serial interface, GPIO input, timer, ADC etc..) flags that an event has occurred.<\/p>\n<p><strong>Software interrupt<\/strong> &#8211; whereby the code is forced to branch when a software event occurs, such as a divide by zero or a trap instruction. It is still driven by hardware, but the code must be running for this to occur (and not in sleep mode).<\/p>\n<p>When an interrupt occurs, a few things typically occur:<\/p>\n<ul>\n<li>context save &#8211; whereby CPU registers are preserved, typically on the current function stack<\/li>\n<li>return address is preserved<\/li>\n<li>the execution <strong>automatically<\/strong> branches to a specified function, known as an \u201c<a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/interrupt-glossary-entry\/\" target=\"_blank\" rel=\"noopener\"><strong>Interrupt Service Routine<\/strong><\/a>\u201d (ISR).<\/li>\n<li>upon completion, the return address is reinstated and the registers are restored, (as if nothing had occurred).<\/li>\n<\/ul>\n<p>The ISR may well have modified some memory, or interacted with the state of the hardware. Such effects are sometimes known as \u201c<strong>side effects<\/strong>\u201d. The programmer has to be very careful not to cause data corruption as a consequence.<\/p>\n<p>As you may already know, interrupts are commonly used to achieve a timely response to external events. For example:<\/p>\n<ul>\n<li>when a timer reaches its target value, a branch is forced so that a function executes at precise intervals. This is sometimes used in sampling.<\/li>\n<li>when a serial interface receives some data, an interrupt is forces the system to branch and read the data (and prevent data loss).<\/li>\n<li>if power begins to fail, an on-chip \u201cbrown-out\u201d detection can generate an interrupt to put the system in a safe state before shutting down (assuming there is enough time to react of course).<\/li>\n<\/ul>\n<p><strong>Nesting<\/strong><\/p>\n<p>Some devices allow interrupts to interrupt (aka preempt) each other. They typically use a numerical priority scheme to determine which interrupts take precedence. It can be quite challenging to design real-time systems using such as scheme.<\/p>\n<p><strong>Power Saving<\/strong><\/p>\n<p>The CMOS logic used to build modern micros only consumes power when it is switching state. When a CPU has nothing to do, simply cycling inside a loop is therefore wasteful of power, as is powering unused peripherals.<\/p>\n<p>Most micros can switch of peripherals that are not required (in the case of the ARM series of devices, the clocks are gated off to prevent them switching). Furthermore, most support idle modes, whereby the code execution logic is suspended in a low power state. It is only interrupts that can wake the CPU from the low power state to service a request. When all requests have been serviced, the CPU can return to an idle mode.<\/p>\n<p>It is probably worth pointing out that without interrupts, the CPU cannot escape idle mode.<\/p>\n<p><strong>Interrupt Safety<\/strong><\/p>\n<p>Many functions, including <code>printf<\/code> and <code>scanf<\/code>, <strong>are not safe to use within an interrupt service routine<\/strong>. Furthermore, many of the mbed objects are not interrupt safe either. Always check the documentation before using a function or class in an interrupt.<\/p>\n<p>As you can see, using interrupts can be challenging and great care is needed to avoid data corruption.<\/p>\n<h3>Using the Mbed-os <code>Ticker<\/code><\/h3>\n<p>In mbed, there is a component called a <code>Ticker<\/code>. This object maintains a hardware timer. When that timer reaches a certain value, an interrupt occurs, and branches to the function you specify. This function should take no arguments and return no data. For example:<\/p>\n<pre class=\"lang:c++ decode:true \">void doISR() {\r\n   state ^= 1;\r\n}<\/pre>\n<p>It is probably best to give an example to explain this.<\/p>\n<pre class=\"lang:c++ decode:true\">#include \"mbed.h\"\r\nDigitalOut myled(LED1);\r\nTicker t;\r\nstatic int state = 0;\r\nvoid doISR();\r\n\r\nint main() {\r\n   t.attach(doISR, 2);\r\n   myled = 0;\r\n   \r\n   while(1) {\r\n\r\n      sleep();    \/\/At is says\r\n     \r\n      \/\/At this point, the ISR has run\r\n      myled = state;\r\n      \r\n      if (state == 0) {\r\n         printf(\"LED OFF\\n\");\r\n      } else {\r\n         printf(\"LED ON\\n\");\r\n      }\r\n      wait_us(9000);  \/\/Give time for printf to finish!\r\n   }\r\n}\r\n\r\nvoid doISR() {\r\n   state ^= 1;  \/\/TOGGLE\r\n}<\/pre>\n<p>First we create an instance of the Ticker object<\/p>\n<p><code>Ticker t;<\/code><\/p>\n<p>Now we specify what function it shall call, and how often.<\/p>\n<p><code>t.attach(doISR, 2);<\/code><\/p>\n<p>The first parameter is the name of the function. In fact, this is actually the address of the function in program memory, but that is a detail right now. Sometimes you see it written like this:<\/p>\n<p><code>t.attach(&amp;doISR, 2);<\/code><\/p>\n<p>This example will cause the function <code>doISR<\/code>\u00a0to run <strong>every<\/strong> 2 seconds (assuming another interrupt of equal or higher priority is not already running). The <code>Ticker<\/code> does some \u201cC++ magic\u201d and is said to \u201cencapsulate\u201d a hardware timer. C++ is covered in level 6. If you don\u2019t understand this, don\u2019t worry.<\/p>\n<p><strong>Note:\u00a0<\/strong>The first parameter is an example of a function pointer. The prefix &amp; means \u201caddress of\u201d. This is actually optional for function pointers.\u00a0The interval between interrupts is specified by the second parameter (in seconds).<\/p>\n<p>What might surprise you is the first statement in the while loop, which is:<\/p>\n<p><code>sleep();<\/code><\/p>\n<p>This does what it says: it puts the CPU into a sleeping state, sometimes known as <strong>idle mode<\/strong>. During this state, the CPU is idle but the hardware timer is still running. The hardware timer is a separate piece of electronics inside the micro-controller which genuinely runs in parallel with the CPU (you might say this is the most genuine form of multi-tasking).<\/p>\n<p>When 2 seconds have elapsed, the CPU is woken up and the <code>doISR<\/code> function is called for you (by the NVIC hardware).\u00a0All this function does is toggle a variable between \u20280 and 1 as follows:<\/p>\n<pre class=\"lang:c++ decode:true \">void doISR() {\r\n   \/\/Toggle 0 to 1, or 1 to 0\r\n   state ^= 1;\r\n}<\/pre>\n<p>The code in the while loop can then resume beyond the <code>sleep()<\/code> function, which is to update the LED output and write to the terminal.<\/p>\n<pre class=\"lang:c++ decode:true\">myled = state;\r\n      \r\nif (state == 0) {\r\n   printf(\"LED OFF\\n\");\r\n} else {\r\n   printf(\"LED ON\\n\");\r\n}\r\n\r\n\/\/Give time for printf to finish!\r\nwait_us(9000);<\/pre>\n<p>When everything is done, the code loops and the CPU returns to the sleep mode, until the ticker wakes it again. This saves a considerable amount of power.<\/p>\n<p><strong>Question:<\/strong> Note that <code>printf<\/code> is in main, and not in the ISR. Why not just put all the code in the ISR?<\/p>\n<p><strong>Note<\/strong> that <code>printf<\/code>\u00a0is also followed by a delay of 9ms. This is because <code>printf<\/code>\u00a0communicates with a serial interface, and the serial interface uses interrupts. The delay is intended to wait until all characters are sent. Without this delay, the CPU would be brought out of sleep by the serial port interrupts!<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-bd729b168bcf6b9b2058b9e4b5a4450a_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#66;&#97;&#117;&#100;&#32;&#61;&#32;&#57;&#54;&#48;&#48;&#32;&#98;&#112;&#115;&#32;&#61;&#32;&#49;&#50;&#48;&#48;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"187\" style=\"vertical-align: -4px;\"\/> Bytes\/second. Therefore each character takes\u00a0<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-5f6f225ace6992a584d3c0c91fab8a36_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#49;&#50;&#48;&#48;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"22\" width=\"28\" style=\"vertical-align: -6px;\"\/> seconds to complete.<\/p>\n<p>Allowing for 10 characters, we need to wait for 9ms until all the characters have been send and the serial interrupts have completed. This assumes the device at the other end is ready to receive the data of course.<\/p>\n<h3>Key Observation<\/h3>\n<p>The interrupt service routine runs once every 2 seconds. The frequency is fixed, and is independent of the code in the main function, compiler settings etc..<\/p>\n<p>We can say that the ISR is \u201cdeterministic\u201d (fully predictable in time).<\/p>\n<p>This example is a rather special case. We have designed this system such that the CPU is always in an idle mode when the interrupt occurs. Therefore, we know where the program has got to when the interrupt occurs (sleep statement).<\/p>\n<blockquote><p>Please note that this is not generally the case with interrupts, so do not extend this pattern into other applications.<\/p><\/blockquote>\n<p><strong>Question:<\/strong> Why would this software pattern not be appropriate for a system with a single interrupt driven by a push switch?<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-845\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1b.png\" alt=\"\" width=\"600\" height=\"279\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1b.png 935w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1b-300x140.png 300w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1b-768x357.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>You should see a very regular and stable waveform as shown below.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-846\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1b-output.png\" alt=\"\" width=\"717\" height=\"403\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1b-output.png 717w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-2-1b-output-300x169.png 300w\" sizes=\"auto, (max-width: 717px) 100vw, 717px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h2>Accurate Sampling with a Timer Interrupt<\/h2>\n<p>We are using the Mbed-os framework (set of C++ objects) to perform rapid development of embedded software. We will now sample an analogue input using an on-chip Analogue to Digital Converter (ADC) and the <code>AnalogIn<\/code> component. Note the the default behaviour is to return a value a fractional value of type <code>float<\/code>, scaled between 0.0 and 1.0. In this task, we read the raw integer value.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-848\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-4-2.png\" alt=\"\" width=\"600\" height=\"284\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-4-2.png 935w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-4-2-300x142.png 300w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-4-4-2-768x364.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<pre class=\"lang:c++ decode:true\">#include \"mbed.h\"\r\n\r\n\/\/Function prototype\r\nvoid doSample1Hz();\r\n\r\n\/\/Global objects\r\nSerial pc(USBTX, USBRX);\r\nAnalogIn POT_ADC_In(A0);\r\nDigitalOut led(LED1);\r\n\r\n\/\/Shared variables\r\nvolatile static unsigned short sample16 = 0;\r\n\r\n\/\/The ticker, used to sample data at a fixed rate\r\nTicker t;\r\n\r\n\/\/Main function\r\nint main()\r\n{\r\n    \/\/Set baud rate to 115200\r\n    pc.baud(115200);\r\n\r\n    \/\/Set up the ticker - 100Hz\r\n    t.attach(doSample1Hz, 1.0);\r\n\r\n    while(1) {\r\n\r\n        \/\/Sleep\r\n        sleep();\r\n        \r\n        \/\/READ ADC as an unsigned integer.\r\n        \/\/Shift right 4 bits (this is a 12bit ADC) &amp; store in static global variable\r\n        sample16 = POT_ADC_In.read_u16() &gt;&gt; 4;\r\n        \r\n        \/\/Display the sample in HEX\r\n        pc.printf(\"ADC Value: %X\\n\", sample16);\r\n        \/\/Wait for 20 characters to clear \r\n        wait(0.0014);\r\n \r\n    } \/\/end while(1)\r\n} \/\/end main\r\n\r\n\/\/ISR for the ticker - simply there to perform sampling\r\nvoid doSample1Hz()\r\n{\r\n    \/\/Toggle on board led\r\n    led = !led;\r\n}\r\n\r\n<\/pre>\n<p>The sampling is performed by the line:<\/p>\n<p><code>sample16 = POT_ADC_In.read_u16() &gt;&gt; 4;<\/code><\/p>\n<p>The member function <code>read_u16()<\/code>\u00a0returns a 16 bit integer, high-bit aligned. The device we are using is 12 bit ADC, so the result always has four zero in the least significant bit positions. This is why the result is shifted right 4 bits.<\/p>\n<p><strong>Important Notes:<\/strong><\/p>\n<p>This example illustrates an important design pattern which works (only) for very simple single-interrupt problems.<\/p>\n<ul>\n<li>The main function is first allowed to sleep (saving power)<\/li>\n<li>When the timer hits its target value, the CPU is woken and execution branches to the ISR\n<ul>\n<li><em>It is assumed the timer interrupt is the ONLY interrupt that can fire during the sleep state<\/em><\/li>\n<li>The ISR will then run the time critical code to completion &#8211; this is typically kept as short as possible.<\/li>\n<\/ul>\n<\/li>\n<li>When the ISR exits, the main function is then allowed to resume, until it loops and sleeps again.<\/li>\n<li>Note once again the delay after the <code>printf<\/code>\u00a0statements (allows time for all serial port interrupts to complete)<\/li>\n<\/ul>\n<p>Note how in this specific (and simple) example, main and the ISR are time <strong>synchronised<\/strong>. This is because of <code>sleep()<\/code> and the fact that we only have a single <strong>timer<\/strong> interrupt firing during the sleep phase.<\/p>\n<ul>\n<li style=\"text-align: left\">We avoid race conditions because we know the CPU is always sleeping when the interrupt occurs<\/li>\n<li style=\"text-align: left\">Therefore, there is no danger of preempting the reading of <code>sample16<\/code> in main<\/li>\n<\/ul>\n<p>In general, interrupts are asynchronous, so this pattern would not work. For example, using <code>InterruptIn<\/code>\u00a0to detect the press of a switch is asynchronous, and unlike a <code>Timer<\/code>, we can&#8217;t predict when it will happen or how frequently.<\/p>\n<p>In general, interrupt driven code can become much more complicated so we will need further strategies to avoid race conditions if our task is to scale.<\/p>\n<h2>Digital to Analogue Conversion (Analogue Output)<\/h2>\n<p>This is section, we look at ways to output analogue signals. For this we use two techniques:<\/p>\n<ul>\n<li><a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/pulse-width-modulation-pwm-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">Pulse Width Modulation<\/a> (PWM)<\/li>\n<li><a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/digital-to-analogue-converter-dac-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">Digital to Analogue Converter<\/a> (using the on-chip DAC).<\/li>\n<\/ul>\n<h3>Pulse Width Modulation (PWM)<\/h3>\n<p>Pulse Width Modulation or PWM is a simple technique used to control an output (mean DC) voltage. The technique is commonly used in control systems, including the control of DC motors, in part because it does not require the use of linear DC amplifiers. See the glossary entry on the\u00a0<a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/h-bridge-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">H-Bridge\u00a0<\/a>\u00a0if you want to know about DC motor control.<\/p>\n<p><strong>TASK<\/strong> &#8211; you should first familiarise yourself with <a href=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/glossary-2\/pulse-width-modulation-pwm-glossary-entry\/\" target=\"_blank\" rel=\"noopener\">the glossary entry on PWM<\/a><\/p>\n<p>PWM is simple to implement. We can use either a <code>Timer<\/code>\u00a0and a GPIO pin (<code>DigitalOut<\/code>) or one of the dedicated <code>PWM<\/code>\u00a0outputs (not all pins support PWM).<\/p>\n<h3>Pulse Width Modulation (PWM) with Timers<\/h3>\n<p>In this task we will implement PWM using a a simple timer (mbed <code>Ticker<\/code>).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-851\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-1.png\" alt=\"\" width=\"601\" height=\"167\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-1.png 935w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-1-300x83.png 300w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-1-768x214.png 768w\" sizes=\"auto, (max-width: 601px) 100vw, 601px\" \/><\/p>\n<pre class=\"lang:c++ decode:true\">#include \"mbed.h\"\r\n\r\n\/\/Time period\r\n#define T 0.001\r\n\r\n\/\/Mark-Space Ratio\r\n#define R 0.1\r\n\r\n\/\/Mark and Space times\r\n#define Tmark (R*T)\r\n#define Tspace ((1.0-R)*T)\r\n\r\nDigitalOut onboardRedLed(LED3);\r\nDigitalOut redLED(D7);\r\n\r\nint main() {\r\n   printf(\"\\nWelcome to ELEC143\\n\");\r\n   \r\n   while (1) {\r\n      redLED = 0; \/\/Space\r\n      onboardRedLed = 0;\r\n      wait(Tspace);\r\n      redLED = 1;\t\/\/Mark\r\n      onboardRedLed = 1;\r\n      wait(Tmark);\r\n   }\r\n}<\/pre>\n<p>Note that the <code>wait<\/code> function is blocking. We assume it does not use the CPU idle mode and simply spins, waiting for a timer to reach a specified value. This approach does not scale well as will be revealed in the next task 5.2.2.<\/p>\n<p><strong>Note<\/strong> &#8211; do not spend too much time on the next task as it\u2019s supposed to be \u201cawkward\u201d. It is intended to make a point! A solution is also available.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-852\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-2.png\" alt=\"\" width=\"600\" height=\"244\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-2.png 935w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-2-300x122.png 300w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-2-768x313.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>You may have noticed already that this is rather cumbersome. There are many ways to try and solve this problem. I have provided one solution that uses timer interrupts (although even this is not perfect).<\/p>\n<p>What you might find is that your solution does not \u201cscale\u201d beyond two LEDs. One of the fundamental problems here is that the wait statement is \u201cblocking\u201d (you cannot do anything else unless you use an interrupt).<\/p>\n<p>There are a number of elegant solutions. Timers are one possibility (as I have used), but you might want to reserve those timers for other tasks. I\u2019ve kept the interrupt routines as short as possible to avoid latency issues (in the event two overlap in time such that one has to wait for the other to finish).<\/p>\n<p>Luckily, PWM is a common requirement and this problem was recognised a long time ago, and this microcontroller comes with PWM controllers built in! These controllers have their own timers and logic to control the output, so all run independently in parallel.<\/p>\n<p><strong>Remember<\/strong>: a single core microcontroller can only really execute one instruction at a time. Any attempt at multitasking is always an illusion and often comes with compromises.<\/p>\n<p>Look at the code below to see how simple it is to use a PWM in mbed on this device.<\/p>\n<pre class=\"lang:c++ decode:true\">#include \"mbed.h\"\r\nDigitalOut led1(LED1);\r\nPwmOut pwm(D6);\r\n\r\nint main() {\r\n   pwm.period_us(10);\r\n   pwm = 0.5;\r\n   \r\n   while(1) {\r\n     wait(0.5);\r\n     led1=!led1;\r\n    }\r\n}<\/pre>\n<p class=\"p1\"><span class=\"s1\"><b>Task: <\/b><\/span><span class=\"s2\"><i>Use an oscilloscope to observe the signal on D6.<\/i><\/span><\/p>\n<p>This code is very simple. This is because we are using the <code>PwmOut<\/code>\u00a0type object to do all the timing in parallel to the CPU.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-853\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3.png\" alt=\"\" width=\"600\" height=\"209\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3.png 935w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3-300x104.png 300w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3-768x267.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>We are controlling the brightness because the PWM is switching too fast for our eyes to notice. It is not true Digital to Analogue Conversion however, but a simple way to deliver variable \u201caverage power\u201d to a load.<br \/>\nIf you don\u2019t have a DAC, we can get closer to true conversion by filtering the output.<\/p>\n<h2>Digital to Analogue Conversion with PWM<\/h2>\n<p>Consider the task of outputting a low frequency signal, for example:<\/p>\n<ul>\n<li>Constant voltage<\/li>\n<li>1Hz sine wave<\/li>\n<li>Slow ramp waveform<\/li>\n<\/ul>\n<p>Now consider the spectrum of a stationary PWM signal with period T. The repetition frequency <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-57c4669b4bf22bf51a7a7e2019422132_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#102;&#95;&#123;&#112;&#119;&#109;&#125;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#84;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"22\" width=\"74\" style=\"vertical-align: -6px;\"\/><\/p>\n<figure id=\"attachment_866\" aria-describedby=\"caption-attachment-866\" style=\"width: 600px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-866\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/pwm_frequencies.png\" alt=\"\" width=\"600\" height=\"319\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/pwm_frequencies.png 717w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/pwm_frequencies-300x159.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption id=\"caption-attachment-866\" class=\"wp-caption-text\">Frequency spectrum of a PWM signal<\/figcaption><\/figure>\n<p>We are only interested in the low frequency components <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-e5f1b26da64f8dcce8ea9209a5e0d53b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#48;&#32;&#92;&#108;&#101;&#113;&#32;&#102;&#32;&#92;&#108;&#101;&#113;&#32;&#102;&#123;&#112;&#119;&#109;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"114\" style=\"vertical-align: -4px;\"\/>.\u00a0From the signal spectrum, as long as <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-5e51914b41252e7d3cf00a6032542ebd_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#102;&#95;&#123;&#112;&#119;&#109;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"18\" width=\"38\" style=\"vertical-align: -6px;\"\/> is high enough, then a simple RC filter should be effective at removing the unwanted harmonics.<\/p>\n<p>The schematic for a RC low-pass filter is given below.<\/p>\n<figure id=\"attachment_867\" aria-describedby=\"caption-attachment-867\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-867 size-medium\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/RC-Filter-300x234.png\" alt=\"\" width=\"300\" height=\"234\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/RC-Filter-300x234.png 300w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/RC-Filter.png 556w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><figcaption id=\"caption-attachment-867\" class=\"wp-caption-text\">RC Low-Pass Filter<\/figcaption><\/figure>\n<p>You may recall the s-plane transfer function for this circuit:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-3476b76a00a2dbff3f0bbf497bd6aba0_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#86;&#95;&#123;&#111;&#117;&#116;&#125;&#40;&#115;&#41;&#61;&#86;&#95;&#123;&#105;&#110;&#125;&#40;&#115;&#41;&#32;&#92;&#99;&#100;&#111;&#116;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#115;&#67;&#82;&#43;&#49;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"38\" width=\"205\" style=\"vertical-align: -14px;\"\/><\/p>\n<p>Substituting <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-ba185c9a2af2e36ce24486809cd449f3_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#115;&#61;&#106;&#92;&#111;&#109;&#101;&#103;&#97;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"51\" style=\"vertical-align: -4px;\"\/> where <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-495606e467c054cf401e1ddb54ba7c18_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#106;&#61;&#92;&#115;&#113;&#114;&#116;&#123;&#45;&#49;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"71\" style=\"vertical-align: -4px;\"\/> and <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-5d666235870ff985d160d7a1275f6268_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#111;&#109;&#101;&#103;&#97;&#61;&#50;&#92;&#112;&#105;&#32;&#102;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"65\" style=\"vertical-align: -4px;\"\/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-477cdaa4a1d423928b1b8b0563940f2a_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#86;&#95;&#123;&#111;&#117;&#116;&#125;&#40;&#106;&#92;&#111;&#109;&#101;&#103;&#97;&#41;&#125;&#123;&#86;&#95;&#123;&#105;&#110;&#125;&#40;&#106;&#92;&#111;&#109;&#101;&#103;&#97;&#41;&#125;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#92;&#111;&#109;&#101;&#103;&#97;&#32;&#67;&#82;&#106;&#43;&#49;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"43\" width=\"171\" style=\"vertical-align: -17px;\"\/><\/p>\n<p>For the half-power point, <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-004241cd0caaf09c96809985a3547975_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#92;&#108;&#101;&#102;&#116;&#124;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#86;&#95;&#123;&#111;&#117;&#116;&#125;&#40;&#106;&#92;&#111;&#109;&#101;&#103;&#97;&#41;&#125;&#123;&#86;&#95;&#123;&#105;&#110;&#125;&#40;&#106;&#92;&#111;&#109;&#101;&#103;&#97;&#41;&#125;&#32;&#92;&#114;&#105;&#103;&#104;&#116;&#124;&#32;&#94;&#50;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#50;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"47\" width=\"120\" style=\"vertical-align: -17px;\"\/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-55f3fde474efffb3cde52521098d4996_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#92;&#108;&#101;&#102;&#116;&#124;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#92;&#111;&#109;&#101;&#103;&#97;&#32;&#67;&#82;&#106;&#43;&#49;&#125;&#32;&#92;&#114;&#105;&#103;&#104;&#116;&#124;&#32;&#94;&#50;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#50;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"47\" width=\"134\" style=\"vertical-align: -17px;\"\/><\/p>\n<p>Square-root both sides we get<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-5e61a83d5f8fb2422b8424cd0fac8528_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#32;&#92;&#108;&#101;&#102;&#116;&#124;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#92;&#111;&#109;&#101;&#103;&#97;&#32;&#67;&#82;&#106;&#43;&#49;&#125;&#32;&#92;&#114;&#105;&#103;&#104;&#116;&#124;&#32;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#50;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"44\" width=\"141\" style=\"vertical-align: -17px;\"\/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-9dd3fba9b3f975aa6d8d06d5787abd1a_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#92;&#115;&#113;&#114;&#116;&#123;&#40;&#92;&#111;&#109;&#101;&#103;&#97;&#32;&#67;&#82;&#41;&#94;&#50;&#43;&#49;&#94;&#50;&#125;&#61;&#92;&#115;&#113;&#114;&#116;&#123;&#50;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"22\" width=\"163\" style=\"vertical-align: -5px;\"\/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-5cdbdc93427db3b0abec28e1920667b3_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#92;&#111;&#109;&#101;&#103;&#97;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#67;&#82;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"36\" width=\"65\" style=\"vertical-align: -12px;\"\/> or <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-d0b5b902f1776414ce6c42d42228d149_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#102;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#50;&#32;&#92;&#112;&#105;&#32;&#67;&#82;&#125;&#72;&#122;\" title=\"Rendered by QuickLaTeX.com\" height=\"36\" width=\"110\" style=\"vertical-align: -12px;\"\/><\/p>\n<p>This is known as the &#8220;-3dB point&#8221;. The power (for a unit load) is defined as <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-6cc053a98929dbe380e4a2e389118de9_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#49;&#48;&#92;&#99;&#100;&#111;&#116;&#32;&#108;&#111;&#103;&#95;&#123;&#49;&#48;&#125;&#32;&#92;&#108;&#101;&#102;&#116;&#40;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#86;&#95;&#123;&#111;&#117;&#116;&#125;&#125;&#123;&#86;&#95;&#123;&#105;&#110;&#125;&#125;&#32;&#92;&#114;&#105;&#103;&#104;&#116;&#41;&#32;&#94;&#50;\" title=\"Rendered by QuickLaTeX.com\" height=\"47\" width=\"137\" style=\"vertical-align: -17px;\"\/> which can be written as\u00a0<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-66caa85bfc2e9e806acd7991631f3554_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#50;&#48;&#92;&#99;&#100;&#111;&#116;&#32;&#108;&#111;&#103;&#95;&#123;&#49;&#48;&#125;&#32;&#92;&#108;&#101;&#102;&#116;&#40;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#86;&#95;&#123;&#111;&#117;&#116;&#125;&#125;&#123;&#86;&#95;&#123;&#105;&#110;&#125;&#125;&#32;&#92;&#114;&#105;&#103;&#104;&#116;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"43\" width=\"128\" style=\"vertical-align: -17px;\"\/><\/p>\n<p>For half RMS power,<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/ql-cache\/quicklatex.com-399bb1c7e716c45baee047a03536ca1e_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#32;&#50;&#48;&#92;&#99;&#100;&#111;&#116;&#32;&#108;&#111;&#103;&#95;&#123;&#49;&#48;&#125;&#32;&#92;&#108;&#101;&#102;&#116;&#40;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#50;&#125;&#125;&#32;&#92;&#114;&#105;&#103;&#104;&#116;&#41;&#32;&#92;&#97;&#112;&#112;&#114;&#111;&#120;&#32;&#45;&#51;&#46;&#48;&#49;&#100;&#66;\" title=\"Rendered by QuickLaTeX.com\" height=\"43\" width=\"217\" style=\"vertical-align: -17px;\"\/><\/p>\n<h3>Filter Design<\/h3>\n<p>A single RC filter will roll off -20dB each time the frequency increased by a factor of 10 (known as a decade).<\/p>\n<figure id=\"attachment_868\" aria-describedby=\"caption-attachment-868\" style=\"width: 600px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-868\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/anti-alias-RCfilter-spec.jpg\" alt=\"\" width=\"600\" height=\"317\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/anti-alias-RCfilter-spec.jpg 717w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/anti-alias-RCfilter-spec-300x159.jpg 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption id=\"caption-attachment-868\" class=\"wp-caption-text\">The frequency characteristic of low-pass filter for removing higher harmonics in a PWM signal<\/figcaption><\/figure>\n<p>Consider the figure above. If you choose the -3dB point to be 10Hz, then the gain will be (approximately) as follows:<\/p>\n<table style=\"border-collapse: collapse;border: 1px solid black\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<th>Frequency (Hz)<\/th>\n<th>Gain (dB)<\/th>\n<\/tr>\n<tr>\n<td>10<\/td>\n<td>-3<\/td>\n<\/tr>\n<tr>\n<td>100<\/td>\n<td>-23<\/td>\n<\/tr>\n<tr>\n<td>1k<\/td>\n<td>-43<\/td>\n<\/tr>\n<tr>\n<td>10k<\/td>\n<td>-63<\/td>\n<\/tr>\n<tr>\n<td>100k<\/td>\n<td>-83<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-871\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3a.png\" alt=\"\" width=\"516\" height=\"420\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3a.png 516w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3a-300x244.png 300w\" sizes=\"auto, (max-width: 516px) 100vw, 516px\" \/><\/p>\n<p>Alongside the resistor trays are 1nF, 10nF and 100nF capacitors. You can also open the \u201cPWM-as-DAC\u201d project on os.mbed.org<\/p>\n<h2>Digital to Analogue Conversion (DAC)<\/h2>\n<p>You might have noticed that using a PWM is somewhat cumbersome. Its advantage is simplicity, and particularly suited to tasks such as DC motor speed control (it is relatively simple to switch a power transistor on and off at high speed in order to drive a motor).<\/p>\n<p>However, for outputting complex waveforms, such as audio or medical signals, you are advised to use a high precision and linear Digital to Analogue Converter (DAC). The micro controller you are using in these labs has an on-chip 12-bit DAC.<\/p>\n<p>mbed provides an object <code>AnalogOut<\/code> which encapsulates all the necessary code to access the DAC.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-872\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3b.png\" alt=\"\" width=\"506\" height=\"363\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3b.png 506w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3b-300x215.png 300w\" sizes=\"auto, (max-width: 506px) 100vw, 506px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-873\" src=\"http:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3c.png\" alt=\"\" width=\"510\" height=\"199\" srcset=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3c.png 510w, https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-content\/uploads\/sites\/94\/2019\/10\/Task-5-2-3c-300x117.png 300w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/p>\n<pre class=\"lang:c++ decode:true\">#include \"mbed.h\"\r\n#include \u201cmath.h\"\r\n\r\n<strong>AnalogOut<\/strong>  aOut(PA_5);\r\n\r\nint main(void) {\r\n    while (true) {\r\n       for (float i=0.0f; i&lt;1.0f; i+=0.01f) {\r\n           <strong>aOut<\/strong> = i;\r\n           wait(0.001f);  \/\/approx. 1kHz\r\n        }\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Table of Contents In this section we look at interfacing with the analogue world using mbed. You will use a simple potentiometer to generate analogue voltages, and measure that voltage using an Analogue to Digital Converter (ADC) to perform sampling. Analogue signals suffer problems with noise and uncertainty. Analogue filters are used to prevent a&hellip; <a class=\"more-link\" href=\"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/microcontrollers\/mbed-os-2\/courses\/level-5-embedded-and-real-time-systems\/analogue-interfacing-real-time-data-conversion\/\">Continue reading <span class=\"screen-reader-text\">Analogue Interfacing &#8211; Real Time Data Conversion<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":719,"menu_order":4,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-821","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-json\/wp\/v2\/pages\/821","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-json\/wp\/v2\/comments?post=821"}],"version-history":[{"count":16,"href":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-json\/wp\/v2\/pages\/821\/revisions"}],"predecessor-version":[{"id":874,"href":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-json\/wp\/v2\/pages\/821\/revisions\/874"}],"up":[{"embeddable":true,"href":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-json\/wp\/v2\/pages\/719"}],"wp:attachment":[{"href":"https:\/\/blogs.plymouth.ac.uk\/embedded-systems\/wp-json\/wp\/v2\/media?parent=821"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}