tag:blogger.com,1999:blog-23817618026156607052024-03-13T22:34:30.978+05:30fetch( ); decode( ); execute( );// the cycle of my life...Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.comBlogger249125tag:blogger.com,1999:blog-2381761802615660705.post-33719266038157169822023-08-09T18:10:00.001+05:302023-08-10T10:13:55.747+05:30Running Blink Example on Raspberry Pi Pico<p>Today, I managed to find some time to try out a Raspberry Pi Pico module that had been awaiting my attention at the lab for some months. More details about this module can be found in their website's <a href="https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html" target="_blank">documentation</a>. The following are the steps that I followed to get their default LED blink example running on the module. I tested this on a computer running Ubuntu 20.04. <br /></p><p><b><u>Get the SDK:</u></b><br /></p><p>mkdir RPi-Pico-Stuff<br />cd RPi-Pico-Stuff/<br />git clone https://github.com/raspberrypi/pico-sdk.git --branch master<br />cd pico-sdk/<br />git submodule update --init<br />cd ..<br />git clone https://github.com/raspberrypi/pico-examples.git --branch master<br />sudo apt update <br />sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential libstdc++-arm-none-eabi-newlib<br />cd pico-sdk/<br />git pull<br />git submodule update<br />cd ..</p><p><b><u>Build the examples (including Blink):</u></b><br /></p><p></p><p></p><p></p><p>cd pico-examples/<br />mkdir build<br />cd build/<br />export PICO_SDK_PATH=../../pico-sdk<br />cmake ..<br />cd blink/<br />make -j4</p><p><b><u>Loading the executable to Raspberry Pi Pico module:</u></b></p><p>While press-and-hold the BOOTSEL button on the Raspberry Pi Pico module, connect it to the USB port of the computer. It will mount the module as a USB mass storage device to the computer. Now, copy the "blink.uf2" file in the build/blink directory into the mounted USB mass storage device. The executable file will immediately start running on the device, which makes the Raspberry Pi Pico device to blink its onboard LED.<br /></p><p>The blink program looks like the following.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHNC-ONrIRPd72MMb5r_ZlrPKU7KRkizW-CqLh-YQN6D6NL-5FvNgyav64eRE_I8ACWN75euhbYYEX-2nXyaNLqaNGulaQO9gfi3ivXZz8BLbXMEAI0lL8AjmCYeJjn_rPr_b-6moYpBlQdJ0nM7vEsv3DX7DNfl5SCWS9z7uFdbjzg9xTKVSXmDR94L8/s632/Screenshot%20from%202023-08-09%2017-51-21.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="446" data-original-width="632" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHNC-ONrIRPd72MMb5r_ZlrPKU7KRkizW-CqLh-YQN6D6NL-5FvNgyav64eRE_I8ACWN75euhbYYEX-2nXyaNLqaNGulaQO9gfi3ivXZz8BLbXMEAI0lL8AjmCYeJjn_rPr_b-6moYpBlQdJ0nM7vEsv3DX7DNfl5SCWS9z7uFdbjzg9xTKVSXmDR94L8/w442-h312/Screenshot%20from%202023-08-09%2017-51-21.png" width="442" /></a></div><br /> The programmed device blinks its built-in LED continuously as follows.<br /><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg49edhbAohmSi_p-YhZCmFmNLBE1FrNShl7HaoZklEsMZ4pyMIoiXPiNoS7pevSwBk7BqAKHNVd-rW1Zo4jo8aIngxCTj7feqAijdQeerkcf2OkrpAPsWgV8BQjd5hOINwfx17b3M2HcAMuYq8QP-ScqkfQxDWdhd2J0nS3tH61VIRtMk9YNaUVnHu_-w/s2632/20230809_174824.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2632" data-original-width="2250" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg49edhbAohmSi_p-YhZCmFmNLBE1FrNShl7HaoZklEsMZ4pyMIoiXPiNoS7pevSwBk7BqAKHNVd-rW1Zo4jo8aIngxCTj7feqAijdQeerkcf2OkrpAPsWgV8BQjd5hOINwfx17b3M2HcAMuYq8QP-ScqkfQxDWdhd2J0nS3tH61VIRtMk9YNaUVnHu_-w/w308-h360/20230809_174824.jpg" width="308" /></a></div><br /><p><br /></p>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-68415639111848597482023-06-28T15:17:00.002+05:302023-06-28T15:17:50.664+05:30Fundamentals of Radio Tomographic Imaging - Part 1<div style="text-align: justify;"></div><div style="text-align: justify;"><b><script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script><script async="" id="MathJax-script" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script></b></div>
<p style="text-align: left;"><b><u>Nodes vs Links</u></b> <br /></p><p style="text-align: left;">Consider a wireless network consisting of \(K\) number of devices. If each and every device is communicating with each other, there will be a wireless link between each and every pair of nodes. The number of such unique two-way links is depicted as \(M\). The following equation describes relationship between \(M\) and \(K\):</p>
<p style="text-align: left;">
$$ M = \frac{{K}^2-K}{2} $$
</p>
<p style="text-align: left;">The following figure illustrates some examples of \(M\) values and their corresponding \(K\) values.</p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU54xJuGRYyGuSyTRmHQNyAP4ldBVpxyVgunBIQJ8wzLRXy-pprg_pKy4uFsKHp4jdPIIqiv3XeT0hhi3HtgYskPcy2D6sYNFudoo_wzcqmhgjAUZNTcRZJtBWHcC1EJNZNf_pYSpNo8tPywUR4fSdA6H3m9hP6wby1n-6aFXb1I-o-0oekzr10BwVk7s/s1140/M-and-K-values.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="758" data-original-width="1140" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU54xJuGRYyGuSyTRmHQNyAP4ldBVpxyVgunBIQJ8wzLRXy-pprg_pKy4uFsKHp4jdPIIqiv3XeT0hhi3HtgYskPcy2D6sYNFudoo_wzcqmhgjAUZNTcRZJtBWHcC1EJNZNf_pYSpNo8tPywUR4fSdA6H3m9hP6wby1n-6aFXb1I-o-0oekzr10BwVk7s/w400-h266/M-and-K-values.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure 1: Relationship between the number of devices and the number of links.<br /></td></tr></tbody></table>Using that equation, based on the number of nodes, i.e., wireless devices, we have in a network, we can easily figure out how many links are available in the network --- if each node is communicating with every other node.<br /><p style="text-align: left;"><b><u>Characteristics of a Particular Link</u></b></p><p style="text-align: left;">There are many wireless links in the network, i.e., \(M\) number of them. Out of these \(M\) links, let's consider a single two-way link between two wireless devices in such a network. The received signal strength of the \(i\)th link (\(i = 1, 2, ..., M\)) at time \(t\) is represented by \({y}_{i}(t)\). The following equation shows how this value can be described:</p><p style="text-align: left;"></p><p style="text-align: left;">
$$ {y}_{i}(t) = P_{i} - L_{i} - {S}_{i}(t) - {F}_{i}(t) - {\upsilon}_{i}(t) $$
</p>
<p style="text-align: left;">where:</p>
<ul style="text-align: left;">
<li style="text-align: left;">\({y}_{i}(t)\) : Received signal strength at time \(t\).</li>
<li style="text-align: left;">\(P_{i}\) : Transmitted power in decible.</li>
<li style="text-align: left;">\(L_{i}\) : Static loss due to distance, antenna patterns, device inconsistencies, etc.</li>
<li style="text-align: left;">\({S}_{i}(t)\) : Shadowing loss due to objects that attenuate the signal.</li>
<li style="text-align: left;">\({F}_{i}(t)\) : Fading loss due to constructive and destructive interference.</li>
<li style="text-align: left;">\({\upsilon}_{i}(t)\) : Measurement noise.</li>
</ul>
<p></p><p><u><b>Voxels and their Impact on Links</b></u><br /></p><p>If we divide the entire environment, where the wireless network resides, into a grid, every unit square in this grid is called a <i>voxel</i>. The number of voxels we have depends on the number of rows and columns we break this field of network into. Let's depict the number of voxels as \(N\). Each link \(i\) spans cross a particular number of voxels in the grid. For a given link \(i\), the specific voxels that it goes through can be represented using a row vector \(w_{i}\) that has a length \(N\), i.e., the number of voxels. In this vector, the elements that are crossed by the link \(i\) are set 1, and the rest to 0. The following figure shows such a voxel weight vector created for a particular link.<br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh15MMIEwnH3vhTCJYdnAmEtlA0JwUcVmPAhpV9KzNHDt43yuNQhebyfesB1EM2gRyib65CWVfiWvmi-xXl2nXJ1ENhuFzVus_L2LqVWYii6phmxaZz1QFX1aPk7TDzXRuE-LiuDtDK-E4Nz35zyTl0viPXtiEZxequRRpDlBizNqNYM-WHxRbbDKRGxOc/s1443/voxels-and-links.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1248" data-original-width="1443" height="371" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh15MMIEwnH3vhTCJYdnAmEtlA0JwUcVmPAhpV9KzNHDt43yuNQhebyfesB1EM2gRyib65CWVfiWvmi-xXl2nXJ1ENhuFzVus_L2LqVWYii6phmxaZz1QFX1aPk7TDzXRuE-LiuDtDK-E4Nz35zyTl0viPXtiEZxequRRpDlBizNqNYM-WHxRbbDKRGxOc/w429-h371/voxels-and-links.png" width="429" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure 2: Creating weight vector for a particular link.<br /></td></tr></tbody></table><p> We can create such a row vector \(w_{i}\) for each link \(i\). By doing so, we end up with \(M\) number such \(w_{i}\) row vectors. We can stack them together to create a matrix of weights. This matrix has a dimension of \(M \times N\) where \(M\) is the number of links and \(N\) is the number of voxels. The following figure illustrates how the combined weight matrix looks like. Using that matrix, we can refer to any particular link \(i\) impacted by a voxel \(j\) using the matrix element \(w_{ij}\). <br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4GVQ7gGHH6S6wpuuPMafbAek7D5FNsUmr2BdNKsP3rxmKgiq8ApJV6HVd7MqWF54VwbYiaSWc2x32v9d6mmq32GWc3_Au3BNly-bqhwoQDeDZuLCrNKe-JBQzr8loag6zHGTKvZE9uX1xcgPfsCGReBDDxsdDPOhtKQcQrUgmz6iwv3zixMyZ8WCI2p8/s1029/weight-vector.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="956" data-original-width="1029" height="345" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4GVQ7gGHH6S6wpuuPMafbAek7D5FNsUmr2BdNKsP3rxmKgiq8ApJV6HVd7MqWF54VwbYiaSWc2x32v9d6mmq32GWc3_Au3BNly-bqhwoQDeDZuLCrNKe-JBQzr8loag6zHGTKvZE9uX1xcgPfsCGReBDDxsdDPOhtKQcQrUgmz6iwv3zixMyZ8WCI2p8/w372-h345/weight-vector.png" width="372" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure 3: The resulting weight matrix that has weigh values for each link and each voxel.<br /></td></tr></tbody></table><p></p><p><b><u>Determining Shadowing Loss</u></b><br /></p><p></p><p>The shadowing loss, \({S}_{i}(t)\) is the sum of attenuation of the link \(i\) when it was going through the grid. Consider a column vector \(x(t)\) that has a length of \(N\), the number of voxels. Not all, but part of the voxels in the grid are crossed by the link \(i\). The attenuation of link \(i\) at a particular voxel \(j\) at time \(t\) is represented by the element \(x_{j}(t)\). Out of all elements in the \(x(t)\) vector, only the elements \(x_{j}(t)\) that have been crossed by the link \(i\) should be considered. We can find the relevance of an element in the vector \(x(t)\) for a link \(i\) by looking whether the corresponding value in the \(w_{ij}\) element of the weight matrix \(w\). If the corresponding element in the weight matrix is 1, that voxel's impact should be counted to the shadowing loss.<br /></p><p>So, for particular link i, we can calculate it's shadowing loss in the following way, by using the weight matrix w and also the attenuation vector x.</p>
<p>
$$ {S}_{i}(t) = \sum_{j=1}^{N} w_{ij} x_{j}(t) $$
</p>
<p>It is important to note that we have to maintain consistency in the way we create the weight vector \(w_{i}\) and attenuation vector \(x\) for a given link \(i\) from its two dimensional matrix representation to a vector (see Figure 2). <br /></p><p>The shadowing loss calculation can be visualised as follows:</p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSRBi7Nv_Gk5T0YnnxR-A9yMu930e8IB5OEM2bdapMRkmwva6VwosPdQPM45fop3YB49gtHR-Gno-OreWCsQS7tb2pdkPAtD_PGHLkpElI14rrm31PZ0N3eprGgVPKEVxf1AEhTFFldInrMec0fYK6YGbZZTj0PEvILwNFmnAmQW7af3ySBnYl0oJ3Pc8/s1452/shadowing-loss-calculation.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="738" data-original-width="1452" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSRBi7Nv_Gk5T0YnnxR-A9yMu930e8IB5OEM2bdapMRkmwva6VwosPdQPM45fop3YB49gtHR-Gno-OreWCsQS7tb2pdkPAtD_PGHLkpElI14rrm31PZ0N3eprGgVPKEVxf1AEhTFFldInrMec0fYK6YGbZZTj0PEvILwNFmnAmQW7af3ySBnYl0oJ3Pc8/w501-h255/shadowing-loss-calculation.png" width="501" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure 4: Calculating shadowing loss for link \(i\) at time \(t\).<br /></td></tr></tbody></table><br /><p><u><b>Changing Attenuation over Time</b></u><br /></p><p>Due to the movement of obstacles, the received signal strength \({y}_{i}(t)\) varies over time. By focusing only on such changes, we can greatly simplify our mathematical representation. So, lets consider received signal values \({y}_{i}(t_{a})\) and \({y}_{i}(t_{b})\) for a link \(i\) at two times, \(t_{a}\) and \(t_{b}\). We can depict the difference of the received signal strengths \(\Delta y_{i}\) as follows:<br /></p>
<p>
$$ \Delta y_{i} = {y}_{i}(t_{b}) - {y}_{i}(t_{a}) $$
</p>
<p>
$$ \Delta y_{i} = \{ P_{i} - L_{i} - {S}_{i}(t_{b}) - {F}_{i}(t_{b}) - {\upsilon}_{i}(t_{b}) \} - \{ P_{i} - L_{i} - {S}_{i}(t_{a}) - {F}_{i}(t_{a}) - {\upsilon}_{i}(t_{a}) \} $$
</p>
<p>
$$ \Delta y_{i} = {S}_{i}(t_{a}) - {S}_{i}(t_{b}) + {F}_{i}(t_{a}) - {F}_{i}(t_{b}) + {\upsilon}_{i}(t_{a}) - {\upsilon}_{i}(t_{b}) $$ </p><p>At this situation, we can consider the fading loss due to interferences, \({F}_{i}(t)\), and the measurement noise, \(\upsilon_{i}(t)\) altogether as an overall noise, \(n_{i}\) for the link \(i\) during the considered time period. </p>
<p>
$$ n_{i} = {F}_{i}(t_{a}) - {F}_{i}(t_{b}) + {\upsilon}_{i}(t_{a}) - {\upsilon}_{i}(t_{b}) $$
</p>
<p>So, out equation for \(\Delta y_{i}\) can be rewritten as follows:</p>
<p>
$$ \Delta y_{i} = {S}_{i}(t_{a}) - {S}_{i}(t_{b}) + n_{i} $$
</p>
<p>Now, the difference between the two shadowing losses, \({S}_{i}(t_{a})\) and \({S}_{i}(t_{b})\), can also be closely inspected.</p>
<p>
$$ {S}_{i}(t_{a}) - {S}_{i}(t_{b}) = \sum_{j=1}^{N} w_{ij} x_{j}(t_{a}) - \sum_{j=1}^{N} w_{ij} x_{j}(t_{b}) $$
</p>
<p>
$$ {S}_{i}(t_{a}) - {S}_{i}(t_{b}) = \sum_{j=1}^{N} w_{ij} \{(x_{j}(t_{a}) - x_{j}(t_{b})\} $$
</p>
<p>
$$ {S}_{i}(t_{a}) - {S}_{i}(t_{b}) = \sum_{j=1}^{N} w_{ij} \Delta x_{j} $$
</p>
<p>So, we ended up with a new attenuation vector \(\Delta x_{j}\) that represents the variation of attenuation for the link \(i\). Considering that, we can further simplify our equation for the variation of received signal strength \(\Delta y_{i}\) as follows:</p>
<p>
$$ \Delta y_{i} = \sum_{j=1}^{N} w_{ij} \Delta x_{j} + n_{i} $$
</p>
<p>This equation that we finally ended up is really important. What it represents is the difference of the received signal strength of link \(i\) represented by \(\Delta y_{i}\). It can be calculated by using the weight matrix \(w\) and the difference of attenuation vector \(\Delta x\) for all the voxels from \(1\) to \(N\). </p><p>There is a unique equation like this for each link \(i\) where \(i\) can be from \(1\) to \(M\).</p>
<p>
$$ \Delta y_{1} = \sum_{j=1}^{N} w_{1j} \Delta x_{j} + n_{1} $$
</p>
<p>
$$ \Delta y_{2} = \sum_{j=1}^{N} w_{2j} \Delta x_{j} + n_{2} $$
</p>
<p>
$$ \Delta y_{3} = \sum_{j=1}^{N} w_{3j} \Delta x_{j} + n_{3} $$
</p>
<p>
$$ \ldots $$
</p>
<p>
$$ \Delta y_{M} = \sum_{j=1}^{N} w_{Mj} \Delta x_{j} + n_{M} $$
</p>
<p>Let's represent this collection of equations (not linear equations) in the following format as a single equation:</p>
<p>
$$ \Delta y = W \Delta x + n $$
</p>
<p>
Here, \(\Delta y\) is what we get to know that contains the variation of received signal strength for each link. By using that information, what we need to find is the \(\Delta x\) that contains a collection of attenuation vectors for each link. As a collective of these attenuation vectors, \(\Delta x\) represents the attenuation image (i.e., the tomographic image) that we need to create.
</p>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-78992423267069755512023-05-14T21:43:00.000+05:302023-05-14T21:43:23.986+05:30Observing I2C Communication using Logic Analyser<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj50zLn5DcseCp_jgXNCF3iPumMXDwmFvtgNcUhrNsvyxrJ4Ob4tVLSG7tJr8aBOFhZYA_je-SAfm-WCcrmdHZXk5ZZ7KPhYkFKxkkUSbz5-QV5fzS-Lw0txO2hVhVc8aeGl1xG4EWvFXsgHHGtgcttecZFBz_Y7wRQY3yT9SkjFNbyNyktPds68BAC/s480/I2C_controller-target.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="230" data-original-width="480" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj50zLn5DcseCp_jgXNCF3iPumMXDwmFvtgNcUhrNsvyxrJ4Ob4tVLSG7tJr8aBOFhZYA_je-SAfm-WCcrmdHZXk5ZZ7KPhYkFKxkkUSbz5-QV5fzS-Lw0txO2hVhVc8aeGl1xG4EWvFXsgHHGtgcttecZFBz_Y7wRQY3yT9SkjFNbyNyktPds68BAC/s320/I2C_controller-target.png" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure: Connectivity between a master (controller) and slaves (target). (source: <a href="https://en.wikipedia.org/wiki/I²C">https://en.wikipedia.org/wiki/I²C</a>)</td></tr></tbody></table><span style="text-align: justify;"><br /></span><div style="text-align: left;"><span style="text-align: justify;">Inter-integrated circuit (I2C) protocol is an advanced protocol, that eliminates many weaknesses in the UART and SPI protocols to provide communication between ICs using minimum number of wires. I2C consists of just two wires interconnecting one or many master devices with one or many slave devices. One wire is serial clock (SCL) that provides clock pulses across the embedded network. The other wire is serial data (SDA) that carries data between master and slave devices. Both SCL and SDA wires are pulled-up by default when the embedded network is in idle state. </span></div><div style="text-align: left;"><span style="text-align: justify;"><br /></span></div><div style="text-align: justify;">When a communication occurs in an I2C environment, it goes according to the following procedure. Every communication is encapsulated by a START condition and a STOP condition. After the START condition, the master can send a address frame, which has a length of 7 or 10 bits. An address uniquely identifies a particular device (a master or slave) in the embedded network. Followed by the address bits, a read/write bit is sent, which specifies whether the sender wishes to send something to the receiver or, expecting to receive something from the receiver. Afterwards, the receiver can send a single bit ACK/NACK bit to specify that the address was receiver. There onward, the sender can send groups of 8 bits of data, each of which are followed by ACK/NACK bits from the receiver. When done, the sender sends a STOP condition to indicate that the communication is over.</div><div style="text-align: justify;"><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidgCtFRI0WhbMIVzxwL0Hcgbh-NS_-MMF2SRrGsv3JMRJST-FKnWPF5iGQA25F60NsSTVqznNSns-_KPsOhxB_2-3EDo1IZU1A7S1rM64Uc7LfvM5IDf7ihBVr06OMazE5sKeq0nSvVPinrw99OpUvBIzTiDhYA99mtQgxIIicFimcQGTywfpnkvi1/s1280/Introduction-to-I2C-Message-Frame-and-Bit-2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="323" data-original-width="1280" height="101" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidgCtFRI0WhbMIVzxwL0Hcgbh-NS_-MMF2SRrGsv3JMRJST-FKnWPF5iGQA25F60NsSTVqznNSns-_KPsOhxB_2-3EDo1IZU1A7S1rM64Uc7LfvM5IDf7ihBVr06OMazE5sKeq0nSvVPinrw99OpUvBIzTiDhYA99mtQgxIIicFimcQGTywfpnkvi1/w400-h101/Introduction-to-I2C-Message-Frame-and-Bit-2.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure: Structure of an I2C message (source: <a href="https://www.circuitbasics.com/basics-of-the-i2c-communication-protocol">https://www.circuitbasics.com/basics-of-the-i2c-communication-protocol</a>)</td></tr></tbody></table><br /><div style="text-align: justify;">The purpose of sending a message like this would be to either write some configuration setting to a register of the recipient device, or to read some register values from a particular recipient device. The following are some key highlights about each important component of an I2C message.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>START condition:</b></div><div style="text-align: justify;">While the SCL is high, the SDA is pulled from HIGH to LOW to indicate the START condition.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>Address frame:</b></div><div style="text-align: justify;">This consists of a bit pattern of a length of 7 or 10 bits. The binary digit 1 is indicated by HIGH value in the SDA wire when SCL is HIGH. The binary digit 0 is indicated by LOW value in the SDA wire when the SCL is HIGH.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>Read/Write bit:</b></div><div style="text-align: justify;">The read operation is indicated by using a data bit 1 (SDA wire released to HIGH which SCL is HIGH). Similarly, the write operation is indicated by using a data bit 0 (SDA wire is pulled to HIGH while SCL is HIGH).</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>ACK/NACK:</b></div><div style="text-align: justify;">At end of an address frame or a data frame of a length of 8 bits, the receiver is supposed to send back an ACK/NACK bit to indicate that whatever that has been sent is successfully received. When this operation is being performed, the slave controls the SDA wire. An ACK bit is indicated by SDA being pulled LOW by the receiver while the SCL is HIGH. A NACK is indicated by SDA left to be HIGH by the receiver while the SCL is HIGH.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>Data frame:</b></div><div style="text-align: justify;">Similar to the address frame, the data frame consists of a bit pattern to indicate some data to be transferred from the master to the slave or wise versa. In from which device to which device the data is transferring is decided by the read/write bit set previously by the master. Whichever the direction is, the length of a data frame is 8 bits. If the data is being sent by a slave to the master, the master will send ACK bits at the end of each 8-bit data frame from the slave to indicate that the master is ready to take more data frames. However, once the master is done with the data frames from the slave, the master sends a NACK to indicate that the slave should stop sending any subsequent data frames.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>STOP condition:</b></div><div style="text-align: justify;">While the SCL is high, the SDA is released from LOW to HIGH to indicate the STOP condition.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The following two figures illustrates two scenarios of I2C data communication between a master and a slave.</div><div style="text-align: justify;"><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDkhTsm5nGyZK9bUeB1edRjBJJOSctvdRwO36so-X6kaT7h0co-7S_PxYxSlfMn1tYe--MdgSsZKZE-q45DAPYa5WIbCvzI93jq7bcFOGW3uNDsXNyyoNqPXG4WL6QXXoM22P_decarHJ0ZlTpgB8vXDYZScKStxFTduw_bYGcOUewaHDENB-wP8ub/s1214/writing-to-slave-register.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="412" data-original-width="1214" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDkhTsm5nGyZK9bUeB1edRjBJJOSctvdRwO36so-X6kaT7h0co-7S_PxYxSlfMn1tYe--MdgSsZKZE-q45DAPYa5WIbCvzI93jq7bcFOGW3uNDsXNyyoNqPXG4WL6QXXoM22P_decarHJ0ZlTpgB8vXDYZScKStxFTduw_bYGcOUewaHDENB-wP8ub/w640-h218/writing-to-slave-register.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure: A master writing to a particular slave's a particular register. (source: TI Application Report SLVA704 <a href="https://www.ti.com/lit/an/slva704/slva704.pdf">https://www.ti.com/lit/an/slva704/slva704.pdf</a>)</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXzDWoWu-itC1QxvLtVGw5Zln0_P2aMY3IFPUVLEBlEpcObB0XSKXBK4HRgg9qrgT8oebZArKMhjgFxFiR4m-umZSzn1q3GhVJ0hnyxOufBx0UGZpii1mVe0E9m_6R166G3kEwDvBcmxm3uHH-yoSRBj7gg6BZ9zki7fIe172VXfXjarxXKRgKqFg3/s1172/reading-from-slave-register.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="278" data-original-width="1172" height="152" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXzDWoWu-itC1QxvLtVGw5Zln0_P2aMY3IFPUVLEBlEpcObB0XSKXBK4HRgg9qrgT8oebZArKMhjgFxFiR4m-umZSzn1q3GhVJ0hnyxOufBx0UGZpii1mVe0E9m_6R166G3kEwDvBcmxm3uHH-yoSRBj7gg6BZ9zki7fIe172VXfXjarxXKRgKqFg3/w640-h152/reading-from-slave-register.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure: A master reading from a particular slave's particular register. (source: TI Application Report SLVA704 <a href="https://www.ti.com/lit/an/slva704/slva704.pdf">https://www.ti.com/lit/an/slva704/slva704.pdf</a>)<br /></td></tr></tbody></table><br /><div style="text-align: justify;">It's time explore how I2C protocol behaves in the real world using actual hardware. We'll use two Arduino devices to communicate with I2C protocol for this demonstration. In our scenario, one Arduino device will act as the I2C master while the other device will act as the slave. The master device is programmed to request 1-byte data from a slave with an address number 8. The slave device is coded to posses address number 8, and upon a request, it sends a byte containing ASCII character A (binary: 01000001). </div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>I2C Master Program:</b></div><div style="text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoRNjreffWFVYD8HtQ6ka3rlEntsURTZ_nhd9BilsIYkAmVqFH7Ia7yMsVBtCJbcy9eHPlQoppiBxJM4beTbemt7mKunkqcazhDe-xMOz9He9v7KdDnNYPLNzJ8olNlnLlWRxVASGUDWLxq926R2G2bhHzeYBRNKMqxC3AXilMHf65LFU_g_YYF6yo/s437/i2c-master.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="328" data-original-width="437" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoRNjreffWFVYD8HtQ6ka3rlEntsURTZ_nhd9BilsIYkAmVqFH7Ia7yMsVBtCJbcy9eHPlQoppiBxJM4beTbemt7mKunkqcazhDe-xMOz9He9v7KdDnNYPLNzJ8olNlnLlWRxVASGUDWLxq926R2G2bhHzeYBRNKMqxC3AXilMHf65LFU_g_YYF6yo/w400-h300/i2c-master.png" width="400" /></a></div><br /><div style="text-align: justify;"><b>I2C Slave Program:</b></div><div style="text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3qlXakYJHNwUGThLEiLhXU3hmJb_joRa7SMmlcCbGgSBnGx1XF3CL0I3wqm5xi0cgSSeLcn8Tmp50a1_f98i_x5Huuicuw4MI-7pC3D7NgLpcl3mIRImd-Me1IQHBpuRxHUXSkvOJElRW9Ug5n8BKRSFbW9U6ThRFYH587XlVkzTaUWpsuMB3r8HZ/s331/i2c-slave.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="288" data-original-width="331" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3qlXakYJHNwUGThLEiLhXU3hmJb_joRa7SMmlcCbGgSBnGx1XF3CL0I3wqm5xi0cgSSeLcn8Tmp50a1_f98i_x5Huuicuw4MI-7pC3D7NgLpcl3mIRImd-Me1IQHBpuRxHUXSkvOJElRW9Ug5n8BKRSFbW9U6ThRFYH587XlVkzTaUWpsuMB3r8HZ/s320/i2c-slave.png" width="320" /></a></div><br /><div style="text-align: justify;">The hardware connectivity between the master and slave devices are made simply by directly connecting SDA pin of master to SDA pin of the slave, and SCL pin of master to SCL pin of the slave. Since we are required to monitor the signals moving in these wires, I've made connections through a project board where I have connected the signal analyser's channels as well. So, when the master and slave are communicating, I should be able to see the signals going through SCL and SDA wires.</div><div style="text-align: justify;"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXdtBwX1TpBnmSu9y0INNFsr7OSJC3dotIprB4RQ7CL0Jv_VJyY_iy_22TnITY5KUq0Oh843n_9M9KuxmxkvkSmCWfBawQJdVAtpijhQOgGPq7WBM5T_IPGNGtj_Zae7QNtd7IPYzB_RQ4iu2FGnooiuOoNuPlHx1lJp-R0lPBjxFDZ8EavoFg-qL2/s4000/20230513_190316.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="4000" data-original-width="2250" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXdtBwX1TpBnmSu9y0INNFsr7OSJC3dotIprB4RQ7CL0Jv_VJyY_iy_22TnITY5KUq0Oh843n_9M9KuxmxkvkSmCWfBawQJdVAtpijhQOgGPq7WBM5T_IPGNGtj_Zae7QNtd7IPYzB_RQ4iu2FGnooiuOoNuPlHx1lJp-R0lPBjxFDZ8EavoFg-qL2/w225-h400/20230513_190316.jpg" width="225" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure: Connectivity between master and slave Adruino devices. The SDA and SCL pins are tapped for the signal analyser connectivity.</td></tr></tbody></table></div><div style="text-align: justify;"><br /></div>The captured signals by the signal analyser are shown in the following figure. Channel 0 is representing SCL wire, while Channel 1 is representing SDA. <br /><div style="text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG1xNCGya_c1evy8aAH2XIGDXDlhUeXjnHtFokFJnv7-aAxcf4EWT0SEi5rrnNsSvn_gWRCKsJkfqKSkflqbjiXsCVfZUXZxv1PEBn5zilxH6ITWHlaLhi0TJVSPfZbYvTidIgqonpmQrmFMLFXUzWtCdw61PPRacuuWpalqXB68crUgrdhx32SqQf/s1185/i2c-signal-analyser-view.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="308" data-original-width="1185" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG1xNCGya_c1evy8aAH2XIGDXDlhUeXjnHtFokFJnv7-aAxcf4EWT0SEi5rrnNsSvn_gWRCKsJkfqKSkflqbjiXsCVfZUXZxv1PEBn5zilxH6ITWHlaLhi0TJVSPfZbYvTidIgqonpmQrmFMLFXUzWtCdw61PPRacuuWpalqXB68crUgrdhx32SqQf/w640-h166/i2c-signal-analyser-view.png" width="640" /></a></div><br /><div style="text-align: justify;">Let's try to decode the captured signal. The SDA signal is surrounded by START and STOP conditions as expected. In between those two, the following bit pattern should exist in the SDA signal for each SCL pulse.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>[ID in 7 bits] - [read bit] - [ACK] - [data frame in 8 bits] - [NACK]</b></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The relevant values in those bits should be as follows:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">ID in 7 bits: 0001000 (address 8 in binary)</div><div style="text-align: justify;">read bit: 1</div><div style="text-align: justify;">ACK: 0</div><div style="text-align: justify;">data frame in 8 bits: 01000001 (character 'A' in ASCII)</div><div style="text-align: justify;">NACK: 1</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">So, the bit pattern in the SDA signal should be:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>[0001000] - [1] - [0] - [01000001] - [1]</b></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">If you watch carefully, you will see this pattern in the SDA signal in Channel 1. One interesting this I noticed was that the SCL clock signal has a little gap somewhere in the middle. I think, this is due to the master finishing up its job and awaiting for the slave to start its transmission. It's a way for the master to let the slave read its internal register value and prepare for a transmission back.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">So, that's about it. I2C is a very important embedded communication protocol that can be used to build complex and very capable embedded system devices containing various components and modules. We can understand how the protocol works by intercepting the signals going through the wires.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-60001961352512807502023-04-13T14:44:00.000+05:302023-04-13T14:44:16.500+05:30Observing SPI Communication using Logic Analyser<p style="text-align: justify;">In this article, let's try to understand how the serial peripheral interface (SPI) protocol works, which can be used to transfer data between digital electronics components. It is useful to connect various digital sensors and other peripheral modules with a microcontroller unit. As the name implies, it is a serial communication protocol. However, unlike UART, this is synchronous communication, and hence, SPI requires a clock signal. When communicating, one device acts as the master which provides the clock signal for the receiving, i.e., slave devices. The clock channel is named as SCK. We can have one master device, and one or more slave devices. The master device has to have dedicated set of channels, each connected to a particular slave device. By enabling the relevant dedicated channel, the master notifies that it wishes to communicate with the relevant slave device. These dedicated channels are called chip select or slave select (SS) channels. If there is only one slave device connected to the master device, there will be only one SS channel from the master to the slave. If there are two slave devices connected to the master, there will be two different SS pins from the master going to the two slave devices separately.</p><p style="text-align: justify;">The data output from the master device is named as master-out slave-in (MOSI) channel, which is connect to the MOSI channels of all the slave devices. Similarly, the data input to the master device is named as master-in slave-out (MISO) channel, which similarly connects to the MISO pins of all the slave devices. This means, the data channels MOSI and MISO are shared about the master and all the slaves. Which slave is communicating with the master as a given moment is decided by the enabling of relevant SS channel by the master. The following diagram from Wikipedia nicely illustrates a scenario where a master device is connected to three slave devices:</p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY2GScOoRMz3_5NJ6pvhv4px6dyJBXrrhEM0UiWQarSEPzmavzuuGs3Yju-ITZlXk2TUVJybd7kaFsPElg4PMtSz3AMPCmwG-26JtwfDlR3SKQwzxkntOcaUVG8GVaDUygR9_l8apG_BLjJuDL0Ajfq3qx95Y-A85QrF5st6wrqtLVeOLNte1JAtI9/s387/SPI_three_slaves.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="307" data-original-width="387" height="318" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY2GScOoRMz3_5NJ6pvhv4px6dyJBXrrhEM0UiWQarSEPzmavzuuGs3Yju-ITZlXk2TUVJybd7kaFsPElg4PMtSz3AMPCmwG-26JtwfDlR3SKQwzxkntOcaUVG8GVaDUygR9_l8apG_BLjJuDL0Ajfq3qx95Y-A85QrF5st6wrqtLVeOLNte1JAtI9/w400-h318/SPI_three_slaves.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure: SPI Connectivity between a master and three slaves (source: <a href="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface">https://en.wikipedia.org/wiki/Serial_Peripheral_Interface</a>)</td></tr></tbody></table><br /><p style="text-align: justify;">Let's see the SPI protocol in action in a microcontroller module, particularly in an Arduino Uno device. In this scenario, our Arduino device is going to act as the master device. For the time being, we will not use a slave device since the action in MISO and MOSI are basically similar, except that they are taking data in the two directions separately. In our case, since we are only going to have a master device, we can observe some data in the MISO line when the master is sending some data out. The following is the code that we are programming the Arduino Uno device with. In this program, we are using <span style="font-family: courier;"><b>SPI.h</b></span> library from the Arduino library for SPI communication. Since we are using the pin 10 of the Arduino as the SS pin, we set it to OUTPUT mode. When initiating communication, we pull the SS pin LOW before sending data, which will go out from the MISO pin of the Arduino. After data transmission, we can set the SS pin HIGH again to signify that we are done. During the time period of SS pin is LOW, the master can both write data out (through MOSI) and also read data from the slave (through MISO) at the same time. In our case, we are only sending data out from the master.</p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj1DWrul18BlzE69LZy-t0JbX0sUjXmHp8_iALL_kE8vAeb3aCSoiW9xSQUNiLiODi3jbaOTC7OXujBaARMsD_udIjWZnZX4r-V-I02ebdXZsxL4S25QtPhEAbL6tH2qxsyKLfd0aSP2O4J1bkmdNa9hD3BpuBU3gugNKTRwsxo-YNfkAhL8P07Ake/s567/arduino-SPI-master-code.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="423" data-original-width="567" height="299" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj1DWrul18BlzE69LZy-t0JbX0sUjXmHp8_iALL_kE8vAeb3aCSoiW9xSQUNiLiODi3jbaOTC7OXujBaARMsD_udIjWZnZX4r-V-I02ebdXZsxL4S25QtPhEAbL6tH2qxsyKLfd0aSP2O4J1bkmdNa9hD3BpuBU3gugNKTRwsxo-YNfkAhL8P07Ake/w400-h299/arduino-SPI-master-code.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure: The Arduino program to be run on the master device.</td></tr></tbody></table><br /><p style="text-align: justify;">Now, it is time to wire the hardware for our observation. The MOSI, MISO, and SCK pins are hardware-defined pins. That means, we don't have a choice but to use the predefined pins of the Arduino device: MOSI is pin 11, MISO is pin 12, and SCK is pin 13. The number of SS pins we need depends on the number of slave devices we have. So, it is not hardwired. From our program code, we have set pin 10 to act as SS. When sending data from the master using <span style="font-family: courier;"><b>SPI.h</b></span> library, we can use <span style="font-family: courier;"><b>SPI.transfer()</b></span> function to specify the data we are sending. In our example code, we are sending the hexadecimal value 0xAA from the master which converts to 10101010 in binary. In order to observe SPI behaviour, let's connect the logic analyser to the SPI pins as follows:</p><p style="text-align: justify;"><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg77XbFauGRIQFhQcYMk5f2OlkGn6SIruUGUibgmflhbe-aXyt_Xm1nvwJ4mErM13QsAnch5VRYk4g8qYfOtk3rzK_h-tMN41cYQwEPtE-EjB6QkO8ZJdnd0iQ9C72qyIpYxPXmdTfY9E-t2vsZ7tAOAVwbId1yJkTdlDMDosoCVtJIHB4sm0dduvDM/s4000/arduino-SPI-hardware-setup.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="4000" data-original-width="2250" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg77XbFauGRIQFhQcYMk5f2OlkGn6SIruUGUibgmflhbe-aXyt_Xm1nvwJ4mErM13QsAnch5VRYk4g8qYfOtk3rzK_h-tMN41cYQwEPtE-EjB6QkO8ZJdnd0iQ9C72qyIpYxPXmdTfY9E-t2vsZ7tAOAVwbId1yJkTdlDMDosoCVtJIHB4sm0dduvDM/w360-h640/arduino-SPI-hardware-setup.jpg" width="360" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure: Arduino's SPI pins connected to the logic analyser.</td></tr></tbody></table>Channel Ground --> GND</p><p style="text-align: justify;">Channel 0 --> 10 (SS)</p><p style="text-align: justify;">Channel 1 --> 11 (MOSI)</p><p style="text-align: justify;">Channel 2 --> 12 (MISO)</p><p style="text-align: justify;">Channel 3 --> 13 (SCK)</p><p style="text-align: justify;">The following picture illustrates the Arduino Uno device pins tapped by the logic analysers channel probes. </p><br /><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;">Now, we can observe the signals going through the relevant SPI pins of the Arduino device as captured by the logic analyser. The following screenshot illustrates the captured data by the logic analyser. Channel 0 indicates that the SS pin has been pulled LOW to enable data communication between the master and slave. When this was done, the master has immediately started sending a clock signal through the SCK pin, which is captured on Channel 3 of the logic analyser. While the clock signal is present, at every HIGH position of the clock, the MOSI and MISO channels can transmit data bits --- HIGH for 1 and LOW for 0 as data bits. In our case, the master was sending the bit pattern 10101010. Therefore, we observe the 10101010 pattern in the MOSI pin, which is captured by Channel 1 of the logic analyser. The MISO pin as captured by Channel 2 remains idle as we don't have a slave device to send anything back to the master.</p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZVBcGvTWT6sUUtYPyMWcingIJw1jLGGDdP8rzYS77jz23FO5OBpnEznBa1IJ3rme6mbB7jlsLGpCp-GmC41HEpN59Ydjp5H3vvz5i-EeVzagaoEYBgTdKvQcTowoqKEb292J9c62diZl_s1h_mD6Grl-X_EmMX2qN9slnqCHcLDtgMTQcPcr4W4TF/s1018/arduino-SPI-master-logic-probe.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="428" data-original-width="1018" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZVBcGvTWT6sUUtYPyMWcingIJw1jLGGDdP8rzYS77jz23FO5OBpnEznBa1IJ3rme6mbB7jlsLGpCp-GmC41HEpN59Ydjp5H3vvz5i-EeVzagaoEYBgTdKvQcTowoqKEb292J9c62diZl_s1h_mD6Grl-X_EmMX2qN9slnqCHcLDtgMTQcPcr4W4TF/w640-h270/arduino-SPI-master-logic-probe.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Figure: Logic analyser's view of the data being transferred through SPI interface.</td></tr></tbody></table><br /><p style="text-align: justify;">That's it about the SPI protocol. In contrast to the UART protocol, SPI has the advantage of connecting multiple devices together. A UART device only has Tx and Rx pins to send and receive data from only one other device. SPI achieves the capability to have more than two devices by adding an extra pin (SS) to select the intended recipient of a transmission. The cost of this is that the master device has to posses extra digital output pins as many as the number of slave devices. If there are 5 slave devices, the master should have 10 SS pins, in addition to the MISO, MOSI, and SCK pins.</p>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-58316878267072423062023-04-01T23:07:00.000+05:302023-04-01T23:07:46.709+05:30Observing UART Communication using Logic Analyser<p style="text-align: justify;">The Universal Asynchronous Receiver / Transmitter (UART) is an embedded communication protocol, which can be used to transfer data between two electronic devices. As the name implies, this protocol is asynchronous, meaning that the sender and receiver does not have to be time synchronised through a dedicated clock signal. Instead, the signal itself is transferring a synchronisation pattern to help the receiver. For communicating from one device to the other, UART requires only one wire. However, since we need bi-directional communication, we need two wires each for sending data in a particular direction.</p><p style="text-align: justify;">When you look at a microcontroller that supports UART communication, you will see that there are two dedicated pins called Tx and Rx for this purpose. The Tx pin is used to send asynchronous data from this microcontroller to the outside reicevier. Similarly the Rx pin is used to receive asynchronous data from the outside sender to the microcontroller. When the channel is idle, the UART wires are maintained at HIGH state (logic 1). When some data need to be transmitted, the transmission wire's logic level is pulled down to LOW so that the receiving device know that something is coming through the channel.</p><p style="text-align: justify;">The data bits going through UART is organised into a frame structure. A UART frame consists of a start bit, data bits, parity bit, and finally a stop bit. The rate of bits is agreed between the sending and receiving devices by the programmer setting a parameter called baud rate. The are a specific set of baud rates that are usually used for this purpose. The data bits are sent in the order of least significant bit (LSB) first. The start bit is signified by a HIGH to LOW switch in the signal. Similarly, the stop bit is signified by a LOW to HIGH switch. The data bits and parity bit will be represented by either a HIGH or a LOW value depending on whether their values are 1s or 0s.</p><p style="text-align: justify;">Let's see some specific real-world example of how UART works in Aruino platform. For this, we will be using a pair of Arduino Uno devices to communicate with each other through their UART ports. Arduino has a serial library to communicate through UART. The following are some specific details related to the Arduino serial library.</p><p style="text-align: justify;"></p><ul><li>The start bit is 0 during a clock interval.</li><li>The end bit is 1 during a clock interval.</li><li>By default, there is no parity bit. If we want, we can set it to odd or even parity depending on our preference.</li><li>There are 8 data bits.</li><li>The data bits are sent in the least significant bit (LSB) first order.</li></ul><div>Let's say we want to send the character 'A' from one Arduino device to which the second device responds with the character 'B'. First of all, let's see how these two characters would be represented in the UART.</div><div><br /></div><p></p><div style="text-align: justify;"><b>Sending character 'A':</b></div><div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">ASCII representation: 01000001</div><div style="text-align: justify;">LSB-first order: 10000010</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">[ start bit | data bits | end bit ]</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Frame pattern: [ 0 | 10000010 | 1 ]</div></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><b>Sending character 'B':</b></div><div><br /></div><div>ASCII representation: 01000010</div><div>LSB-first order: 01000010</div><div><br /></div><div>[ start bit | data bits | end bit ]</div><div><br /></div><div>Frame pattern: [ 0 | 01000010 | 1 ]</div><div><br /></div><div>The following two Arduino programs can be used for this purpose.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgG1wdVxwidju_kdqFMaIEWGwzepQNEE6Uz4zLOcIwtJoFqA557ztJ55AOveLBDLWQEyIXrrLIpvWiMRIpbWUT3P6KcJCisqKqVDs8tg56LMqEVqvTcoLswvYA6TFjUJW_DrZttVqZaparB9Dsgi_bvwspazmIqRhnRQ7FYN39dET51iwqwPLAbmOmq/s300/uart-sender-arduino-screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="182" data-original-width="300" height="182" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgG1wdVxwidju_kdqFMaIEWGwzepQNEE6Uz4zLOcIwtJoFqA557ztJ55AOveLBDLWQEyIXrrLIpvWiMRIpbWUT3P6KcJCisqKqVDs8tg56LMqEVqvTcoLswvYA6TFjUJW_DrZttVqZaparB9Dsgi_bvwspazmIqRhnRQ7FYN39dET51iwqwPLAbmOmq/s1600/uart-sender-arduino-screenshot.png" width="300" /></a></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIkxzqV8iyMAUnEUlSCEsxzEvJRt-e8gRfFIYaOTKe4ICt08YhHLrFAnOaCKNIjcuK74ftCXq1J6McB__kPmDAjRkgj7fU6Ce73MzpGngfknyVI9zvS6p3vnFhO7oIJgNiRGrbvCBdL0tEgKMlpRLZxuGvG9dtNm9WnhxGXYR1Lb0-gPCdqx3BAHmC/s368/uart-receiver-arduino-screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="276" data-original-width="368" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIkxzqV8iyMAUnEUlSCEsxzEvJRt-e8gRfFIYaOTKe4ICt08YhHLrFAnOaCKNIjcuK74ftCXq1J6McB__kPmDAjRkgj7fU6Ce73MzpGngfknyVI9zvS6p3vnFhO7oIJgNiRGrbvCBdL0tEgKMlpRLZxuGvG9dtNm9WnhxGXYR1Lb0-gPCdqx3BAHmC/s320/uart-receiver-arduino-screenshot.png" width="320" /></a></div><br /></div>The two Arduino devices need to be connected with each other through their relevant pins. The Tx pin of the first Arduino should be connected to the Rx pin of the second device. Similarly, the Tx pin of the second Arduino device should be connected with the Rx pin of the first device. Furthermore, we should connect two GND pins of the two devices to have a common ground. The UART communication between these two devices can be observed using a logic analyser. We will connect the ground pin of the logic analyser to one of the GND pins of an Arduino. Then, channel-0 pin of the logic analyser can be connected to the Tx pin of the first Arduino. Similarly, the channel-1 pin of the logic analyser is connected to the Tx pin of the second Arduino. The following picture illustrates this wiring.</div><div style="text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp5fmuDbJhKU53DAk96E0z-Ji_ZPKMnq9xrh3JLApVRYFKlyhMnyBixUQcVDSishsmCSAF0a---M2WzEZQ7tleLLGmOlxP5s4boEgTpYD8k3rhjZz9FY-01ngXuKwFZir8c2q3QxGTTToj1PczR5wuWNmLszMGuK2CkClCgWN6z5XLR0k8bEY8DHoS/s4000/uart-hardware-wiring.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="4000" data-original-width="2250" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp5fmuDbJhKU53DAk96E0z-Ji_ZPKMnq9xrh3JLApVRYFKlyhMnyBixUQcVDSishsmCSAF0a---M2WzEZQ7tleLLGmOlxP5s4boEgTpYD8k3rhjZz9FY-01ngXuKwFZir8c2q3QxGTTToj1PczR5wuWNmLszMGuK2CkClCgWN6z5XLR0k8bEY8DHoS/w225-h400/uart-hardware-wiring.jpg" width="225" /></a></div><br /><div style="text-align: justify;">Now, let's fire up the Logic 2 program on the host computer to view the data captured by logic analyser on its channel-0 and channel-1 each representing the bits traveled in the Tx pins of each Arduino. The following screenshot illustrates the UART frames went on the two directions. If you watch carefully, you will see that the transmitted bit pattern is equal to the frame patterns that we identified previously for characters 'A' and 'B'.</div><div style="text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5lBtMOrolwNNxXgSVofn3qeAhxhX4B-DZUpyGwOXrbDqMPKg9KIRFPpHYocWcXPffr62Kbd6SP5m3m1OIdKSS-obWATF-gLK5lFQsL0aekYNcIAgP8if7nVpxxGpo93SKtdpH_Rmwu0BbbsFv7JgIlWmA9XcRDuY1RHgj26nrs0ceYdzOGAfsSJlr/s1248/uart-write-A-receive-B-logic-pro-window.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="233" data-original-width="1248" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5lBtMOrolwNNxXgSVofn3qeAhxhX4B-DZUpyGwOXrbDqMPKg9KIRFPpHYocWcXPffr62Kbd6SP5m3m1OIdKSS-obWATF-gLK5lFQsL0aekYNcIAgP8if7nVpxxGpo93SKtdpH_Rmwu0BbbsFv7JgIlWmA9XcRDuY1RHgj26nrs0ceYdzOGAfsSJlr/w640-h120/uart-write-A-receive-B-logic-pro-window.png" width="640" /></a></div><br /><div style="text-align: justify;">Let's change the second Arduino's program to send back character '@' instead of 'B'. That means, the bit pattern it sends back has to be different.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><b>Sending character '@':</b></div><div><div><br /></div><div>ASCII representation: 01000000</div><div>LSB-first order: 00000010</div><div><br /></div><div>[ start bit | data bits | end bit ]</div><div><br /></div><div>Frame pattern: [ 0 | 00000010 | 1 ]</div></div><div><br /></div></div><div style="text-align: justify;">In the program code shown above, there is a commented line representing the way we send character '@' from the second Arduino. This time, when we observe this new response, we will see the following output on the logic analyser window.</div><div style="text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhHxEFgrq2mf5vkN8wCSAymLhLqfvUmkFo0jlPcgzEpU7zQiafSY96lKX7KCO90L9IwiZhWQj6OdkAxEs5j5oxUfaaalVBsToRuQ9fSKLlMYGFwjOUQ5nEHJJ5b_zb3eU8wRFWr5Kn5T8M1ybOoVpl7-CKJnMwQyctZ4t5In3fDLJ_yPaDnxgy-N5S/s1243/uart-write-A-receive-AT-logic-pro-window.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="231" data-original-width="1243" height="118" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhHxEFgrq2mf5vkN8wCSAymLhLqfvUmkFo0jlPcgzEpU7zQiafSY96lKX7KCO90L9IwiZhWQj6OdkAxEs5j5oxUfaaalVBsToRuQ9fSKLlMYGFwjOUQ5nEHJJ5b_zb3eU8wRFWr5Kn5T8M1ybOoVpl7-CKJnMwQyctZ4t5In3fDLJ_yPaDnxgy-N5S/w640-h118/uart-write-A-receive-AT-logic-pro-window.png" width="640" /></a></div><br /><div style="text-align: justify;">This simple demonstration illustrates how data are included in UART communication protocol. By observing the channel using a logic analyser, it is actually possible to view the data being transferred. Let's explore how another embedded communication protocol works in another blog post.</div>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-15679815952929458632023-03-31T19:17:00.002+05:302023-04-01T15:19:06.197+05:30Observing Digital Signals using Logic Analysers<div style="text-align: justify;">While working with embedded systems, we come across various moments where it is needed to observe a digital signal produced by a device. Some devices produce digital output through their GPIO pins to control various other peripheral devices. Meanwhile, there are sensors that produces digital output that can be read by a microcontroller/SoC. Furthermore, there are communication happening between multiple devices using digital protocols. Being able to observe any such digital signal helps to debug things when they are not functioning as expected. Although the obvious tool for observing signals is oscilloscope, there is a much better hardware device that is purpose-built for observing digital signals: logic analyser. </div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbO8KC5-AOqCDJY5lsXB8zrdZcoIV5xYO1dAULLw2DeH4oLv_TvlOXrcHgGwiHg-UiUls2WCns4r-mjNPg6UzbtZQpfd_tf9o0LCqgNjvF68Uylp6b9pQHPKMgeJtBwYqVAG2-Rnnr4fmIsmSVCWKsImTLxbSqHyo8NG5TCbmtXkDRfL9B0Lgsy0ji/s600/08938-01.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbO8KC5-AOqCDJY5lsXB8zrdZcoIV5xYO1dAULLw2DeH4oLv_TvlOXrcHgGwiHg-UiUls2WCns4r-mjNPg6UzbtZQpfd_tf9o0LCqgNjvF68Uylp6b9pQHPKMgeJtBwYqVAG2-Rnnr4fmIsmSVCWKsImTLxbSqHyo8NG5TCbmtXkDRfL9B0Lgsy0ji/s320/08938-01.jpg" width="320" /></a></div><br />A logic analyser has a collection of input puts through which we can input digital signals. The device would read these pins and transfer the identified digital values to an attached computer. A specialised software running on the computer helps to visualise these data against time. Depending on the features of the software, it would be possible to decode a signal and take any usable data out in addition to simple observation of the signal. The <i>Saleae Logic</i> is such a logic analyser product that has multiple variants. I'm using the 8-channel version of the product that can be used to observe 8 digital signals at the same time. The device can be connected to a computer through the USB port. The host computer can run the official software application provided by the manufacturer, called Logic 2, which can be downloaded from their website (<a href="https://www.saleae.com/downloads">https://www.saleae.com/downloads</a>).</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLjmZ4uz8fAMR0UzQWpunCpcxiacCJ6Lj6F_NdUzAC9OF0AtGytvkAJLhg0XTO4GgeI13ZqYckchODRUtI0wQl-_Laht0KZ7Cy4S78vWmhzUyHJz6tbCNoG_Z2BYuHCR32o_z3z4uKMYnl3uea5R982oi2FboPQ_qt8IX4NOPUASQQ_itpPyLhLbra/s335/pin13-blink-arduino-screenshot.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="269" data-original-width="335" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLjmZ4uz8fAMR0UzQWpunCpcxiacCJ6Lj6F_NdUzAC9OF0AtGytvkAJLhg0XTO4GgeI13ZqYckchODRUtI0wQl-_Laht0KZ7Cy4S78vWmhzUyHJz6tbCNoG_Z2BYuHCR32o_z3z4uKMYnl3uea5R982oi2FboPQ_qt8IX4NOPUASQQ_itpPyLhLbra/s320/pin13-blink-arduino-screenshot.png" width="320" /></a></div>Let's explore how we can use Saleae Logic device to observe a signal. For this purpose, we are going to use an Arduino Uno device as the target device being observed. We are going to turn a digital output pin of the Arduino Uno to switch between high and low logic states by programming it to run a small code. So, program the Arduino Uno device to run the following code as the first step. This program is simply switching the pin 13 to HIGH and LOW states with a small time delay in between. Since there is a 1000 milliseconds (1 second) delay in between, we should be able to observe the digital output staying in HIGH and LOW states each 1 second time period.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhonxrwVOzAGioZ48ciy6NCYQdOWrWxLapEAiGJBkdUxyCJxNvEu_wUsa2-aonwKVuEGFLX7hPZ0M6mk5FYZHOOQ4vU-58yB4LYuQHssomsrlmD40mFy54WCkEY78duRzo8M0Sfi3d8G9pimmPHEpX7usbBuO-j_va3jac7FSW-mEKLcYTTTFQ1PUA0/s4000/pin13-blink-hardware-wiring.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="4000" data-original-width="2250" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhonxrwVOzAGioZ48ciy6NCYQdOWrWxLapEAiGJBkdUxyCJxNvEu_wUsa2-aonwKVuEGFLX7hPZ0M6mk5FYZHOOQ4vU-58yB4LYuQHssomsrlmD40mFy54WCkEY78duRzo8M0Sfi3d8G9pimmPHEpX7usbBuO-j_va3jac7FSW-mEKLcYTTTFQ1PUA0/s320/pin13-blink-hardware-wiring.jpg" width="180" /></a></div>Once programmed, it is the time to observe the output using logic analyser. Connect the logic analyser to the computer through the USB port and launch the Logic 2 software on the computer. Connect the ground pin of the logic analyser to a ground pin of the Arduino Uno device. Then, let's connect first pin (pin 0) of the logic analyser to the pin 13 of the Arduino Uno. The following figure illustrates this wiring between the logic analyser and Arduino Uno devices. The logic analyser has nice clips that can be attached to jumper wires connected to Arduino Uno's pins. Now, powering up the Arduino Uno device should result in its digital pin 13 going high and low, which will be captured by the logic analyser and fed to the computer. The pin 13 value going high and low should be visible in Logic 2 software window in the specific channel --- channel 0 in this particular case. The following figure illustrates the signal observation on the Logic 2 software. It should be visible that the timing set by program code are very closely achieved by the Arduino Uno device.</div><div style="text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicusTRrSBCd7LfbMiJF28KTtxKLPCbxbwNG5R2zU-A6juKyaXyVC_JfcCtERCpxRiPwFWZEq6zNLzZwAhtLs8l-IautbTFUEI5SVK55iY2HRYqzPuAelKr_--gYhqwOUg18HUBB50QjfgUZ1t_CBOGnuGh7PjMTg3Lhrh_kmzdigMNz7zm2ghsqm8X/s1313/pin13-blink-logic-pro-window.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="735" data-original-width="1313" height="324" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicusTRrSBCd7LfbMiJF28KTtxKLPCbxbwNG5R2zU-A6juKyaXyVC_JfcCtERCpxRiPwFWZEq6zNLzZwAhtLs8l-IautbTFUEI5SVK55iY2HRYqzPuAelKr_--gYhqwOUg18HUBB50QjfgUZ1t_CBOGnuGh7PjMTg3Lhrh_kmzdigMNz7zm2ghsqm8X/w579-h324/pin13-blink-logic-pro-window.png" width="579" /></a></div><br /><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Out of curiosity, I decided to attach the oscilloscope's probe to the ground and pin 13 of the Arduino Uno device to see how the digital signal is visualised on it. The following two figures show how the hardware wiring and the oscilloscope display looked like.</div><div style="text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeUDRteanZUtc70WwaJ6VGZxt1Z9wVYx5EmdBtPRptTVtR4yHWjtI9FwdEyyuP-wGLMDrOoJMlp93U6ONRGouu6g7ZIkdU3LVOuPbPopW7T9cFhyyGCaMPp1De1kyqx89bs5uyj_DBNMkT8ys7u0ceHN_8o8Fwrw63Xt3r5TURvExghiwJWEe2p1jV/s4000/pin13-blink-hardware-wiring-with-oscilloscope.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="4000" data-original-width="2250" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeUDRteanZUtc70WwaJ6VGZxt1Z9wVYx5EmdBtPRptTVtR4yHWjtI9FwdEyyuP-wGLMDrOoJMlp93U6ONRGouu6g7ZIkdU3LVOuPbPopW7T9cFhyyGCaMPp1De1kyqx89bs5uyj_DBNMkT8ys7u0ceHN_8o8Fwrw63Xt3r5TURvExghiwJWEe2p1jV/s320/pin13-blink-hardware-wiring-with-oscilloscope.jpg" width="180" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDaj4Ozb8a_mm30AoVrfxXOznEh_xsE-rqcPG-oWymbN7x5sGASW3QbtubbgXRcExXF5iOfY5tjdy1JRPfRsXuCwMV4JJUGmA4IbOs6If63zgFFIa4_oYF49MujS38Holcz0wOEI9i-4Hnm292sAYn_tE8gKHOKwTL_1xR3VeTUFedf_-7GwxVAMbu/s800/pin13-blink-oscilloscope-window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="800" height="313" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDaj4Ozb8a_mm30AoVrfxXOznEh_xsE-rqcPG-oWymbN7x5sGASW3QbtubbgXRcExXF5iOfY5tjdy1JRPfRsXuCwMV4JJUGmA4IbOs6If63zgFFIa4_oYF49MujS38Holcz0wOEI9i-4Hnm292sAYn_tE8gKHOKwTL_1xR3VeTUFedf_-7GwxVAMbu/w521-h313/pin13-blink-oscilloscope-window.png" width="521" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">That's all for this blog post. Using logic analyser, let's explore how to intercept and understand digital communication protocols in some future blog posts. </div><div style="text-align: justify;"><br /></div>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com2tag:blogger.com,1999:blog-2381761802615660705.post-35340978637272616792023-03-13T15:48:00.004+05:302023-03-13T15:50:29.546+05:30Troubles, Confusion, and Hope<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPDJhk4mZO6BU6qjrCUN-rpIPSJiMOOvuUqP76LPrfe_1A-n9LOPqNI76lM6TWWMuj9OLVT_OilOvMNC70KB11Rri5xTuYm5YDjo1yjUghQVfikmI4j51HFIJFnT9FqxLRcYACcDj8PoZ5cPhsyIISQeMIfBxDBQhTtT1FihU9QdRp-bF6nYj9ZdvF/s4000/20230306_163306.jpg" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="4000" data-original-width="2250" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPDJhk4mZO6BU6qjrCUN-rpIPSJiMOOvuUqP76LPrfe_1A-n9LOPqNI76lM6TWWMuj9OLVT_OilOvMNC70KB11Rri5xTuYm5YDjo1yjUghQVfikmI4j51HFIJFnT9FqxLRcYACcDj8PoZ5cPhsyIISQeMIfBxDBQhTtT1FihU9QdRp-bF6nYj9ZdvF/w225-h400/20230306_163306.jpg" width="225" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">The paddy fields in Thalpavila.</td></tr></tbody></table><div style="text-align: justify;">Last long weekend, I went to Matara to my home town with my wife. We don't get to travel to Matara very often --- just once a month in the best case. This is mostly due to us getting busy over the weekends. The renovation work at home in Matara has been progressing well, although in a slow pace since the last year. It's a pleasure to see the beautiful transformation of our childhood home getting refurbished and modernised. The economic hardships in the country challenged us in various stages of this project due to increase cost of raw material and labour. Although I carry my work with me to Matara hoping that I would be able to do some work there, I didn't do any work at home in the last weekend. It would be unfair to my family if I spend holidays in front of my computer doing works; holidays are holidays after all. It's a safe haven for us to take a break from work and have a breath and good sleep.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">In Matara, my younger brother has a bicycle. Every time I go to Matara, I wanted to take it out and ride in the neighborhood. One day a few months back, I went on a ride across the village over a long distance. In that journey, I managed to go through roads that I had either never traveled or haven't traveled for a long time. In the last weekend, I took the bicycle to go all the way closer to the Kekanadura railway station. Although the expressed objective of this journey was to buy some bread, my real objective was to visit a water stream near Kenanadura railway station. Over 25 years ago, when I was in 6th, 7th, and 8th grades, I used to walk from home to Kekanadura to attend tuition classes in weekends. In evenings, after a class, I would walk with a few neighborhood friends back home, sipping an ice packet — not that drug, but a frozen sweetened beverage in a polythene packaging. Somewhere in between Kekanadura and Thalpavila — near modern-day railway station — there used to be this stream of water. It brought water, what I believe to be from Allakanda Reservoir, to the paddy fields all around that area. As kids, we used to stop by this stream, on our way home, to have a look at various types of fishes. This time after 25 years, my visit in a bicycle to this place revealed that a lot of construction work has happened and the stream is gone. It is sad that urbanisation is taking over the nature.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkLQzx7itbud58cLsquvFfr9znsJ8V4ELTalePg8XIHqHmOqkwNMxgCngOBPS6hbirnX39T2lFuSGt-yGTBx4sbc0slKTMoIkEwxNMDL7c2-370VJWYKoi45AMzasOH4tgN_mPkmuggfXlqOBLhKlUPa0xaSC7TM6kRxFrq-QNhSeZrSt5AcZLYm7W/s4000/20230311_165840.jpg" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="2250" data-original-width="4000" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkLQzx7itbud58cLsquvFfr9znsJ8V4ELTalePg8XIHqHmOqkwNMxgCngOBPS6hbirnX39T2lFuSGt-yGTBx4sbc0slKTMoIkEwxNMDL7c2-370VJWYKoi45AMzasOH4tgN_mPkmuggfXlqOBLhKlUPa0xaSC7TM6kRxFrq-QNhSeZrSt5AcZLYm7W/w400-h225/20230311_165840.jpg" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">The lab with new arrangement of equipment.</td></tr></tbody></table><br /> In my research, I have been struggling to complete many work I had started since last year. The year 2022 has been mostly occupied with various new administration duties at the university. Due to that, I had less time to make progress in my research, impacting negatively to my profile. This year, I got one paper accepted in MDPI Applied Sciences journal, which was a much needed achievement to start this year 2023. Meanwhile, I'm facing a serious challenge from the ongoing research project funded by Dialog Axiata. The research assistant and the interns assigned to the project were making very little progress in the project, which was very tight in terms of timeline. I was constantly under pressure to move even tiny steps forward in that project's tasks. I think, there is an issue in the way I have been recruiting and managing human resources. This project taught me many lessons on how to manage a project and how to deal with employees. Just throwing people into a project and expecting that they would do a good job on their own is not realistic; as PI, I have to proactively engage and monitor the progress of a project from the beginning.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">In a tough time like this, it is necessary to have a proper research team who can help each other and make everybody in company. The lack of such a team is impacting my research negatively. Under such circumstances, I've found a good companion who has the same enthusiasm towards research as myself. Akila was a Master's degree student, whom I supervised for his final project. Since I started supervising his project, we turned into good friends and are in constant contact. He successfully completed his project and submitted his thesis recently. He regularly visits UCSC and do various kinds of experiments whenever he finds something interesting. It is a great pleasure to work with him. Last few days, I got together with him and arranged the lab in a novel way so that we now have a better working environment in the lab. I hope that the support I'm getting from him would help me to keep my enthusiasm high on continuing my research work.</div>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-36315041988370074542023-02-04T22:19:00.000+05:302023-02-04T22:19:12.560+05:30Blogging: My Lost Habit<p>I've used to be a very enthusiastic blog writer over a decade ago. With time, the number of posts I write per year decreased drastically. By the year 2022, I was barely writing a single post — even that's after noticing the risk that I might go without a single post in that year. </p><p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7pTEmFUFM7uJew9Ws83aPpHByJPs7GbtE1JMzZNNwuneQxn5oCjftO3to4n-KLspw14ESdvAuTPud2CtTYNWqtWEB0FdZdsVCXQWD5kcr-IJPvXLnJSJ6g4GnQ67JnTnscmHsXnPGnqNPj1x47RNjGoDilY9R3uu3xSGpqL_sv4hbgJXAp5yzX2YA/s3264/20130915_122352.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="2448" data-original-width="3264" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7pTEmFUFM7uJew9Ws83aPpHByJPs7GbtE1JMzZNNwuneQxn5oCjftO3to4n-KLspw14ESdvAuTPud2CtTYNWqtWEB0FdZdsVCXQWD5kcr-IJPvXLnJSJ6g4GnQ67JnTnscmHsXnPGnqNPj1x47RNjGoDilY9R3uu3xSGpqL_sv4hbgJXAp5yzX2YA/w400-h300/20130915_122352.jpg" width="400" /></a></td></tr><tr align="center"><td class="tr-caption">The benches at Kyunpook National University (KNU) in Daegu, South Korea. The picture was taken on a Sunday in mid-September, 2013. I was waiting for someone to meet me there.<br /></td></tr></tbody></table>Back in the days, most of my blog posts were on new technical knowledge that I had acquired. For example, while doing some project work, a research work in the lab, or even when trying to do some course work-related task, I've come across various challenging situations. The answers to such challenges were found by either searching in the web, or by exploring myself. Solutions I find in such situations are so precious and potentially can arise in the future again, to me and to others. Due to this very reason, such things deserve to be written down somewhere that myself and other's can easily find — that's what the blog is for. I've written very detailed blog posts on how to do this and that over the years.<br /></p><p>In addition to technical posts, I have occasionally written about important events, experiences, and thoughts that I've came across. After several years, these special posts are a pleasure to read; they refresh memories and take me back across time.</p><p>So, all these facts points to the importance of keep writing blogs. In this year 2023, I'll restart the blogging habit and try to write as much as possible.</p>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-593042647290272542022-10-05T11:47:00.006+05:302022-10-05T11:50:38.864+05:30Editing Binary Files on Vim Editor<p> Here's a quick method I use to edit binary files on the vim editor. Suppose that the binary file name that we need to edit is called <i>hello</i>. Let's open it using the <i>xxd</i> hex viewer utility and pipe it to the <i>vim</i> editor as follows using the terminal. This produces the hex view of the binary file on the <i>vim</i> editor.<br /></p><p><span style="font-family: courier;"><b>xxd hello | vim -</b></span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjyK7N3tGZtRQDM2t1zBln34aEJQifUuy1CrqwvTw4YNZHndoSvLcMISrzwDZjIl6Zzd-Z8d4v-jldngK1qmFBrZ-rD-CzzbhmIX-j3gkKqtw0Gm6P2WeuSbEj8YqZ_ZtaJSl7sFJx0JMWT6bdIEdd20FY2OpSOgwGUGTlaKoWahgLLGvGfd1eu3gFj" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1382" data-original-width="2004" height="382" src="https://blogger.googleusercontent.com/img/a/AVvXsEjyK7N3tGZtRQDM2t1zBln34aEJQifUuy1CrqwvTw4YNZHndoSvLcMISrzwDZjIl6Zzd-Z8d4v-jldngK1qmFBrZ-rD-CzzbhmIX-j3gkKqtw0Gm6P2WeuSbEj8YqZ_ZtaJSl7sFJx0JMWT6bdIEdd20FY2OpSOgwGUGTlaKoWahgLLGvGfd1eu3gFj=w553-h382" width="553" /></a></div>Now, we are good to go with editing the hex values in the file as you would do with any text file on the <i>vim</i> editor. Once we are done with the editing, we can now convert this updated hexdump view on the <i>vim</i> editor back to a new binary file. In order to do that, go to the command mode of the vim editor, and type and enter the following command. It will save the edited binary into a new file; the new file can be named anything while I have made it to be <i>hello-new</i>.<br /><p></p><p><b><span style="font-family: courier;">%!xxd -r > hello-new</span></b></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhAUTTWO3QEfXMiaDoUDxu_GQZJ_r9399lXs8EiXEb6lhyo8Oijbv6XEBBObgd2E7IUWnVYmGH4nwJaUA-HDb492KXBT6MPA44J2ykG9Pd33XcTyBk0uTG7HffE3BZF4Fr0Oo73qCXlN_Z-1oM15zb30iEANxwG5zxM5EYCth58ubQNOIniTA-qCdsT" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1382" data-original-width="2004" height="385" src="https://blogger.googleusercontent.com/img/a/AVvXsEhAUTTWO3QEfXMiaDoUDxu_GQZJ_r9399lXs8EiXEb6lhyo8Oijbv6XEBBObgd2E7IUWnVYmGH4nwJaUA-HDb492KXBT6MPA44J2ykG9Pd33XcTyBk0uTG7HffE3BZF4Fr0Oo73qCXlN_Z-1oM15zb30iEANxwG5zxM5EYCth58ubQNOIniTA-qCdsT=w557-h385" width="557" /></a></div><p>Now, you can safely quit the vim editor with <b><span style="font-family: courier;">q!</span></b> on the command mode as you would always quit it. :) Cheers!</p><p>References:</p><p>[1] <a href="https://vi.stackexchange.com/questions/343/how-to-edit-binary-files-with-vim">https://vi.stackexchange.com/questions/343/how-to-edit-binary-files-with-vim</a><br /></p><p></p>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-24728184097953077162021-12-14T17:38:00.003+05:302021-12-14T17:43:55.689+05:30Creating a Window 10 Live USB Stick on an Ubuntu GNU/Linux Computer<p style="text-align: justify;">As a hardcore user of GNU/Linux systems, I don't usually come across any requirement to use Windows operating system. However recently, I had to install Windows in somebody else's computer as a help. It took me a while to find out how to prepare a installation USB drive for the purpose. Here's the steps I followed, hoping that my future self may need to refer back one day.</p><p style="text-align: justify;">1. Download Window 10 ISO file from the official Microsoft website.</p><p style="text-align: justify;"><br /></p><p style="text-align: justify;">2. Download and install WoeUSB-ng on the Ubuntu computer using the information in the following Github page: <a href="https://github.com/WoeUSB/WoeUSB-ng">https://github.com/WoeUSB/WoeUSB-ng</a></p><p style="text-align: justify;"><br /></p><p style="text-align: justify;">3. Run the following command to make the USB device (/dev/sdb in my case) bootable with the downloaded Windows ISO file. If there are files in the Windows 10 ISO file that are bigger than 4GB, the following command will automatically revert to NTFS format. </p><p style="text-align: justify;"></p><div><br /></div><div><span style="white-space: pre;"> </span><span style="font-family: courier;"><b>sudo woeusb --target-filesystem FAT --device ~/Downloads/Win10_21H2_EnglishInternational_x64.iso /dev/sdb </b></span></div><div><span style="font-family: courier;"><b><br /></b></span></div><div><b>References:</b></div><p></p><div><div style="text-align: justify;"><ol><li><a href="https://www.microsoft.com/en-us/software-download/windows10ISO">https://www.microsoft.com/en-us/software-download/windows10ISO</a></li><li><a href="https://github.com/WoeUSB/WoeUSB-ng">https://github.com/WoeUSB/WoeUSB-ng</a></li><li><a href="https://askubuntu.com/questions/1097560/woeusb-error-code-256-with-ntfs-formatted-usb">https://askubuntu.com/questions/1097560/woeusb-error-code-256-with-ntfs-formatted-usb</a></li></ol></div></div>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-37216163874042397632021-03-25T12:32:00.001+05:302021-03-25T12:37:03.733+05:30Enabling Hibernation in Ubuntu 20.04 LTS using a Swap File<p>Enabling of the hibernation option on Ubuntu 20.04 LTS didn't work in the way I used to do. So, I had to explore further and do it slightly differently. This blog post records those things I did to get hibernation option working.</p><p><b>1. </b>First of all, create a swap file using the following commands.</p><p><b><span style="font-family: courier;">sudo fallocate -l 17G /swapfile<br /><br />sudo chmod 600 /swapfile<br /><br />sudo mkswap /swapfile<br /><br />sudo swapon /swapfile</span></b><br /><br />Once done, add an entry to the end of <span style="font-family: courier;"><b>/etc/fstab</b></span> file to make use of this swap file as follows.</p><p><b><span style="font-family: courier;">/swapfile none swap sw 0 0</span></b></p><p><b>2.</b> Check the UUID of the partition where the swap file is located using the following command. <br /></p><p><b><span style="font-family: courier;">cat /etc/fstab</span></b></p><p>Take note of the UUID string, which we will need in a later step.</p><p><b>3.</b> Check the offset to the swapfile with in the storage device using either of the following commands. Take note of that offset value.<br /></p><p><span style="font-family: courier;"><b>sudo filefrag -v /swapfile | awk '{ if($1=="0:"){print substr($4, 1, length($4)-2)} }'<br /><br />sudo swap-offset /swapfile</b></span></p><p><b>4.</b> Now, open the <span style="font-family: courier;"><b>/etc/default/grub</b></span> file and add update the correct line as follows.</p><p>Original line:</p><p><b><span style="font-family: courier;">GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"</span></b></p><p>Updated line: <br /></p><p><b><span style="font-family: courier;">GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=UUID=a27fc21e-3315-4497-99aa-1fe7fad64091 resume_offset=9807872" </span></b><br /></p><p>Note that the UUID value and the resume offset value are found using the above steps 2 and 3.<br /></p><p>Once this grub file is updated, run the following command to take the changes effect.</p><p><span style="font-family: courier;"><b>sudo update-grub</b></span></p><p><b>5.</b> Test whether the hibernation option is working now, use either of the following commands. I personally prefer the second command as it provides some verbose output while the system is being hibernated and being resumed later.<br /></p><p><b><span style="font-family: courier;">sudo systemctl hibernate</span></b></p><p><b><span style="font-family: courier;">sudo pm-hibernate <br /></span></b></p><p>Cheers!</p><p><br /><b>References:</b><br /></p><ol style="text-align: left;"><li><a href="https://linuxize.com/post/create-a-linux-swap-file/">https://linuxize.com/post/create-a-linux-swap-file/</a></li><li><a href="https://askubuntu.com/questions/1240123/how-to-enable-hibernate-option-in-ubuntu-20-04">https://askubuntu.com/questions/1240123/how-to-enable-hibernate-option-in-ubuntu-20-04</a></li><li><a href="https://wiki.archlinux.org/index.php/Power_management/Suspend_and_hibernate#Hibernation_into_swap_file">https://wiki.archlinux.org/index.php/Power_management/Suspend_and_hibernate#Hibernation_into_swap_file</a><br /></li></ol><p><br /></p>Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-43875652726992049112020-04-21T20:58:00.004+05:302020-04-21T21:02:20.456+05:30Encrypting Files Using GnuPG<div dir="ltr" style="text-align: left;" trbidi="on">
This post shows how to use GnuPG to encrypt and decrypt files on a Linux environment.<br />
<br />
1. If you haven't created your GnuPG key pair yet, you can use the following commands to create them and view their details.<br />
<br />
Create a pair of GnuPG keys using the following command.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><b>gpg --gen-key</b></span><br />
<br />
The keys and their relevant information are stored in .gnupg directory under your home directory. You can view the public keys in your keyring using the following command.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><b>gpg --list-key</b></span><br />
<br />
You can view the private keys using the following command.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><b>gpg --list-secret-keys</b></span><br />
<br />
2. Encrypting a file called "private-file.txt" can be done as follows. We can either specify a new name for the encrypted file or GnuPG will automatically name the new file by appending .gpg extension to the name of the plaintext file.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><b>gpg --encrypt --recipient your.email@gdomain.com private-file.txt</b></span><br />
<br />
<b><span style="font-family: "courier new" , "courier" , monospace;">gpg --output encrypted.gpg --encrypt --recipient your.email@gdomain.com private-file.txt</span></b><br />
<br />
3. Decrypting a file called "private-file.txt.gpg" can be done as follows. Similar to the previous case, we can either specify a name for the decrypted file or leave it to the default.<br />
<br />
<b><span style="font-family: "courier new" , "courier" , monospace;">gpg --output private-file.txt --decrypt private-file.txt.gpg </span></b><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><b>gpg --decrypt encrypted.gpg > private-file.txt</b></span><br />
<br />
4. Encrypting all the files in a directory can be done as follows.<br />
<br />
<b><span style="font-family: "courier new" , "courier" , monospace;">gpg --encrypt-files --recipient </span></b><b><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><b>your.email@gdomain.com</b></span> /path/to/the/directory/*</span></b><br />
<br />
5. Decrypting all the .gpg files in a particular directory can be done as follows.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><b>gpg --decrypt-files /path/to/the/directory/*.gpg</b></span><br />
<br />
<b>Resources: </b><br />
<br />
1. <a href="https://blog.ghostinthemachines.com/2015/03/01/how-to-use-gpg-command-line/">https://blog.ghostinthemachines.com/2015/03/01/how-to-use-gpg-command-line/</a><br />
<br />
2. <a href="https://www.gnupg.org/gph/en/manual.pdf">https://www.gnupg.org/gph/en/manual.pdf</a><br />
<br />
<div style="text-align: center;">
~*************~</div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-22555400002896187192020-04-17T21:00:00.000+05:302020-04-17T21:05:20.858+05:30Sending Secure Emails with OpenPGP<div dir="ltr" style="text-align: left;" trbidi="on">
Use of encryption in our electronic communication is essential to protect our security and privacy. Here's how we can use OpenPGP standard to send and receive emails securly. While there are many software tools to get this done, I prefer this way.<br />
<br />
1. Create a pair of GNU Pritty Good Privacy (PGP) keys using the following command.<br />
<br />
<b><span style="font-family: "courier new" , "courier" , monospace;">gpg --gen-key</span></b><br />
<br />
The keys and their relevant information are stored in <span style="font-family: "courier new" , "courier" , monospace;"><b>.gnupg</b></span> directory under your home directory. You can view the public keys in your keyring using the following command.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><b>gpg --list-key</b></span><br />
<br />
You can view the private keys using the following command.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><b>gpg --list-secret-keys</b></span><br />
<br />
2. Log-in to your email account from Thunderbird email client. Thunderbird is available by default in most Linux systems including Ubuntu Linux.<br />
<br />
3. Install the Enigmail plug-in in Thunderbird. Since we have already created the GPG keys, Enigmail will automatically detect them and start using them. If we didn't have created the keys already, Enigmail facilitates creating them as well.<br />
<br />
4. From the menu bar of Thunderbird, select the <b>Enigmail</b> item and then <b>Key Management</b> option, which will display your key. Right-click on your key and select the option "Upload Public Keys to Kerservers". This will post your public key to a public key server.<br />
<br />
5. Now, we are good to go with sending and receiving encrypted emails. When you compose an email with Thunderbird, there is a padlock button that stands for encryption of the email. When you enable it and then hit send button, Enigmail will prompt you if the public key of the recipient is not available locally. In that case, it will also facilitate to obtain the required keys from keyservers as well.<br />
<br />
References:<br />
<br />
1. <a href="https://emailselfdefense.fsf.org/en/">https://emailselfdefense.fsf.org/en/</a><br />
<br />
2. <a href="https://blog.ghostinthemachines.com/2015/03/01/how-to-use-gpg-command-line/">https://blog.ghostinthemachines.com/2015/03/01/how-to-use-gpg-command-line/</a> <br />
<br />
<div style="text-align: center;">
~***********~</div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-40118889493537661972020-03-31T23:20:00.001+05:302020-03-31T23:20:58.823+05:30Setting up Hibernation on Ubuntu 18.04 LTS<div dir="ltr" style="text-align: left;" trbidi="on">
The ability to hibernate the computer when we are done for the day and get back to where we left next time was a useful feature we had in Ubuntu sometime back by default. However, unfortunately, recent Ubuntu versions does not offer this feature off-the-shelf. Recently, I wanted to get this feature into my laptop running Ubuntu 18.04 version and following are the steps I followed. <br /><br /><b>1. Creating a swap file</b><br />
<br />
My laptop has 8GB of RAM. Therefore, we need to have a swap space of at least the same size of RAM. Since I didn't want to allocate a partition partition, I created a swap file as follows.<b><span style="font-family: "Courier New", Courier, monospace;"> </span></b><br />
<br />
<b><span style="font-family: "Courier New", Courier, monospace;">sudo fallocate -l 8G /swapfile2<br />sudo chmod 600 /swapfile2<br />sudo mkswap /swapfile2<br />sudo swapon /swapfile2</span></b><br />
<br />
Append the following line to <b>/etc/fstab</b> file in your system.<br />
<br /><b><span style="font-family: "Courier New", Courier, monospace;">/swapfile2 none swap sw 0 0</span></b><br /><br /><b>2. Enabling hibernation</b><br />
<br />
Check the UUID of the device where swapfile is located using the following command. The UUID is a very long number that you can see in the output.<br />
<br /><span style="font-family: "Courier New", Courier, monospace;"><b>sudo findmnt -no SOURCE,UUID -T /swapfile2</b></span><br /><br />Install the following tool.<br />
<br /><b><span style="font-family: "Courier New", Courier, monospace;">sudo apt install uswsusp</span></b><br /><br />
Run the following command. When prompted, go ahead without a valid swap space by giving 'yes' as the response and then select the device partition where the swap file exists (don't select the swap file itself).<br />
<br /><b><span style="font-family: "Courier New", Courier, monospace;">sudo dpkg-reconfigure -pmedium uswsusp</span></b><br /><br />
I'm not sure whether I ran the following command next. Probably I did.<br />
<br /><span style="font-family: "Courier New", Courier, monospace;"><b>sudo update-initramfs -u</b></span><br /><br /><b>3. Enabling the resume from hibernation at next boot</b><br /><br />We need to update the <b>/etc/default/grub</b> file as follows.<br />
<br /><b><span style="font-family: "Courier New", Courier, monospace;">GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=UUID=<swap uuid>"</span></b><br /><br />
The following is how mine looks like after the modification.<br />
<br /><b><span style="font-family: "Courier New", Courier, monospace;">GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=UUID=cda0136e-ffd9-4a0c-8657-a6511517aa71"</span></b><br /><br /><b>4. Testing hibernation</b><br /><br />Run the following command to hibernate your computer. When you turn the computer on next time, it should resume the execution from where you left it when you run the following command.<br />
<br /><span style="font-family: "Courier New", Courier, monospace;"><b>sudo pm-hibernate</b></span><br /><br /><b>References:</b><br /><br />1. <a href="https://askubuntu.com/questions/6769/hibernate-and-resume-from-a-swap-file">https://askubuntu.com/questions/6769/hibernate-and-resume-from-a-swap-file</a><br /><br />2. <a href="https://askubuntu.com/questions/548015/ubuntu-14-04-sudo-pm-hibernate-doesnt-work">https://askubuntu.com/questions/548015/ubuntu-14-04-sudo-pm-hibernate-doesnt-work</a><br />
<br />
<div style="text-align: center;">
~******************~</div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-23418492488252345712019-01-29T00:01:00.000+05:302019-01-29T00:01:03.790+05:30Sending Samples to Python from GRC using ZMQ Sink<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
When we need to process some data generated by an SDR device, the most convenient approach we have currently is saving the data into a file and then reading the files from Python. However, if the requirement is to process data in real-time as they are generated from the SDR device, saving to a file is not the right way. GNURadio Companion software provides a special set of sink blocks which uses ZMQ messaging protocol for such purposes. This post demonstrates how to use one of such sink types in order to deliver raw samples generated by a GRC flow graph into a Python script.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(1) Create the following flow graph on GNURadio Companion. Instead of taking data from a real SDR device, we use two Signal Source blocks to generate two cosine wave signals with 3MHz and 5MHz frequencies. We set the sample rate to 4 MHz. The Throttle block is necessary to regulate the data flow through the flow graph since we are not using a real SDR hardware. Most importantly, we are using a ZMQ Push Sink block. Notice that we have given the localhost IP address and an arbitrarily selected port number as the destination of the data.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu0tXFPCmxQNGCuEtuIcWDPzqV8RjaiTepXbUU0rx4Qhd5e2HR8_lnWAy3jjNSr4kihCboYBRIuwqDqaK9Dl_GgbKRhyphenhyphenfH9gsUmlp8YL_l5rHuTlhoGlxbjYhGb8-cYEmL8V-7sGhVViM/s1600/grc-flow-graph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="294" data-original-width="507" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu0tXFPCmxQNGCuEtuIcWDPzqV8RjaiTepXbUU0rx4Qhd5e2HR8_lnWAy3jjNSr4kihCboYBRIuwqDqaK9Dl_GgbKRhyphenhyphenfH9gsUmlp8YL_l5rHuTlhoGlxbjYhGb8-cYEmL8V-7sGhVViM/s400/grc-flow-graph.png" width="400" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(2) Now, in order to capture the data, we need a Python script which implements a ZMQ Pull client. Create a Python program with the following content and save it as <b>client.py</b>.</div>
<div style="text-align: justify;">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">time</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">zmq</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">random</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">numpy</span> <span style="color: #008800; font-weight: bold;">as</span> <span style="color: #0e84b5; font-weight: bold;">np</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">matplotlib.pyplot</span> <span style="color: #008800; font-weight: bold;">as</span> <span style="color: #0e84b5; font-weight: bold;">plt</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">consumer</span>():
consumer_id <span style="color: #333333;">=</span> random<span style="color: #333333;">.</span>randrange(<span style="color: #0000dd; font-weight: bold;">1</span>,<span style="color: #0000dd; font-weight: bold;">10005</span>)
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"I am consumer #</span><span style="background-color: #eeeeee;">%s</span><span style="background-color: #fff0f0;">"</span> <span style="color: #333333;">%</span> (consumer_id))
context <span style="color: #333333;">=</span> zmq<span style="color: #333333;">.</span>Context()
consumer_receiver <span style="color: #333333;">=</span> context<span style="color: #333333;">.</span>socket(zmq<span style="color: #333333;">.</span>PULL)
consumer_receiver<span style="color: #333333;">.</span>connect(<span style="background-color: #fff0f0;">"tcp://127.0.0.1:5557"</span>)
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
buff <span style="color: #333333;">=</span> consumer_receiver<span style="color: #333333;">.</span>recv()
<span style="color: #008800; font-weight: bold;">print</span>(time<span style="color: #333333;">.</span>time())
data <span style="color: #333333;">=</span> np<span style="color: #333333;">.</span>frombuffer(buff, dtype<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">"float32"</span>)
data <span style="color: #333333;">=</span> data[<span style="color: #0000dd; font-weight: bold;">0</span>::<span style="color: #0000dd; font-weight: bold;">2</span>] <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1j</span><span style="color: #333333;">*</span>data[<span style="color: #0000dd; font-weight: bold;">1</span>::<span style="color: #0000dd; font-weight: bold;">2</span>]
<span style="color: #008800; font-weight: bold;">print</span>(<span style="color: #007020;">type</span>(data))
<span style="color: #008800; font-weight: bold;">print</span>(<span style="color: #007020;">len</span>(data))
<span style="color: #888888;">#plt.figure()</span>
<span style="color: #888888;">#plt.psd(data, NFFT=len(data), Fs=4e6, Fc=1e3)</span>
<span style="color: #888888;">#plt.savefig("psd.png")</span>
<span style="color: #888888;">#time.sleep(0.5)</span>
<span style="color: #888888;">#exit()</span>
consumer()
</pre>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(3) We need to start the client Python program first from a terminal.<br />
<br />
<b><span style="font-family: Courier New, Courier, monospace;">python client.py</span></b><br />
<br />
(4) Now, start the GNURadio Companion flow graph. On the terminal where our Python program running, we should be able to see the chunks of data coming now. The number of samples contained in each data set various over time which I'm not exactly sure why. Following screenshot shows the output on the terminal.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH1hAQO9PCgfAZpevj9IIybmdvJ0QATSegqNdnkLZm-eWqdyQk7VmFdS4ONPwaRAFdgOXBPEgR-LlryKfM1EFN8JYcNP4cGSYKtrgn1qN4Du56ANE10Sb-BQ8Bx1fHK45oEqMOrpew2ss/s1600/size-output.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="297" data-original-width="426" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH1hAQO9PCgfAZpevj9IIybmdvJ0QATSegqNdnkLZm-eWqdyQk7VmFdS4ONPwaRAFdgOXBPEgR-LlryKfM1EFN8JYcNP4cGSYKtrgn1qN4Du56ANE10Sb-BQ8Bx1fHK45oEqMOrpew2ss/s320/size-output.png" width="320" /></a></div>
<br />
(5) If we activate the commented lines, we can save a plot in a PNG file which shows the power spectral density (PSD) of the received signal. As expect, there are two peaks in both sides of the center frequency with a gap of 1 MHz. This is because our sampling rate was 4 MHz while there were two signals with 3MHz and 5MHz in the captured signal. Following figure shows that PSD graph.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH98-_B0-4oJHTZLBBBb1wgBq0fBzH-dCcTsXUH1187-14ZuEyGflbSWMYHtdJYQlRM16ksyOiPL9HXSOmJR7IalBZs0j_rCuaCO6wdwdWERPvocupUjzHMb8tza82ZprGkDsVJOnXbRg/s1600/psd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH98-_B0-4oJHTZLBBBb1wgBq0fBzH-dCcTsXUH1187-14ZuEyGflbSWMYHtdJYQlRM16ksyOiPL9HXSOmJR7IalBZs0j_rCuaCO6wdwdWERPvocupUjzHMb8tza82ZprGkDsVJOnXbRg/s400/psd.png" width="400" /></a></div>
<br />
The code for the Python script and the GRC flow graph file are kept in a Github repository to try it easily. Cheers!</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>Useful links:</b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>[1]</b> More reading on PyZMQ library.</div>
<div style="text-align: justify;">
<a href="https://learning-0mq-with-pyzmq.readthedocs.io/en/latest/pyzmq/patterns/pushpull.html">https://learning-0mq-with-pyzmq.readthedocs.io/en/latest/pyzmq/patterns/pushpull.html</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>[2]</b> A question in StackExchange where somebody had suggested to use ZMQ Sink.</div>
<div style="text-align: justify;">
<a href="https://dsp.stackexchange.com/questions/42928/how-do-i-extract-data-from-a-gnuradio-flowgraph-now-that-the-message-sinks-have">https://dsp.stackexchange.com/questions/42928/how-do-i-extract-data-from-a-gnuradio-flowgraph-now-that-the-message-sinks-have</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>[3]</b> The Github repository with my codes illustrating this work.</div>
<div style="text-align: justify;">
<a href="https://github.com/asanka-code/grc-zmq-data-transfer">https://github.com/asanka-code/grc-zmq-data-transfer</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-13580993108358276222019-01-06T19:01:00.000+05:302019-01-06T19:02:21.416+05:30Starting Viber with too large resolution<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
After installing a brand new Ubuntu 18.04 LTS on my computer, I made some adjustments to the font sizes of the operating system in order to make it better suit for my perception. However, I realized that something is wrong after installing Viber on my desktop. The GUI of the Viber application appears so huge that it falls off the resolution of the screen making it completely unusable. After searching on the web, the only solution I found was to start Viber using the terminal with an extra parameter called QT_SCALE_FACTOR. Following is the command which we should run on the terminal to start Viber with a usable scale.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(Note: <i>it is important to set the environmental variable first before invoking the Viber executable as shown.</i>)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b><span style="font-family: Courier New, Courier, monospace;">QT_SCALE_FACTOR=0.6 /opt/viber/Viber</span></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Reference:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
[1] <a href="https://askubuntu.com/questions/881679/viber-appears-huge-kubuntu-16-04">https://askubuntu.com/questions/881679/viber-appears-huge-kubuntu-16-04</a></div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-53907950273190642592018-12-30T05:26:00.000+05:302018-12-30T05:40:33.015+05:30Truly Reproducible Research Papers<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3cykVo8U8TKjfXcyDhP40C4Bl5g-R5jaSDyLFXv0-M_QykDFo9kJkzuvBDtuqeclLuk9pSmHXwUqXTLBP2mP4FUF8YIhja7II3920DBpDAb_XLWjnnAdmVaXmD0ucJmKY3ZWZmJtm2zQ/s1600/47688251_2017944871628305_8350805123789750272_o.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3cykVo8U8TKjfXcyDhP40C4Bl5g-R5jaSDyLFXv0-M_QykDFo9kJkzuvBDtuqeclLuk9pSmHXwUqXTLBP2mP4FUF8YIhja7II3920DBpDAb_XLWjnnAdmVaXmD0ucJmKY3ZWZmJtm2zQ/s320/47688251_2017944871628305_8350805123789750272_o.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A slide from Prof. Barry Smyth's presentation</td></tr>
</tbody></table>
If you perform an experiment and get some interesting results which cannot be redone and get the same results by somebody else, something is wrong with your finding. This is called reproducibility of research. If it is not reproducible, it is not science. You might think that systematic research carried out by academics and professional scientists who publish papers in conferences and journals are doing reproducible research. Not really.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Majority of research papers I've come across in my own domain are bare descriptions and explanations of their results without proper support for reproduction of the results by anybody interested. Even though a paper with a good quality provides a lot of details of their experimental setups and settings, it difficult to truly recreate their results completely based on the details in the paper. It is often necessary to contact the authors and have a correspondence back and forth several times to get things clear. Similarly, if I ask myself whether I can reproduce a research work I had published few years ago solely based on the details I had put down on my own paper, I have to give a big 'No' unfortunately.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This is a bad way to do science.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
It is unfair to computer scientist if I say they are not putting any effort to make their research reproducible. There are two important ways they try do it these days. The first is giving away data sets that they had collected. This allows third parties to verify their results and also to extend and build upon it. The second is to provide the source codes of the experimental implementations they have made. They usually put their codes into a Github repository and provide the link in their research papers so that readers can find the source code repository and reuse their code.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU8AHjVJXp-QoD_mIuoGPngMmA1yS41EK2oPa8-PldB2z8zs4xjKGAjONvHIi8PwoP7SASgB_bsZUQ3Ocu0V6wS8D2v_PlIKb_pk_eRsLB-4-j_ac2sXJhVOWxuTK7V2Kvm3rmsdSVu-g/s1600/48058994_2017945138294945_4651433269282209792_o.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU8AHjVJXp-QoD_mIuoGPngMmA1yS41EK2oPa8-PldB2z8zs4xjKGAjONvHIi8PwoP7SASgB_bsZUQ3Ocu0V6wS8D2v_PlIKb_pk_eRsLB-4-j_ac2sXJhVOWxuTK7V2Kvm3rmsdSVu-g/s320/48058994_2017945138294945_4651433269282209792_o.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Another slide from Prof. Barry Smyth's presentation</td></tr>
</tbody></table>
Recently I attended to a talk delivered by Prof. Barry Smyth in UCD, Ireland where he suggested two interesting ways to make our research papers reproducible. The first is a practice which is much simpler and easier to do. That is to produce a Jupyter Notebooks along the scientific publication which has both software codes, data, descriptions and explanations in a well documented manner which a third party can quickly run and build upon. If you haven't used or read about Jupyter Notebooks, have a look at the first link in the references section. It's a way to produce well documented software codes where you have your software codes, their descriptions and their output in a report-like format.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
There's even more powerful way of making reproducible research papers. Imagine you are producing a research paper where the paper talks about a 30% improvement in something. How to enable the reader to verify whether this number is truly 30% by using their own experimental data? If I'm giving away the source codes of my implementations, does the reader has sufficient information to locate the correct programs and execute them in the correct sequence in order to get the final result? This is where the tool "Kallysto" comes in. It is a tool developed by Prof. Barry in order to make scientific publications fully reproducible and traceable. Kallysto combines Latex with Jupyter Notebooks in such a way, your Latex manuscript is directly linked with the original data and the software codes which analyze them. While the typical workflow of writing a research paper is to (1) analyze data, (2) produce graphs as images or PDF files, and finally (3) create a Latex manuscript which explicitly include those graphs. When you compile your Latex source files, Kallysto will run the Jupyter Notebooks analyzing data and generates the results in real-time which will be used by Latex to produce the final PDF document.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The idea of Prof. Barry Smyth is to make scientific publications truly reproducible by scripting everything from the data to results and finally to latex documents.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>References:</b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
[1] Jupyter notebooks</div>
<div style="text-align: justify;">
<a href="https://jupyter.org/">https://jupyter.org/</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
[2] Netflix Papermil tool</div>
<div style="text-align: justify;">
<a href="https://medium.com/netflix-techblog/notebook-innovation-591ee3221233">https://medium.com/netflix-techblog/notebook-innovation-591ee3221233</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
[3] The tool made by Prof. Barry Smyth called Kallysto</div>
<div style="text-align: justify;">
<a href="https://github.com/barrysmyth/kallysto">https://github.com/barrysmyth/kallysto</a></div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-21297731303380429812018-12-21T05:49:00.000+05:302018-12-21T05:49:52.033+05:30Google Colaboratory Notebook with Data from Google Drive<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
Until recently, I was using individual Python scripts with data files here and there for data analysis in my research works. After understanding the power of having a better documentation of my experiments along with the codes and graphs, I started to use Jupyter Notebooks. However, I still had a limitation. Jupyter Notebook works on my local computer with the data files. Every time I do some analysis, I have to do it locally and upload the results to Google Drive as a backup. Whenever I want to work on it again, I have to download the Jupyter Notebook and the data files which is a big hassle.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Today I realized that Google provides an online tool to run Python Notebooks while the data and the Notebook file is still in the Google Drive. There's no requirement to download my data and Python scripts to local computer each time I want to do some analysis. Here's how we use <b>Google Colaboratory</b> for this purpose.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(1)</b> Create a directory in the Google Drive where I want to create my Colab Notebook. Let's say I've created the directory "Google-Colab-Demo" in the following location.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b><span style="font-family: inherit;">My Drive > UCD > Asanka's PhD > Experiments > Google-Colab-Demo</span></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(2)</b> Right-click inside the created directory and select <b>Colaboratory</b> from the menu. It will open a new web browser tab with a new Notebook. Give a name to the notebook. I'll set it to <b>plotting.ipynb</b>. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(3)</b> In the local computer, create a text file with the name <b>data.csv</b> and add the following content. Then upload it into the above directory we created in Google Drive.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
1,2</div>
<div style="text-align: justify;">
2,4</div>
<div style="text-align: justify;">
3,9</div>
<div style="text-align: justify;">
4,16</div>
<div style="text-align: justify;">
5,25 </div>
<div style="text-align: justify;">
6,36</div>
<div style="text-align: justify;">
7,49</div>
<div style="text-align: justify;">
8,64</div>
<div style="text-align: justify;">
9,81</div>
<div style="text-align: justify;">
10,100</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(4)</b> Add a text cell and provide some details about what we are going to do.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(5)</b> Add a code cell and insert the following code into it. Note that the full path to the <b>data.csv</b> file can be extracted by right-clicking on the data file on the file browser in the left hand size pane and then selecting the menu option <b>Copy path</b>.</div>
<div style="text-align: justify;">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">matplotlib.pyplot</span> <span style="color: #008800; font-weight: bold;">as</span> <span style="color: #0e84b5; font-weight: bold;">plt</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">numpy</span> <span style="color: #008800; font-weight: bold;">as</span> <span style="color: #0e84b5; font-weight: bold;">np</span>
x, y <span style="color: #333333;">=</span> np<span style="color: #333333;">.</span>loadtxt(<span style="background-color: #fff0f0;">"/content/drive/My Drive/UCD/Asanka's PhD/Experiments/Google-Colab-Demo/data.csv"</span>, delimiter<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">','</span>, unpack<span style="color: #333333;">=</span><span style="color: #007020;">True</span>)
plt<span style="color: #333333;">.</span>plot(x,y, label<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">'Loaded from file!'</span>)
plt<span style="color: #333333;">.</span>xlabel(<span style="background-color: #fff0f0;">'x'</span>)
plt<span style="color: #333333;">.</span>ylabel(<span style="background-color: #fff0f0;">'y'</span>)
plt<span style="color: #333333;">.</span>title(<span style="background-color: #fff0f0;">'Interesting Graph</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">Check it out'</span>)
plt<span style="color: #333333;">.</span>legend()
plt<span style="color: #333333;">.</span>show()
</pre>
</td></tr>
</tbody></table>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(6)</b> Now, run the code segment by clicking on the <b>Play</b> icon on the left corner of the code cell. The resulting graph will appear like the following.</div>
<div style="text-align: justify;">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRQ4JKF4pbPB2Qm-XTt7Inrjf1QzGlpUx47gBUz_gEDXcf4jEGPLELBxWNxyuHkhSS8LYYbjvKOgPpP74UQOBwmNqReQ-mOo0GINTmcmPR8w-u5ejEybKkhuV6uKC6EAUgiUmUPet0Bn8/s1600/Screenshot+from+2018-12-20+23-49-22.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="954" data-original-width="1113" height="545" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRQ4JKF4pbPB2Qm-XTt7Inrjf1QzGlpUx47gBUz_gEDXcf4jEGPLELBxWNxyuHkhSS8LYYbjvKOgPpP74UQOBwmNqReQ-mOo0GINTmcmPR8w-u5ejEybKkhuV6uKC6EAUgiUmUPet0Bn8/s640/Screenshot+from+2018-12-20+23-49-22.png" width="640" /></a></div>
<br />
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>Some extra work...</b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Sometimes, you can have a Jupyter Notebook with data in the local computer which you have copied to Google Drive. Now you want to run the same Jupyter Notebook in Google Colab. In that case, first you need to right-click on the Jupyter Notebook on Google Drive and open it with Collaboratory. If your Google Drive does not appear to be mounted automatically in the File browser pane, follow the stesps given below.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(7)</b> Mounting Google Drive into the Notebook by running following code. It will prompt for an authentication code which should be typed in. In the left hand side corner of the screen, a file browser should be available now with the access to the google drive files in the mounted location.</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;">1
2</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">google.colab</span> <span style="color: #008800; font-weight: bold;">import</span> drive
drive<span style="color: #333333;">.</span>mount(<span style="background-color: #fff0f0;">'/content/drive'</span>)
</pre>
</td></tr>
</tbody></table>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(8)</b> If we want to import another Python file in the Google Drive as a Python module within our Notebook, first give the path to the location of the Python file. Then import the Python module as in a normal Python program.</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;">1
2
3</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">sys</span>
sys<span style="color: #333333;">.</span>path<span style="color: #333333;">.</span>append(<span style="background-color: #fff0f0;">"/content/drive/path-to-current-directory"</span>)
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">my</span><span style="color: #333333;">-</span>module
</pre>
</td></tr>
</tbody></table>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Now everything should be good to go like a normal Colab Notebook.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Cheers!</div>
<div style="text-align: justify;">
<br />
<div style="text-align: center;">
~********************~</div>
</div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-76828014697853040822018-11-18T02:46:00.000+05:302018-11-18T02:46:14.936+05:30Saving Selected GNURadio Data using an External Trigger<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
When using GNURadio Companion (GRC) software package with a software defined radio (SDR) to capture radio signals, the usual approach is to save the incoming data stream into a file so that they can be processed later other other tools. However, the fast sample rate of SDR devices such as HackRF causes GRC script to generate large IQ data files which are difficult to handle on computers unless there's a big memory and a fast processor. It would be a wiser decision to save IQ data only when there's some useful signal is coming through the data stream. This article describes a way to give an external trigger to a GRC script in order to save selected segments of the incoming IQ data stream into a file. The two key elements of this trick are <b>Burst Tagger</b> and <b>Tagged File Sink</b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The Burst Tagger is a block which tag the incoming data stream by inserting a special tag with a value. The tagging work is one based on an input given to it through a second channel. When the value of this second channel goes above 0, a tag is inserted into the data string and when the value of the second channel goes below 0 again, another tag is inserted into the data. These two tags specify the region of the data stream which we needs to be saved. This output of the Burst Tagger is sent to the Tagged File Sink block. This block identify the tagged regions of the data stream and save each of those regions into separate data files.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Let's start.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(1) First of all, we need a GNURadio Companion flowchart like the one shown in the following figure. Once the flowchart was created, generate the Python script by clicking the button to "Generate the script". The generated file is named as <b>top_block.py</b> by default.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXGaupLSE9CMq4efsCjxYR-xnzyBoRqqeDULkhLCgQbuwmd9UduOlrFO1GFiJi5ru8umZEvAT4c0Sc48FW7THa4MyZ6zqvcHLL_nLIMzQTqQBxdcaDfLGPAacVh-QdckhtVn1IfSLQU48/s1600/burst-tagger-example.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="381" data-original-width="843" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXGaupLSE9CMq4efsCjxYR-xnzyBoRqqeDULkhLCgQbuwmd9UduOlrFO1GFiJi5ru8umZEvAT4c0Sc48FW7THa4MyZ6zqvcHLL_nLIMzQTqQBxdcaDfLGPAacVh-QdckhtVn1IfSLQU48/s640/burst-tagger-example.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(2) Write the following Python script in a separate file and name as <b>test.py</b>. This script updates the "trigger" variable which causes the GRC script to perform the tagging and saving data files.</div>
<div style="text-align: justify;">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">top_block</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">time</span>
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"Creating top_block class..."</span>)
tb<span style="color: #333333;">=</span>top_block<span style="color: #333333;">.</span>top_block()
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"Starting top_block..."</span>)
tb<span style="color: #333333;">.</span>start()
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"Started..."</span>)
<span style="color: #888888;">#######################################</span>
<span style="color: #888888;"># Testing the trigger</span>
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"saving..."</span>)
tb<span style="color: #333333;">.</span>set_trigger(<span style="color: #0000dd; font-weight: bold;">1</span>)
time<span style="color: #333333;">.</span>sleep(<span style="color: #0000dd; font-weight: bold;">2</span>)
tb<span style="color: #333333;">.</span>set_trigger(<span style="color: #333333;">-</span><span style="color: #0000dd; font-weight: bold;">1</span>)
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"stopping..."</span>)
time<span style="color: #333333;">.</span>sleep(<span style="color: #0000dd; font-weight: bold;">2</span>)
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"saving..."</span>)
tb<span style="color: #333333;">.</span>set_trigger(<span style="color: #0000dd; font-weight: bold;">1</span>)
time<span style="color: #333333;">.</span>sleep(<span style="color: #6600ee; font-weight: bold;">0.5</span>)
tb<span style="color: #333333;">.</span>set_trigger(<span style="color: #333333;">-</span><span style="color: #0000dd; font-weight: bold;">1</span>)
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"stopping..."</span>)
</pre>
</td></tr>
</tbody></table>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(3) Now, the script can be run as follows. You should see that two IQ data files get's saved into the current working directory.<br />
<br />
<b><span style="font-family: Courier New, Courier, monospace;">python test.py</span></b><br />
<br />
That's it!<br />
<br />
<div style="text-align: center;">
~*************~</div>
</div>
<div style="text-align: justify;">
<br /></div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com7tag:blogger.com,1999:blog-2381761802615660705.post-58096951398942640592018-09-11T19:40:00.001+05:302018-09-11T19:40:47.689+05:303.5 inch LCD Display on Raspberry Pi<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
I received a 3.5 inch LCD display which can be attached to the Raspberry Pi B+ device. It can be attached to the GPIO port of the RPi and use it as a display and as a touch screen for input. Installing drivers for the device was straightforward. Following are the steps I took to get it done.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
</div>
(1) Download the software from the Github from the following project into a computer. <a href="https://github.com/goodtft/LCD-show">https://github.com/goodtft/LCD-show</a><br />
<br />
<div>
(2) Connect the RPi from the computer through SSH and copy the downloaded software into it.<br />
<br /></div>
<div>
(3) Move into the directory from the terminal and run the following command to install the driver software.</div>
<div>
<br /></div>
<div style="text-align: center;">
<b><span style="font-family: Courier New, Courier, monospace;">sudo ./LCD35-show</span></b></div>
<div>
<br /></div>
<div>
When the commend completes running, it automatically reboots the RPi and get back with the LCD touch screen.</div>
<div>
<br /></div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-59753685632596304082018-07-11T18:51:00.001+05:302018-07-11T18:51:02.773+05:30A Signature Image for Documents<div dir="ltr" style="text-align: left;" trbidi="on">
While filling forms and preparing documents on the computer, I come across needs to put my handwritten signature on the document. In such cases, the printing of the document, signing it by hand and then scanning it to produce the soft copy is too much. It is useful to have an image of the signature which can be easily inserted into documents.<br />
<br />
On Linux, we can use the following steps to produce an image file where the handwritten signature stays in a transparent background.<br />
<br />
<b>(1)</b> Put the signature on a white paper and take a photograph.<br />
<br />
<b>(2)</b> Use a suitable tool to crop the photograph file to remove the unnecessary edges and have only the area covering the signature (e.g., Shotwell Viewer). Let's say the resulting image file is <b>original.jpg</b>.<br />
<br />
<b>(3)</b> Run the following command to push the whiter pixels to fully white and darker pixels to fully black.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><b>convert original.jpg -colorspace gray -threshold 28% filtered.png</b></span><br />
<br />
<b>(4)</b> Run the following command to set the while pixels as transparent.<br />
<br />
<b><span style="font-family: Courier New, Courier, monospace;">convert filtered.png -transparent white signature.png</span></b><br />
<div>
<br /></div>
<div>
Now, the resulting <b>signature.png</b> file contains the handwritten signature in black color while the background stays as transparent. This file can be used for the purpose of inserting the signature into electronic documents.</div>
<div>
<br /></div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com1tag:blogger.com,1999:blog-2381761802615660705.post-23846931292170848442018-06-17T15:44:00.001+05:302018-06-17T15:44:23.004+05:30Low Graphics Mode Problem on Ubuntu 16.04 LTS<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
My laptop, which runs Ubuntu 16.04 LTS, recently started to give me a strange error. When the computer is turned on, it boots into a screen where a message is shown as "Your system is running on low graphics mode". If I proceed to boot the system, the system boots up however the on-board WiFi is not detected. My computer suffered a physical damage lately which may have caused some hardware to malfunction. Anyway, being unable to fix this strange error, I found a somewhat workaround for it in the web.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Following the steps shown below to workaround each time when the "Low Graphics Mode" error occurs on Ubuntu 16.04.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(1)</b> Turn on the computer and wait till it lands on the "Your system is running on low graphics mode" error.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(2)</b> Press the key combination <b>Ctrl + Alt + F1</b> and login to the virtual terminal it provides.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(3)</b> On this terminal, type the following command.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: center;">
<span style="font-family: "Courier New", Courier, monospace;"><b>sudo service lightdm restart</b></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>(4)</b> Now, when the GUI login prompt appears, login there and the desktop environment should load now without any issues.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Cheers!</div>
<div style="text-align: justify;">
<br /></div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com1tag:blogger.com,1999:blog-2381761802615660705.post-45700766716832947872018-04-28T00:53:00.003+05:302018-04-28T00:53:57.794+05:30Installing SETI@home on Ubuntu 16.04 LTS<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
Searching for alien life is the goal of many space exploration projects for many years. Aliens can come in all shapes and sizes starting with single celled life. Among them, finding intelligent life would be exciting than anything else. Search for Extraterrestrial Intelligence (SETI) is a project which attempts to achieve that goal by listening to their radio transmissions. They have large radio telescopes which collect radio signals from the outer space and then process them to look for any sign of message from an intelligent beings.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Now, here's the issue. The scientists at SETI don't have enough processing power in their computers to process all these data acquired from the radio telescopes. This is obviously a computationally intensive task. That's where we can give a little hand as a good citizen of Earth. We can share a part of our personal computers processing power to process SETI data. I'm writing down the steps to install the required software on a computer running Ubuntu 16.04 LTS and setup everything. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(1) First of all, we need to have an account in the SETI@home website, in order to contribute. Go to the following website and create an account.</div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
<a href="https://setiathome.berkeley.edu/">https://setiathome.berkeley.edu/</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(2) Now, it's time to install the relevant software on our computer. For a computer running Ubuntu 16.04 LTS, we can easily install the software through the software repositories. Open a terminal and issue the following command for that.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b><span style="font-family: "Courier New", Courier, monospace;">sudo apt update</span></b></div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
<b><span style="font-family: "Courier New", Courier, monospace;">sudo apt install boinc</span></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(3) Open the BOINC software GUI and log into your account. Once you are logged in, you should be able to search for the SETI@home project from the list of projects available and add it.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNnZeGcJzE0dIdGehxHOBimaMgUhGhM_OUK1P8pA5onUUY-TL4i2ZPaJSSOvlSiE7bSj8XOuodLijfnDGzbaCPwwdX9TKQKKAyWg2n5_-JD2tZXLzc4iKtwZYkipFULB_8PIHWKZOLUaA/s1600/Screenshot+from+2018-04-27+19-56-05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="477" data-original-width="691" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNnZeGcJzE0dIdGehxHOBimaMgUhGhM_OUK1P8pA5onUUY-TL4i2ZPaJSSOvlSiE7bSj8XOuodLijfnDGzbaCPwwdX9TKQKKAyWg2n5_-JD2tZXLzc4iKtwZYkipFULB_8PIHWKZOLUaA/s320/Screenshot+from+2018-04-27+19-56-05.png" width="320" /></a></div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
(4) After a while, the SETI@home client will start taking data from the sever and process them locally. You can view the ongoing tasks on your computer in the GUI client.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7i0cP7msjFTOmOJRo4s4QONCt2k7HKVifuCaSzrTfjjGcsOKgtEXenoR07Rc9Cq0Kkf7D2UOzb0uyXJUIUB0CdvdWnMjI1VP6Ecn4sn5SakP15iCTAcF8jY9Fm_p1ns528lrpG4PengI/s1600/Screenshot+from+2018-04-27+20-12-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="628" data-original-width="1288" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7i0cP7msjFTOmOJRo4s4QONCt2k7HKVifuCaSzrTfjjGcsOKgtEXenoR07Rc9Cq0Kkf7D2UOzb0uyXJUIUB0CdvdWnMjI1VP6Ecn4sn5SakP15iCTAcF8jY9Fm_p1ns528lrpG4PengI/s320/Screenshot+from+2018-04-27+20-12-11.png" width="320" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Cheers!</div>
<div style="text-align: justify;">
<br /></div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com1tag:blogger.com,1999:blog-2381761802615660705.post-77342375861775036472018-03-19T02:07:00.000+05:302018-03-19T02:07:38.227+05:30SSIM to Measure Image Similarity<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
There are situations where we need to measure the similarity between two images. For example, when we have an original image and few other images with lower quality, we might need to identify when one is mostly similar to the original image. Bit-wise comparison of the image pixels is not applicable in this kind of scenarios. We need something more sophisticated. <a href="https://en.wikipedia.org/wiki/Structural_similarity" target="_blank">Structural similarity index (SSIM)</a> is such a method. It provides a value between 1 and 0 when comparing two images. If two images are exactly similar the SSIM becomes 1. If they are totally different, SSIM becomes 0.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Following Python program implements SSIM to compare between to images. Since we need some extra python libraries for this code to run, we should install following libraries on Ubuntu Linux.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b><span style="font-family: "courier new" , "courier" , monospace;">sudo apt install python-skimage</span></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b><span style="font-family: "courier new" , "courier" , monospace;">sudo apt install python-opencv</span></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
SSIM calculation code is as follows.</div>
<div style="text-align: justify;">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">skimage.measure</span> <span style="color: #008800; font-weight: bold;">import</span> structural_similarity <span style="color: #008800; font-weight: bold;">as</span> ssim
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">cv2</span>
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"Reading files..."</span>)
first <span style="color: #333333;">=</span> cv2<span style="color: #333333;">.</span>imread(<span style="background-color: #fff0f0;">"image1.png"</span>)
second <span style="color: #333333;">=</span> cv2<span style="color: #333333;">.</span>imread(<span style="background-color: #fff0f0;">"image2.png"</span>)
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"Resizing files..."</span>)
first <span style="color: #333333;">=</span> cv2<span style="color: #333333;">.</span>resize(first, (<span style="color: #0000dd; font-weight: bold;">2576</span>,<span style="color: #0000dd; font-weight: bold;">1125</span>))
second <span style="color: #333333;">=</span> cv2<span style="color: #333333;">.</span>resize(second, (<span style="color: #0000dd; font-weight: bold;">2576</span>,<span style="color: #0000dd; font-weight: bold;">1125</span>))
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"Converting files to grayscale..."</span>)
first <span style="color: #333333;">=</span> cv2<span style="color: #333333;">.</span>cvtColor(first, cv2<span style="color: #333333;">.</span>COLOR_BGR2GRAY)
second <span style="color: #333333;">=</span> cv2<span style="color: #333333;">.</span>cvtColor(second, cv2<span style="color: #333333;">.</span>COLOR_BGR2GRAY)
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"Calculating SSIM value..."</span>)
s <span style="color: #333333;">=</span> ssim(first, second)
<span style="color: #008800; font-weight: bold;">print</span>(<span style="background-color: #fff0f0;">"first vs second"</span>, s)
</pre>
</td></tr>
</tbody></table>
</div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: center;">
~*******************~ </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0tag:blogger.com,1999:blog-2381761802615660705.post-76151622899935618102018-03-01T05:11:00.000+05:302018-03-01T05:15:11.151+05:30Merging Video Files on Linux Terminal<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
When we need to merge multiple video files into a single file, there's an interesting tool called <b>mkvtoolnix</b> we can us. We can install it using the Linux software repository as follows.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><b>sudo apt install mkvtoolnix</b></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Let's say we have three <b>mp4</b> video files which we need to merge and build a single <b>mkv</b> file. We can do it in the following way.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b><span style="font-family: "courier new" , "courier" , monospace;">mkvmerge -o full-video.mkv part-1.mp4 \+ part-2.mp \+ part-3.mp</span></b></div>
<div style="text-align: justify;">
<br />
Meanwhile, I learned that there's a GUI version of the tool called <b>mkvtoolnix-gui</b> which I should explore later. For the moment, we can install it using the following command.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;"><b>sudo apt install mkvtoolnix-gui</b></span><br />
<br /></div>
<div style="text-align: justify;">
Cheers!</div>
</div>
Asanka P. Sayakkarahttp://www.blogger.com/profile/15397677684978919716noreply@blogger.com0