tag:blogger.com,1999:blog-19046787479054861842024-03-17T00:13:44.156-07:00Hojo's Ham Blogkd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.comBlogger67125tag:blogger.com,1999:blog-1904678747905486184.post-73500573026911705502024-01-02T19:29:00.000-08:002024-01-02T19:29:35.632-08:00Testing RS41 current draw at different TX_POWER settings<p> </p><h3 style="text-align: left;">Introduction</h3><p>RS41ng
on the RS-41 allows you to configure the output power via the
RADIO_SI4032_TX_POWER setting in the config.h file. It allows values
from 0-7. I set out to determine how that setting impacts the RF
output power as well as the current draw from the batteries during
transmission.</p><h3 style="text-align: left;">Testing configuration</h3><h3 style="text-align: left;"> <div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJAnx27vVHw3GaeLNEzrud7wKUbpXLaGq_VUnXR75jNnS_MiVw13E7yUNqXW90IOvR-GBFKFTRBWHDONZLMNyqOAk5NObqqcHlU-L4iA3nElGg0yRttQp5LCI1h5YBWe2NW19QnUWOCRObPWoU6Xeata3zWPB31UFwEryLoXP5viMqp8lmU7DErbtABoE/s851/test_setup.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="832" data-original-width="851" height="313" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJAnx27vVHw3GaeLNEzrud7wKUbpXLaGq_VUnXR75jNnS_MiVw13E7yUNqXW90IOvR-GBFKFTRBWHDONZLMNyqOAk5NObqqcHlU-L4iA3nElGg0yRttQp5LCI1h5YBWe2NW19QnUWOCRObPWoU6Xeata3zWPB31UFwEryLoXP5viMqp8lmU7DErbtABoE/s320/test_setup.jpg" width="320" /></a></div><br /></h3><p>I
configured a RS-41 with RS41ng. The RS-41 has an SMA connector
attached so that it could be wired through 19db of attenuators into a
Spectrum Analyzer. Power was provided by a bench power supply. I
varied the RADIO_SI4032_TX_POWER through various settings and measured
both current draw and TX output power. The basic setup as as follows:</p><p><b>Bench power supply voltage:</b> 3.2 volts<br /><b>Bench power supply max current:</b> 0.650 amps</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUAExT1T-EypfwYCUPcES2rOWx_40SNNqCr9Lb9gSTBn1QWevMtqjQkhiD7mmsi0P6id9yycc3NxswtW2r2gzK1C1DcJAapE336y3X0UC9tRA1Cg6LBBo7pGzuGTeY3H6g2cnRTkGxmWkKwfpi7dLdQt04v6PD0Oyrulu97xdgr6nY_vQ93VYSIOkiFBs/s597/ps_setup.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="597" data-original-width="467" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUAExT1T-EypfwYCUPcES2rOWx_40SNNqCr9Lb9gSTBn1QWevMtqjQkhiD7mmsi0P6id9yycc3NxswtW2r2gzK1C1DcJAapE336y3X0UC9tRA1Cg6LBBo7pGzuGTeY3H6g2cnRTkGxmWkKwfpi7dLdQt04v6PD0Oyrulu97xdgr6nY_vQ93VYSIOkiFBs/s320/ps_setup.jpg" width="250" /></a></div><br /> <p></p><p><b>Frequency:</b> 432.605mhz<br /><b>Modulation:</b> Horus Binary V2</p><h3 style="text-align: left;">Testing</h3><p>For
each test, I reprogrammed the RS-41 with a different
RADIO_SI4032_TX_POWER setting and measured the output on the Spectrum
Analyzer as well as the current draw on the bench power supply.</p><p>Example current draw when testing with the TX power set to 30:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnOL3acBl7oZIyNqRWsxmVUq-RN7J9HFfQ8h-2XPZz5RP-SjlKBpevA7Jh9-vSw63YqkPzd7y523_Dkm6rpRG1UkqJrqnN5OqnnH7jvVhozwLnEXOICpwBozk2KSuUktkDOifhQDyYb9UNLH5xd9ePvE5gfp3xK1J7aApUEwtZ-eZb9RJEB7Cy08MXbuc/s603/ps_30.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="603" data-original-width="444" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnOL3acBl7oZIyNqRWsxmVUq-RN7J9HFfQ8h-2XPZz5RP-SjlKBpevA7Jh9-vSw63YqkPzd7y523_Dkm6rpRG1UkqJrqnN5OqnnH7jvVhozwLnEXOICpwBozk2KSuUktkDOifhQDyYb9UNLH5xd9ePvE5gfp3xK1J7aApUEwtZ-eZb9RJEB7Cy08MXbuc/s320/ps_30.jpg" width="236" /></a></div><br /><p>Example Spectrum Analyzer result:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1HVzQKVFzD0QN0Tsq9QSUEoJdhQ8i14p2W9P089G3k5nUWce4BNIqFYFgQbht3sYzfy5XZLDWXuX1CncgeKvINAI_0iE58vDRPS9cL7642Uh-wtycKfniGy_kCYxxWef47cK4bOEkbW8rrhdApLIrzQZ_wSRtRIL9YjsoUlrXP0pNXY4ypBIupVfzM7U/s4000/20231230_153650.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3000" data-original-width="4000" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1HVzQKVFzD0QN0Tsq9QSUEoJdhQ8i14p2W9P089G3k5nUWce4BNIqFYFgQbht3sYzfy5XZLDWXuX1CncgeKvINAI_0iE58vDRPS9cL7642Uh-wtycKfniGy_kCYxxWef47cK4bOEkbW8rrhdApLIrzQZ_wSRtRIL9YjsoUlrXP0pNXY4ypBIupVfzM7U/s320/20231230_153650.jpg" width="320" /></a></div><br /><h3 style="text-align: left;">Results</h3><div style="text-align: left;">
<table border="1" style="text-align: center; width: 100%;">
<tbody><tr>
<th>RADIO_SI4032_TX_POWER</th>
<th>DBM</th>
<th>Current (ma)</th>
</tr>
<tr>
<td>Idle Consumption</td>
<td>n/a<br /></td>
<td>133</td>
</tr>
<tr>
<td>0</td>
<td>-4.5</td>
<td>172<br /></td>
</tr>
<tr>
<td>1</td>
<td>-1.25<br /></td>
<td>174<br /></td>
</tr>
<tr>
<td>2</td>
<td>1.0<br /></td>
<td>179<br /></td>
</tr>
<tr>
<td>3</td>
<td>4.5<br /></td>
<td>184<br /></td>
</tr>
<tr>
<td>4</td>
<td>7.7<br /></td>
<td>190<br /></td>
</tr>
<tr>
<td>5<br /></td>
<td>10.9<br /></td>
<td>205<br /></td>
</tr>
<tr>
<td>6</td>
<td>13.6<br /></td>
<td>218<br /></td>
</tr>
<tr>
<td>7<br /></td>
<td>15.0<br /></td>
<td>225<br /></td>
</tr>
</tbody></table>
<br /></div><h3 style="text-align: left;">Conclusions</h3><p>For
airborne use, 14dbm (25mW) has been observed to be sufficient for line
of site reception of Horus Binary using other trackers. By setting
RADIO_SI4032_TX_POWER set to 6 or 7, the desired output power is achieved. </p><p><br /></p><p><br /></p><p> <br /></p>kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-76281829710789482592023-12-30T12:07:00.000-08:002023-12-30T14:29:33.627-08:00Testing DFM17 Current draw at different TX_POWER settings<h3 style="text-align: left;">Introduction</h3><p>RS41ng on the DFM17 allows you to configure the output power via the RADIO_SI4063_TX_POWER setting in the config.h file. It allows values from 0-127. I set out to determine how that setting impacts the RF output power as well as the current draw from the batteries during transmission.</p><h3 style="text-align: left;">Testing configuration</h3><h3 style="text-align: left;"> <div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJAnx27vVHw3GaeLNEzrud7wKUbpXLaGq_VUnXR75jNnS_MiVw13E7yUNqXW90IOvR-GBFKFTRBWHDONZLMNyqOAk5NObqqcHlU-L4iA3nElGg0yRttQp5LCI1h5YBWe2NW19QnUWOCRObPWoU6Xeata3zWPB31UFwEryLoXP5viMqp8lmU7DErbtABoE/s851/test_setup.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="832" data-original-width="851" height="313" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJAnx27vVHw3GaeLNEzrud7wKUbpXLaGq_VUnXR75jNnS_MiVw13E7yUNqXW90IOvR-GBFKFTRBWHDONZLMNyqOAk5NObqqcHlU-L4iA3nElGg0yRttQp5LCI1h5YBWe2NW19QnUWOCRObPWoU6Xeata3zWPB31UFwEryLoXP5viMqp8lmU7DErbtABoE/s320/test_setup.jpg" width="320" /></a></div><br /></h3><p>I configured a DFM-17 with RS41ng. The DFM-17 has an SMA connector attached so that it could be wired through 19db of attenuators into a Spectrum Analyzer. Power was provided by a bench power supply. I varied the RADIO_SI4063_TX_POWER through various settings and measured both current draw and TX output power. The basic setup as as follows:</p><p><b>Bench power supply voltage:</b> 7.5 volts<br /><b>Bench power supply max current:</b> 0.650 amps</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUAExT1T-EypfwYCUPcES2rOWx_40SNNqCr9Lb9gSTBn1QWevMtqjQkhiD7mmsi0P6id9yycc3NxswtW2r2gzK1C1DcJAapE336y3X0UC9tRA1Cg6LBBo7pGzuGTeY3H6g2cnRTkGxmWkKwfpi7dLdQt04v6PD0Oyrulu97xdgr6nY_vQ93VYSIOkiFBs/s597/ps_setup.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="597" data-original-width="467" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUAExT1T-EypfwYCUPcES2rOWx_40SNNqCr9Lb9gSTBn1QWevMtqjQkhiD7mmsi0P6id9yycc3NxswtW2r2gzK1C1DcJAapE336y3X0UC9tRA1Cg6LBBo7pGzuGTeY3H6g2cnRTkGxmWkKwfpi7dLdQt04v6PD0Oyrulu97xdgr6nY_vQ93VYSIOkiFBs/s320/ps_setup.jpg" width="250" /></a></div><br /> <p></p><p><b>Frequency:</b> 432.605mhz<br /><b>Modulation:</b> Horus Binary V2</p><h3 style="text-align: left;">Testing</h3><p>For each test, I reprogrammed the DFM-17 with a different RADIO_SI4063_TX_POWER setting and measured the output on the Spectrum Analyzer as well as the current draw on the bench power supply.</p><p>Example current draw when testing with the TX power set to 30:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnOL3acBl7oZIyNqRWsxmVUq-RN7J9HFfQ8h-2XPZz5RP-SjlKBpevA7Jh9-vSw63YqkPzd7y523_Dkm6rpRG1UkqJrqnN5OqnnH7jvVhozwLnEXOICpwBozk2KSuUktkDOifhQDyYb9UNLH5xd9ePvE5gfp3xK1J7aApUEwtZ-eZb9RJEB7Cy08MXbuc/s603/ps_30.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="603" data-original-width="444" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnOL3acBl7oZIyNqRWsxmVUq-RN7J9HFfQ8h-2XPZz5RP-SjlKBpevA7Jh9-vSw63YqkPzd7y523_Dkm6rpRG1UkqJrqnN5OqnnH7jvVhozwLnEXOICpwBozk2KSuUktkDOifhQDyYb9UNLH5xd9ePvE5gfp3xK1J7aApUEwtZ-eZb9RJEB7Cy08MXbuc/s320/ps_30.jpg" width="236" /></a></div><br /><p>Example Spectrum Analyzer result:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1HVzQKVFzD0QN0Tsq9QSUEoJdhQ8i14p2W9P089G3k5nUWce4BNIqFYFgQbht3sYzfy5XZLDWXuX1CncgeKvINAI_0iE58vDRPS9cL7642Uh-wtycKfniGy_kCYxxWef47cK4bOEkbW8rrhdApLIrzQZ_wSRtRIL9YjsoUlrXP0pNXY4ypBIupVfzM7U/s4000/20231230_153650.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3000" data-original-width="4000" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1HVzQKVFzD0QN0Tsq9QSUEoJdhQ8i14p2W9P089G3k5nUWce4BNIqFYFgQbht3sYzfy5XZLDWXuX1CncgeKvINAI_0iE58vDRPS9cL7642Uh-wtycKfniGy_kCYxxWef47cK4bOEkbW8rrhdApLIrzQZ_wSRtRIL9YjsoUlrXP0pNXY4ypBIupVfzM7U/s320/20231230_153650.jpg" width="320" /></a></div><br /><h3 style="text-align: left;">Results</h3><div style="text-align: left;">
<table border="1" style="text-align: center; width: 100%;">
<tbody><tr>
<th>RADIO_SI4063_TX_POWER</th>
<th>DBM</th>
<th>Current (ma)</th>
</tr>
<tr>
<td>Idle Consumption</td>
<td>n/a<br /></td>
<td>65</td>
</tr>
<tr>
<td>1</td>
<td>-12.0</td>
<td>76<br /></td>
</tr>
<tr>
<td>12</td>
<td>3.0</td>
<td>90<br /></td>
</tr>
<tr>
<td>25</td>
<td>9.0<br /></td>
<td>107<br /></td>
</tr>
<tr>
<td>30</td>
<td>10.4<br /></td>
<td>112<br /></td>
</tr>
<tr>
<td>45</td>
<td>14.0<br /></td>
<td>128<br /></td>
</tr>
<tr>
<td>50<br /></td>
<td>14.7<br /></td>
<td>132<br /></td>
</tr>
<tr>
<td>75</td>
<td>17.8<br /></td>
<td>151<br /></td>
</tr>
<tr>
<td>100<br /></td>
<td>18.8<br /></td>
<td>162<br /></td>
</tr>
<tr>
<td>127<br /></td>
<td>19.2<br /></td>
<td>182<br /></td>
</tr>
</tbody></table>
<br /></div><h3 style="text-align: left;">Conclusions</h3><p>For airborne use, 14dbm (25mW) has been observed to be sufficient for line of site reception of Horus Binary using other trackers. By setting RADIO_SI4063_TX_POWER set to 45, the power consumption is about 70% of transmitting at full power. The reduced power consuption would lead to longer battery life during flight, or on the ground during a HAB recovery. </p><p><br /></p><p><br /></p><p> <br /></p>kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-21168478997696548412023-12-27T20:00:00.000-08:002023-12-27T21:20:34.604-08:00A little "science" on the DFM-17 running on 2m vs 70cm<h3 style="text-align: left;">The Experiment</h3><p>I put on my lab coat, started boiling some test tubes, and made a few bwoo-hahaha noises tonight, as I did some science. I attached an SMA connector to one of my DFM-17's so that I could run some controlled experiments of RS41ng on both 2m vs 70cm. The intent was to verify whether the output RF filters on the DFM-17 are appropriate for transmitting beacons on the 2m band.<br /></p><h3 style="text-align: left;">Modifying the DFM-17</h3><p style="text-align: left;">I removed the stock antenna and added an SMA connector on the provided pads. The board layout was standard, and an SMA connector in my parts bin fit just fine.<br /></p><p style="text-align: left;"><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9YxQhBpxkdMYBKwLJ-tFO7CADI1puu4qL6zl634FEkYwoJJy3rktFsYHMHJz4JJCzaW3k0WcbgedNKccxdTwqbvehAsFg4njww8gdeYwJ081GLaC4FOZkhoJue9w3BzvvPlM2TfvdwGw19LlJ7Q5FOSa4DUVlo4RYs_-Dn0V52TboyT1G_7LI6K8tRjg/s4000/20231227_205237.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="4000" data-original-width="3000" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9YxQhBpxkdMYBKwLJ-tFO7CADI1puu4qL6zl634FEkYwoJJy3rktFsYHMHJz4JJCzaW3k0WcbgedNKccxdTwqbvehAsFg4njww8gdeYwJ081GLaC4FOZkhoJue9w3BzvvPlM2TfvdwGw19LlJ7Q5FOSa4DUVlo4RYs_-Dn0V52TboyT1G_7LI6K8tRjg/s320/20231227_205237.jpg" width="240" /></a><br /></p><p style="text-align: left;"> </p><h3 style="text-align: left;">The test setup</h3><p style="text-align: left;"><br />I then cabled the DFM-17 through a pushbutton attenuator and added 40db of attenuation in the path to my Spectrum Analyzer (I didn't want to overdrive the input). Note, the pushbutton attenuator I was using is built for 75 ohm, not 50 ohm. This may impact some output power readings, but it should be consistent across frequencies, so while the output measured may not be exact, the relative powers and presence (or lack) of harmonic signals should be close enough for folk music and ham radio.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9H9WXSMhc_o1kB9Q_ps0Ijs-0hDk6GxspcWt-WqXESg8O-umcZbby6veClT_10D255DcE4Ob9Y_bOwWTt4YMsNIH1bf0OhTM2r8FbsmGR70Im-pbJizmVtAQ5wTFokb2VTDVXOmnh8h_vbyj5ByDW5k7Bsc75wraSGMZJGFeVqTPONiiM8fGOJzXt5U8/s4000/20231227_210122.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3000" data-original-width="4000" height="419" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9H9WXSMhc_o1kB9Q_ps0Ijs-0hDk6GxspcWt-WqXESg8O-umcZbby6veClT_10D255DcE4Ob9Y_bOwWTt4YMsNIH1bf0OhTM2r8FbsmGR70Im-pbJizmVtAQ5wTFokb2VTDVXOmnh8h_vbyj5ByDW5k7Bsc75wraSGMZJGFeVqTPONiiM8fGOJzXt5U8/w558-h419/20231227_210122.jpg" width="558" /> </a></p><p style="text-align: left;"> <br /></p><h3 style="text-align: left;">70cm Measurement</h3><p style="text-align: left;">I then took a look at the spectrum when running at Horus Binary and APRS on 70cm. I had the Spectrum Analyzer set to full scale (0-1500 mhz). Note there were no harmonics in evidence at all. The filters on the board seemed to do an admirable job of keeping it clean. The SA showed -15 db. Adding the 40db of attenuation, it's making about 25dbm of output. Ish.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMaO9q8rCc2gRDLMQUzNY_4fUIPHJmCf3bP3TLO7U1_mMeGEPicaTvCEfn8xpVXV2RfXtgx9MJ2BuDnSW5EHbEZSDzR0yaNHvVhJLkRwMOC3BxPlKZ2VD2WxmkFIQU8E2gexDhS27Sxe4aXDm1YJ1VNFSKQZX8sShIg8Jz9TyXvjeiLbd0t6dHOWnszcI/s4000/20231227_214820.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3000" data-original-width="4000" height="422" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMaO9q8rCc2gRDLMQUzNY_4fUIPHJmCf3bP3TLO7U1_mMeGEPicaTvCEfn8xpVXV2RfXtgx9MJ2BuDnSW5EHbEZSDzR0yaNHvVhJLkRwMOC3BxPlKZ2VD2WxmkFIQU8E2gexDhS27Sxe4aXDm1YJ1VNFSKQZX8sShIg8Jz9TyXvjeiLbd0t6dHOWnszcI/w563-h422/20231227_214820.jpg" width="563" /></a><br /></p><h3 style="text-align: left;">2m Measurement</h3><p style="text-align: left;">I then re-flashed the code to beacon APRS at 144.390, and transmit Horus Binary at 145.600. Note the harmonics generated. The filtering on the board appears to be a low pass filter tuned to 70cm So the harmonics below 400 mhz are coming through loud and clear. There does seem to be <i>some</i> attenuation, as the signal on 144.390 is showing 10db weaker than the 70cm test). The first and second harmonics have pretty strong relative output power, since they are presumably going through <i>less</i> attenuation as the frequencies increase. There could be some variability in the output power of the Si4063 chip at different frequencies as well. Note that the harmonic up in the 70cm frequency range is even stronger than the base signal at 2m, due to the vagaries of the filtering.<br /><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh65I3L3wVgfXszP_t5RcjMJAxanfQe8cTm4JjcKmxeDigsr2B0kJcfLmRUTfrrgtqKL3jF-mnrPOMkdUOdBi-sMkCPCCjPa9GyxkxEXyQgXtBYxtKjxk1qwbpLuidyPW_YbRK6mTiiV6mTrz_DOnnZlp4FlMB4O0XEmeZ-iK0R29PmKL0bh1r4hyphenhyphenojMZ8/s4000/20231227_213807.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3000" data-original-width="4000" height="437" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh65I3L3wVgfXszP_t5RcjMJAxanfQe8cTm4JjcKmxeDigsr2B0kJcfLmRUTfrrgtqKL3jF-mnrPOMkdUOdBi-sMkCPCCjPa9GyxkxEXyQgXtBYxtKjxk1qwbpLuidyPW_YbRK6mTiiV6mTrz_DOnnZlp4FlMB4O0XEmeZ-iK0R29PmKL0bh1r4hyphenhyphenojMZ8/w582-h437/20231227_213807.jpg" width="582" /></a></div><p> </p><h3 style="text-align: left;">Conclusions</h3><p style="text-align: left;">Running the DFM-17 below 70cm is going to transmit unwanted harmonics. Though the overall output power is low, down in the 15dbm range, this would be generated by a balloon aloft, meaning the harmonics will be broadcast for pretty much line of sight across quite a significant radius. I would advise against doing it unless you modify the filtering on the board. The DFM-17 seems VERY nicely tuned for signals on 70cm, however. I was quite pleased to see the results there.<br /><br />Mike / KD2EAT<br /><br /> </p><br /><div><br /><br /><br /></div>kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-52820240550947954222020-02-16T09:29:00.002-08:002020-02-16T11:45:44.326-08:00Helical antenna for LMS6 radiosondes<h2>
Helical antenna for LMS6 radiosondes</h2>
<br />
The National Weather Service in Buffalo, NY launches two weather sondes per day. They presently use <a href="https://www.lockheedmartin.com/en-us/products/meteorological-instrumentation.html" target="_blank">Lockheed Martin LMS6 Radiosondes</a> running at 1680(ish) MHZ and intend to continue running the until sometime in 2020. Since I'd like to track them, I wanted to build an optimized antenna system.<br />
<br />
<h3>
Antenna Design</h3>
<br />
The LMS6 uses a Left Hand Circularly Polarized (LHCP) patch antenna. <span style="color: blue;"> </span><i>(Note: I read this somewhere, but I'll be darned if I can now find the information. If you happen to have documentation of that fact, I'd love to have it!)</i> Therefore, for best range, I opted to build an LHCP antenna for my receive station. Looking online, I quickly found an <a href="https://www.daycounter.com/Calculators/Helical-Antenna-Design-Calculator.phtml" target="_blank">online calculator</a> and came up with the following model.<br />
<br />
<ul>
<li>Assumed Velocity Factor: 100%</li>
<ul>
<li>Frequency: 1680 mhz</li>
<li>Wavelength: 178.6 mm</li>
<li>Diameter: 58.9 mm</li>
<li>Spacing (.25 wave): 44.6 mm</li>
</ul>
</ul>
<h3>
Build</h3>
<div>
Using these characteristics, I used Fusion 360 to design a "holder" for the spiral of wire I would use for the antenna. I configured a 1/4" x 20 threaded mounting hole in the bottom so that it could be screwed down to a reflector, and the same threaded rod could be used on the bottom to secure a 1/4" x 20 coupling nut. That nut could be used to mount the reflector on a standard camera tripod.</div>
<div>
<br /></div>
<div>
The 3D Design looked like this:</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoVMMs0KKcTGx-SOrMvXuTl1ybwJv66hDX7c77VZ11DPo_0W7IsPaiXMA7QQ1wtEMC_6OeG3B2Rju8eFrX6J167tyRudMyuDoyp-OubKAWDVeIhZuj5CAZfcEoa41xdn1QEfsGfWBs_K4/s1600/Helical+Model.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="611" data-original-width="421" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoVMMs0KKcTGx-SOrMvXuTl1ybwJv66hDX7c77VZ11DPo_0W7IsPaiXMA7QQ1wtEMC_6OeG3B2Rju8eFrX6J167tyRudMyuDoyp-OubKAWDVeIhZuj5CAZfcEoa41xdn1QEfsGfWBs_K4/s320/Helical+Model.JPG" width="220" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
I used bare 16ga wire for the element. I pre-wrapped it around a 2" mailer tube to get the shape right, and then fed it through the structure. I bought a lid for a pot at a local reuse store for $1 to use as my reflector. I installed a bulkhead SMA adapter on the lid, near the base of the spiral. The result looked like this:</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoewvsSUGvMMpyPrkqt_AlH9Ypzu8iD3MTcbgc6bI9cTTT-Jai2KLSL5vUH-FQw-SIwg4SIjSzzyCVA2x7De_URitZOvTwjMe7upGodiMNB28aTpEctAVyRayGDk6E0CxhA-qL1uoaWeg/s1600/20200122_180231.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoewvsSUGvMMpyPrkqt_AlH9Ypzu8iD3MTcbgc6bI9cTTT-Jai2KLSL5vUH-FQw-SIwg4SIjSzzyCVA2x7De_URitZOvTwjMe7upGodiMNB28aTpEctAVyRayGDk6E0CxhA-qL1uoaWeg/s320/20200122_180231.jpg" width="240" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5cEmQtyxwzAWDo_2dEEhfTLlUCFTEONKFWI-ca8qX9bLsfAULAxwTch3r2EFIwG0Vx93yYt3xLA9rx5YJbGEe-8tZ7fI6GNJp5fDk0ecz2888nCkyi23ZajqzfA-g6-3krlSvlOJma1U/s1600/20200122_180243.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5cEmQtyxwzAWDo_2dEEhfTLlUCFTEONKFWI-ca8qX9bLsfAULAxwTch3r2EFIwG0Vx93yYt3xLA9rx5YJbGEe-8tZ7fI6GNJp5fDk0ecz2888nCkyi23ZajqzfA-g6-3krlSvlOJma1U/s320/20200122_180243.jpg" width="240" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h3>
Testing</h3>
</div>
<div>
<br /></div>
<div>
Unfortunately, the online model does not account for velocity factor. When I did an SWR measurement on the antenna, it was out of tune in the frequency of interest. I did about 1/2 dozen prints, and resolved that 95% velocity factor was the ideal for this design.</div>
<div>
<br /></div>
<ul>
<li>Velocity Factor: 95%</li>
<ul>
<li>Frequency: 1680 mhz</li>
<li>Wavelength: 169.6 mm</li>
<li>Diameter: 54.0 mm</li>
<li>Spacing (.25 wave): 42.4 mm</li>
</ul>
</ul>
<div>
</div>
<br />
<div>
With those parameters, I ran a VSWR plot, and it looked great! The plot is centered at 1680 mhz, and the two markers are at the approximate end points of the range of frequencies we might see from an LMS6 sonde running at 1680 mhz.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigpvAHLqE9H_GIQWj72izYHYhNdygmjNiXKAGBi4mKzbPQTLSV09pzDrrrzziyK6u7HMK4rXt1jLI_uae7nI5HmwJDYbBrcp9esL5LEpT_2BRjA4LSmfol5ACC_VrJtdJkXDuTW6cSMD4/s1600/Helical+95+pct+final3.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="320" data-original-width="480" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigpvAHLqE9H_GIQWj72izYHYhNdygmjNiXKAGBi4mKzbPQTLSV09pzDrrrzziyK6u7HMK4rXt1jLI_uae7nI5HmwJDYbBrcp9esL5LEpT_2BRjA4LSmfol5ACC_VrJtdJkXDuTW6cSMD4/s400/Helical+95+pct+final3.bmp" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h3 style="clear: both; text-align: left;">
In use</h3>
<div>
<br /></div>
<div>
I took the antenna out and compared it to a 1/4 wave dipole antenna (which also has very good VSWR) and the results were significantly better. I was running two Raspberry Pi's in my vehicle, running <a href="https://github.com/projecthorus/radiosonde_auto_rx" target="_blank">radiosonde_auto_rx software</a> with identical <a href="https://www.amazon.com/gp/product/B06Y1D7P48/ref=ppx_yo_dt_b_asin_title_o00_s00" target="_blank">SDRs</a> and <a href="https://www.amazon.com/gp/product/B07K1M39H4/ref=ppx_yo_dt_b_asin_title_o00_s00" target="_blank">preamps</a>. The helical began receiving the sonde about 30 miles (48 km) distant. My dipole running, simultaneously, did not beg receiving the sonde until about 10 miles out. That's only one data point, so far, but I'm pleased by the initial findings.</div>
<div>
<br /></div>
<div>
Here's an image of my chase vehicle, with a dipole duct-taped to the roof rack, and the helical set up on a tripod beside the car.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq6uucWplHjAPe9w7TD_tIB1obfVNEUT8hWQlYYdf41HMKSAAgc_hrZz5mI9QikykEVwy8p6S-Rj-8LAHeS1O84JwR5-366rTPU-KltpOcsKtWldIVq8tuyrPMHo344H6ylH4E2WdUk78/s1600/20200215_145856.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq6uucWplHjAPe9w7TD_tIB1obfVNEUT8hWQlYYdf41HMKSAAgc_hrZz5mI9QikykEVwy8p6S-Rj-8LAHeS1O84JwR5-366rTPU-KltpOcsKtWldIVq8tuyrPMHo344H6ylH4E2WdUk78/s400/20200215_145856.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF17lx7GcLTLonDL6jup5r5mfdS5_dOdnhkXF7A_5MkPfrCu5ZsgYSBVTwHI9KTx2annL428G_OboO8_eRSk-Z_UggfPN3WkA13-Yh63PKmUrR457lSEFEV0hIXpbye1v-0nmQDTnFBqE/s1600/20200215_145902.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF17lx7GcLTLonDL6jup5r5mfdS5_dOdnhkXF7A_5MkPfrCu5ZsgYSBVTwHI9KTx2annL428G_OboO8_eRSk-Z_UggfPN3WkA13-Yh63PKmUrR457lSEFEV0hIXpbye1v-0nmQDTnFBqE/s400/20200215_145902.jpg" width="400" /></a></div>
<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/AVvXsEipjD_gCFA1q3lzmvRtS_7auRZNQN_6UjI6Kk_hAIirjbDR6a-dJ1m9XCSwloZnuz6_feeLDFOrsceZ_p40UVgJ2a-H5wgqvj8gmavVXbnFlOfT8OPYAFsh_zWmVz5HI2XZ6-Bk2XDbwUU/s1600/20200215_145913.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipjD_gCFA1q3lzmvRtS_7auRZNQN_6UjI6Kk_hAIirjbDR6a-dJ1m9XCSwloZnuz6_feeLDFOrsceZ_p40UVgJ2a-H5wgqvj8gmavVXbnFlOfT8OPYAFsh_zWmVz5HI2XZ6-Bk2XDbwUU/s400/20200215_145913.jpg" width="400" /></a></div>
<br />
<div>
<br /></div>
<h3>
Further testing</h3>
<div>
<br /></div>
<div>
I'd like to gather more side by side comparisons of the performance of these antennas during radiosonde hunts. That will be greatly facilitated if one of them (finally!) lands somewhere that I can retrieve it. My area of Central New York State features an awful lot of tall trees! Once I have one in hand, I can use it for real-world signals in a more controlled laboratory environment.</div>
<div>
<br /></div>
<div>
<br /></div>
kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-57609461833228812282019-12-29T20:27:00.000-08:002019-12-29T20:28:02.767-08:00radiosonde_auto_rx addition - OLED display<h2>
The problem with auto_rx on a "headless" Raspberry Pi</h2>
<br />
So, the <a href="https://github.com/projecthorus/radiosonde_auto_rx" target="_blank">Project Horus "radiosonde_auto_rx" package</a> is a wonderful bit of software that one can run on a Raspberry Pi to automatically detect and upload radiosonde data to the CUFS Predictor site. They've also front-ended that site with one specifically for weathersondes at <a href="https://tracker.sondehub.org/">https://tracker.sondehub.org</a>.<br />
<br />
Unfortunately, it's the kind of thing I'd prefer to run "headless" and save the space and expense of keeping a keyboard, monitor and mouse attached to my Raspberry Pi. I would also like to be able to use it in a mobile application, rather than the <a href="https://github.com/projecthorus/chasemapper" target="_blank">Project Horus chasemapper</a> software. While Chasemapper looks like great software, I presently run HAB chases with Windows <a href="http://aprsisce.wikidot.com/start" target="_blank">APRSISCE32 software</a>. I run a windows laptop in my chase vehicle, and expect to continue doing so. Therefore, when running with auto_rx, I'd like to keep the mobile footprint of my weather sonde gear minimal and use my Windows laptop. Therefore, I decided to add an OLED display to the, otherwise headless, Raspberry Pi.<br />
<br />
<h3>
The OLED</h3>
<br />
I picked up some very cheap (like under $2 each) 0.96" monochrome 128x64 OLED displays from Banggood. I won't post a link as they seem to come and go with inventory. The particular model that I got actually has the first 16 rows of pixels in yellow, and the rest in blue. That actually works out well for my plans, as I'd like to use the top rows for static data, and the lower rows for a scrolling text area with incoming telemetry.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCHDeDDJQzHiQdtLjskxOEDSRQBPTFn4W2hVaY-ulGa0d1cjCJmkrLngHXzhP4U2eH8IvUEb9RFmXnTewMUw7mcJ3vONdc7sjumh2d9iFfBFcyiMY3sjgfEleCnu5qw9kb3iNAzeY_GIk/s1600/oled+display.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="421" data-original-width="444" height="303" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCHDeDDJQzHiQdtLjskxOEDSRQBPTFn4W2hVaY-ulGa0d1cjCJmkrLngHXzhP4U2eH8IvUEb9RFmXnTewMUw7mcJ3vONdc7sjumh2d9iFfBFcyiMY3sjgfEleCnu5qw9kb3iNAzeY_GIk/s320/oled+display.JPG" width="320" /></a></div>
<br />
The OLED is an I2C device. It easily plugs into a Raspberry Pi on pins 1, 3, 5, 6. <br />
<br />
<h3>
Python Library</h3>
<br />
It was harder than I expected to find a good library for the OLED in the Raspberry Pi. Several were expecting Python 2. Others that I expected to work had dependency problems. Adafruit was suggesting using their Circuitpython libraries, but I couldn't get them to work. I ended up downloading <a href="https://github.com/adafruit/Adafruit_Python_SSD1306" target="_blank">Adafruit's legacy Adafruit_SSD1306</a> library and using that.<br />
<br />
<span style="color: red;">Todo</span>: I should really download a contemporary library and get this code working with it.<br />
<br />
<h3>
Interfacing with auto_rx</h3>
<br />
The next decision was about how to interface with auto_rx as seamlessly as possible. Project Horus made that very easy by providing the data I wanted via UDP broadcast. By setting "payoad_summary_enabled" to "True" in the "station.cfg" file of auto_rx, they enable broadcasts. While intended for use with their Chasemapper app, there's no reason we can't piggy-back on that functionality to get the payload data out separately with no mods at all to the stock auto_rx code.<br />
<br />
The basic script<br />
<br />
My "runoled.py" script is very simple. It's basically doing this:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> Initialize OLED</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Initialize UDP Listener</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while (1) </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> update_OLED</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Update first two lines with IP addr and SSID</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Print out the next 6 lines of scrolling text.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> sleep(1)</span><br />
<br />
<br />
The real magic comes in when a new UDP packet comes in. When it does, the interrupt routine updates the 6 lines of rolling text for the OLED display, preparing it for the next update in the main program loop..<br />
<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">def handle_payload_summary(packet)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ...</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line1 = oled_line2</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line2 = oled_line3</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line3 = oled_line4</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line4 = oled_line5</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line5 = oled_line6</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line6 = _time + ' ' + str(_alt)</span><br />
<br />
This just rolls the lines from bottom to top, and puts the latest packet data (time and altitude) on the bottom. As additional packets come in, we'll scroll the oldest up, and then off.<br />
<br />
<h3>
How it looks in action</h3>
<br />
Here's an example of how the OLED works on my Pi. I have the Pi installed in a cheap clear case. I drilled a hole in it to mount the OLED, and poke the riser pins through the cover. They're wired to the GPIO riser inside the case. It's just taped together for now. If I get fancy, I might install some screws. The data in the display is just fabricated times and altitudes that I sent to the script via a test program that uses the same library calls that auto_rx uses.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5WGZ3WxJmmd21HrJPJkMXAk33rKKUo8ta00yoJdeTKewmc9vejq3sw8JtjtpUOxPFBLIsLjXrooVgMSM96B1gaIoAPM95tYQBqUmfcAxU2fqAB5zg3OqAFmDRT6dKa64KwjXsbheoXBQ/s1600/example.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5WGZ3WxJmmd21HrJPJkMXAk33rKKUo8ta00yoJdeTKewmc9vejq3sw8JtjtpUOxPFBLIsLjXrooVgMSM96B1gaIoAPM95tYQBqUmfcAxU2fqAB5zg3OqAFmDRT6dKa64KwjXsbheoXBQ/s400/example.jpg" width="400" /></a></div>
<br />
<h3>
Network display and Wifi setup</h3>
<br />
I configure multiple SSID's on my auto_rx Raspberry Pi. When it's in my home, it joins to my home network. When I'm out in my car, I have it join my cell phone's tether SSID. I have the first two lines of the OLED set up so that I can see the IP address of the Pi, and also the SSID that it has joined. This gives me visual confirmation that the Pi is up and running on the network.<br />
<br />
I rum a <a href="http://xmodulo.com/access-linux-server-behind-nat-reverse-ssh-tunnel.html" target="_blank">proxy ssh solution</a> on my Pi, so that I can SSH into it, even when on my cell phone tether.<br />
<br />
<h3>
Automated startup</h3>
<div>
<br /></div>
<div>
I have the script set up to run out of /etc/rc.local so that it starts at boot time. I can monitor the first two lines of the OLED to confirm the Pi is on the network, and then when packets start arriving, the timestamp and altitude begin scrolling from the bottom. </div>
<div>
<br /></div>
<div>
From /etc/rc.local:</div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">/bin/su --login pi -c /home/pi/src/oled/runoled.py > /tmp/runoled.log 2>&1 &</span></div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
The full source of runoled.py</h3>
<div>
<br /></div>
<div>
Shipped by weight not volume. Some settling may have occurred during shipping. Actual color may vary from the packaging. If you experience any unpleasant side effects, discontinue use immediately.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#!/usr/bin/env python</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># radiosonde_auto_rx - 'Horus UDP' Receiver Example</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># Copyright (C) 2019 Mark Jessop <vk5qi@rfhead.net></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># Released under GNU GPL v3 or later</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># This code provides an example of how the Horus UDP packets emitted by auto_rx can be received</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># using Python. Horus UDP packets are simply JSON blobs, which all must at the very least contain a 'type' field, which</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># (as the name suggests) indicates the packet type. auto_rx emits packets of type 'PAYLOAD_SUMMARY', which contain a summary</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># of payload telemetry information (latitude, longitude, altitude, callsign, etc...)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># Output of Horus UDP packets is enabled using the payload_summary_enabled option in the config file.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># See here for information: https://github.com/projecthorus/radiosonde_auto_rx/wiki/Configuration-Settings#payload-summary-output</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># By default these messages are emitted on port 55672, but this can be changed.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># In this example I use a UDPListener object (ripped from the horus_utils repository) to listen for UDP packets in a thread,</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># and pass packets that have a 'PAYLOAD_SUMMARY' type field to a callback, where they are printed.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import datetime</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import json</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import pprint</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import socket</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import time</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import traceback</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">from threading import Thread</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import Adafruit_GPIO.SPI as SPI</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import Adafruit_SSD1306</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">from PIL import Image</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">from PIL import ImageDraw</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">from PIL import ImageFont</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import subprocess</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">oled_line1 = ""</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">oled_line2 = ""</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">oled_line3 = ""</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">oled_line4 = ""</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">oled_line5 = ""</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">oled_line6 = ""</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">class UDPListener(object):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ''' UDP Broadcast Packet Listener</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Listens for Horus UDP broadcast packets, and passes them onto a callback function</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> '''</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def __init__(self,</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> callback=None,</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> summary_callback = None,</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> gps_callback = None,</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> port=55673):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.udp_port = port</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.callback = callback</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.listener_thread = None</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.s = None</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.udp_listener_running = False</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def handle_udp_packet(self, packet):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ''' Process a received UDP packet '''</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> try:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # The packet should contain a JSON blob. Attempt to parse it in.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> print "Packet received"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> packet_dict = json.loads(packet)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # This example only passes on Payload Summary packets, which have the type 'PAYLOAD_SUMMARY'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # For more information on other packet types that are used, refer to:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # https://github.com/projecthorus/horus_utils/wiki/5.-UDP-Broadcast-Messages</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if packet_dict['type'] == 'PAYLOAD_SUMMARY':</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if self.callback is not None:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.callback(packet_dict)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> except Exception as e:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> print("Could not parse packet: %s" % str(e))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> traceback.print_exc()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def udp_rx_thread(self):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ''' Listen for Broadcast UDP packets '''</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.s.settimeout(1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> try:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> except:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pass</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.s.bind(('',self.udp_port))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> print("Started UDP Listener Thread on port %d." % self.udp_port)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.udp_listener_running = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Loop and continue to receive UDP packets.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while self.udp_listener_running:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> try:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Block until a packet is received, or we timeout.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> m = self.s.recvfrom(1024)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> except socket.timeout:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Timeout! Continue around the loop...</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> m = None</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> except:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # If we don't timeout then something has broken with the socket.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> traceback.print_exc()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # If we hae packet data, handle it.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if m != None:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.handle_udp_packet(m[0])</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> print("Closing UDP Listener")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.s.close()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def start(self):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if self.listener_thread is None:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.listener_thread = Thread(target=self.udp_rx_thread)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.listener_thread.start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def close(self):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.udp_listener_running = False</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.listener_thread.join()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">def handle_payload_summary(packet):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global oled_line1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global oled_line2</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global oled_line3</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global oled_line4</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global oled_line5</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global oled_line6</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ''' Handle a 'Payload Summary' UDP broadcast message, supplied as a dict. '''</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Pretty-print the contents of the supplied dictionary.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pprint.pprint(packet)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Extract the fields that should always be provided.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _callsign = packet['callsign']</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _lat = packet['latitude']</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _lon = packet['longitude']</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _alt = packet['altitude']</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _time = packet['time']</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # The comment field isn't always provided.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if 'comment' in packet:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _comment = packet['comment']</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _comment = "No Comment Provided"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Do nothing with these values in this example...</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line1 = oled_line2</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line2 = oled_line3</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line3 = oled_line4</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line4 = oled_line5</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line5 = oled_line6</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> oled_line6 = _time + ' ' + str(_alt)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">if __name__ == '__main__':</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Raspberry Pi pin configuration:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> RST = None # on the PiOLED this pin isnt used</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Note the following are only used with SPI:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> DC = 23</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SPI_PORT = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SPI_DEVICE = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # 128x64 display with hardware I2C:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Initialize library.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp.begin()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Clear display.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp.clear()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp.display()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Create blank image for drawing.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Make sure to create image with mode '1' for 1-bit color.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> width = disp.width</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> height = disp.height</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> image = Image.new('1', (width, height))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Get drawing object to draw on image.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw = ImageDraw.Draw(image)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Draw a black filled box to clear the image.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.rectangle((0,0,width,height), outline=0, fill=0)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Draw some shapes.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # First define some constants to allow easy resizing of shapes.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> padding = -2</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> top = padding</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> bottom = height-padding</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Move left to right keeping track of the current x position for drawing shapes.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> x = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Load default font.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> font = ImageFont.load_default()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.text((x, top), "Booting", font=font, fill=255)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Display image.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp.image(image)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp.display()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">################################################################################################</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Instantiate the UDP listener.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> udp_rx = UDPListener(</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> port=55673,</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> callback = handle_payload_summary</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> )</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # and start it</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> udp_rx.start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # From here, everything happens in the callback function above.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> try:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while True:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Draw a black filled box to clear the image.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.rectangle((0,0,width,height), outline=0, fill=0)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Shell scripts for system monitoring from here : https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cmd = "hostname -I | cut -d\' \' -f1"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> IP = subprocess.check_output(cmd, shell = True )</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cmd = "/sbin/iwgetid"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> try:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SSID = subprocess.check_output(cmd, shell = True )</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> except:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SSID = '"None"'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SSID = SSID[SSID.find('"')+1:SSID.rfind('"')]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Write two lines of text.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.text((x, top), "IP: " + str(IP), font=font, fill=255)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.text((x, top+8), "SSID: " + str(SSID[0:10]), font=font, fill=255)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.text((x, top+16), oled_line1, font=font, fill=255)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.text((x, top+24), oled_line2, font=font, fill=255)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.text((x, top+32), oled_line3, font=font, fill=255)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.text((x, top+40), oled_line4, font=font, fill=255)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.text((x, top+48), oled_line5, font=font, fill=255)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.text((x, top+56), oled_line6, font=font, fill=255)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Display image.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp.image(image)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp.display()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time.sleep(1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Catch CTRL+C nicely.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> except KeyboardInterrupt:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Close UDP listener.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> udp_rx.close()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Draw a black filled box to clear the image.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> draw.rectangle((0,0,width,height), outline=0, fill=0)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> # Display image.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp.image(image)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> disp.display()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> print("Closing.")</span></div>
</div>
<div>
<br /></div>
<br />
<h3>
Full source of "send.py"</h3>
<br />
This program sends UDP packets to the OLED daemon, so that I can test it without waiting for a balloon to come by. It uses the same subroutine calls that auto_rx uses. Note, this script isn't pretty. It was just hacked at until it worked well enough to test the OLED. I'm not really familiar with the time and datetime libraries or I'm sure I could have done something prettier.<br />
<br />
Note, you'll need to set your PYTHONPATH to point into the autorx directories to use this. Ex:<br />
<span style="font-family: "courier new" , "courier" , monospace;"> $ export PYTHONPATH=/home/pi/src/projecthorus/radiosonde_auto_rx/auto_rx:$PYTHONPATH</span><br />
<br />
Here's the code:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">import time</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import datetime</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from autorx.ozimux import OziUploader</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from time import gmtime, localtime</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">dt = datetime.datetime(2019, 12, 29, 20, 03, 04, 79043)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">gmt = gmtime()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">ozimux = OziUploader(</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ozimux_port = None,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> payload_summary_port = 55673,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> update_rate = 5,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> station='KD2EAT')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">packet = {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'frame' : '1',</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'id' : '1',</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'datetime' : gmt,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'lat' : 42.4417,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'lon' : -76.4985,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'alt' : 22345,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'temp': 32,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'type' : 'PAYLOAD_SUMMARY',</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'freq': '1678',</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'freq_float': 1678.0,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'datetime_dt' : dt,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">_short_time = packet['datetime_dt'].strftime("%H:%M:%S")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">ozimux.add( packet )</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">print "Sent. sleeping 10 to avoid race condition where we shut down before sending the packet."</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">time.sleep(10)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">ozimux.close()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">print "Closed"</span><br />
<div>
<br /></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com1tag:blogger.com,1999:blog-1904678747905486184.post-40636012060479254062019-12-29T09:05:00.000-08:002019-12-29T09:48:16.540-08:00Weather sonde automated prediction <h2>
Weather Sonde automated prediction</h2>
<br />
So, I've gotten the bug to chase weather balloons. The balloons in my region are launched by the National Weather Service from a location adjoining the airport in Buffalo, New York. Only a small percentage of the balloons make it southeast enough to be within reasonable chase distance from my home near Ithaca, New York, 110 air miles away. I ran manual predictions every day, to see how the balloons might progress, but that got tedious. I decided some automation was in order.<br />
<br />
<h3>
CUFS Prediction Software</h3>
To begin, I picked up the <a href="https://github.com/darksidelemm/cusf_predictor_wrapper" target="_blank">CUFS Prediction Wrapper</a> for python. It provided tools to download the latest NWS prediction data as well as tools to run predictions. I run a Raspberry Pi at home, so I set up cron jobs to load the data each morning, and to run predictions for the next 7 days.<br />
<br />
<h3>
Downloading Wind Data</h3>
I set up a cron job to download the wind data at 3am each day:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">0 3 * * * /home/mqh1/bin/wind_grabber.sh > /home/mqh1/balloons/cusf/logs/windgrabber.log 2>& 1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
The contents of the "wind_grabber.sh' script are as follows:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">python \</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">/home/mqh1/balloons/cusf/cusf_predictor_wrapper/apps/get_wind_data.py \</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">--lat=42 --lon=-77 --latdelta=2 --londelta=4 -f 180 \</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">-m 0p25_1hr -o /tmp/gfs/</span><br />
<br />
The lat/long as well as latedelta/londelta parameters are sufficient to include most of the likely flight locations of a weather balloon out of Buffalo. I cache the results in /tmp/gfs on the pi. "-f 180" is looking for the next 180 hours of predictions (7 1/2 days).<br />
<br />
The result is that I have current wind data automatically downloaded on a daily basis that should cover the areas of interest for any NWS flights. Since I do my own High Altitude Balloon launches, as well as pico flights, I don't feel too guilty about downloading this data daily.<br />
<br />
<span style="color: red;">Todo</span>: I'd like to find out when the NWS uploads the data, and tune my download and daily prediction schedule to use the latest data.<br />
<br />
<h3>
Running predictions</h3>
<div>
<br /></div>
<h4>
Typical flights</h4>
I was curious what the best parameters would be to choose for ascent rate / descent rate / and burst altitude for the NWS balloon. Fortunately, two of the three are provided on a regular basis by the NWS. They have an index with the codes for all the launch locations. I was able to <a href="https://www1.ncdc.noaa.gov/pub/data/igra/data/data-y2d/" target="_blank">download a big file</a> with all of the flight data from the last two years of flights. I stuck it in a spreadsheet, and did some number crunching. I had to eliminate a few flights that were clearly outliers. They had really screwy ascent rates or burst altitudes compared to the rest. I removed the anomalies that had glaring differences, and ran averages on the remainder. I got the following averages.<br />
<br />
Average burst altitude: 31,420 meters<br />
Average ascent rate: 5.28 m/sec<br />
<br />
Unfortunately, the NWS doesn't log the descent data, so I don't have a good measure of the average descent rate of the sondes. Based on conversations with folks who do this, it seems like most people go with 5m/s. It can vary widely however.<br />
<br />
<span style="color: red;">Todo</span>: If I get a fully automated station running, I'd like to get better data about descent rates and decide how to handle it. I might use an average, or I might do predictions on each end of the range.<br />
<br />
<h4>
Automated predictions</h4>
The CUSF software makes it really easy to run predictions. I run them after I download the GFS data. I haven't measured the typical download rate yet, so for now, I run them 90 minutes after the wind data download.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">30 4 * * * /home/mqh1/bin/sonde_predict.py > /home/mqh1/balloons/cusf/logs/sonde_predict.log 2>& 1</span><br />
<div>
<br /></div>
<div>
The prediction script is a bit more complicated than the download script. I started from the <b>sonde_predict.py</b> script provided by the CUSF wrapper and made three principal mods. <br />
<br />
<ol>
<li>Determining which predictions are coming in "near' Ithaac</li>
<li>Generating two separate KML files. One for "nearby" and one for "all" predictions.</li>
<li>Emailing results.</li>
</ol>
</div>
<h4>
Determining nearby predictions</h4>
<div>
After the prediction runs, I take the final landing coordinates and determine whether they are "nearby" Ithaca. I do this with a <a href="https://automating-gis-processes.github.io/CSC18/lessons/L4/point-in-polygon.html" target="_blank">Point in Polygon (PIP) algorithm</a>.<br />
<br />
I used Google Earth to draw a bounding box covering an area around Ithaca in which I was willing to search for balloons (Add / Polygon). I then exported the polygon to a KML (right-click, Save Place As), I was then able to grab the coordinates from the KML file, and just copy/paste them to create an array in the code. Note, I had edit the data to reverse the lat/long coming out of the KML file to make them more friendly. In retrospect, I could have left them reversed, and just reversed the order in the code below. Still, I think this is more "human friendly" to see them in the typical order.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"># Coordinate around Ithaca (larger grid)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">nearby_coords = [</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> (42.5894692373013, -77.13750089643533),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> (42.13873798563936, -77.11683620792473),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> (42.1355764571338, -75.91998110781731),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> (42.62563890419801, -75.89559117314741)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ]</span></div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
The coords of the prediction of the payload are in the script in the flight_path[] array, so we grab the last position.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> finalcoords = flight_path[-1]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> latlong = (finalcoords[1], finalcoords[2])</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> landingsite = Point(latlong)</span></div>
</div>
<div>
<br /></div>
<div>
Then we can determine whether it's in the "nearby_coords" polygon we've established:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if landingsite.within(nearby_poly):</span></div>
</div>
<div>
<br /></div>
<h4>
Creating a second KML file</h4>
<div>
<br /></div>
<div>
If we're within the "nearby_poly", I add the KML plot to a separate list. I modified the provided script to generate two KML files. One for "all' predictions, and one for "nearby" predictions. I write both of the predictions into an HTML directory for the web server I run on the Pi. That makes it trivial to download them to my laptop to inspect them with Google Earth.</div>
<div>
<br /></div>
<h4>
Emailing results</h4>
<div>
Finally, I modified the prediction script to generate an email summarizing the number of nearby predictions, and containing HTML links to both the nearby and full KML files. Each morning, I receive an email that tells me if I have nearby predictions. If I do, I can click the link to see the predictions for the coming week that land near Ithaca.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUlwnXRVXQsmG1cUnVxiaW8Q5CP8ya_4RhfHFj4EjyJ1I5GphQrgjhhraSR57EjWy9B0GWrMpPmittLmi5UfFLc9v7WhQjsw9QEss6XIyNzw06bGgfsJsDkqHFShA6N8-ldEQeHOQCZVw/s1600/email.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="355" data-original-width="888" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUlwnXRVXQsmG1cUnVxiaW8Q5CP8ya_4RhfHFj4EjyJ1I5GphQrgjhhraSR57EjWy9B0GWrMpPmittLmi5UfFLc9v7WhQjsw9QEss6XIyNzw06bGgfsJsDkqHFShA6N8-ldEQeHOQCZVw/s400/email.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
In the image below, I highlighted the bounding box for my "nearby" predictions.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcgX2noZCQizc-xkSBevK4UtYJo8QHaNeYHqe_4JoRnbtXu8AlB7iKuhgRsaFCJR97VPgkGPXm8K4AtkK_j2d483BtX4gNHxvpVRBxODviDdiXVffL9J8ejAVbbkYdvWv6hU_FFKRPrSs/s1600/nearby.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="728" data-original-width="1406" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcgX2noZCQizc-xkSBevK4UtYJo8QHaNeYHqe_4JoRnbtXu8AlB7iKuhgRsaFCJR97VPgkGPXm8K4AtkK_j2d483BtX4gNHxvpVRBxODviDdiXVffL9J8ejAVbbkYdvWv6hU_FFKRPrSs/s400/nearby.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span style="color: red;">Todo</span>: I'd like to find a way to provide a link into google maps which will show the 2D representation of the prediction by just clicking a link, rather than having to download a KML file and launch Google Earth.</div>
<div>
<br />
<h3>
Sample Code</h3>
<br />
Disclaimers: Shipped by weight not volume. Some settling may occur during shipping. Not actual size. Consult your computer professional before running. If this code causes and erection lasting more than 4 hours, consult a physician.. no, seriously!<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#!/usr/bin/env python</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># Project Horus</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># CUSF Standalone Predictor Python Wrapper</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># Radiosonde Launch Predictor</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># Copyright 2017 Mark Jessop <vk5qi@rfhead.net></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># In this example we run predictions for a radiosonde launch from Adelaide Airport</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># for every launch for the next 7 days, and write the tracks out to a KML file.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># For this script to work correctly, we need a weeks worth of GFS data available within the gfs directory.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># This can be gathered using get_wind_data.py (or scripted with wind_grabber.sh), using :</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># python get_wind_data.py --lat=-33 --lon=139 --latdelta=10 --londelta=10 -f 168 -m 0p25_1hr -o gfs</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># with lat/lon parameters chaged as appropriate.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># Mods to this script written by Mike Hojnowski / KD2EAT. It is provided for informational purposes. It will</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># not run in a generic environment without modification. In particular, look for the email addresses and for</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># the home directories sprinkled in paths all over.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">import smtplib</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import time</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import fastkml</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import datetime</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from dateutil.parser import parse</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from cusfpredict.predict import Predictor</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from pygeoif.geometry import Point, LineString</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from cusfpredict.utils import *</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from shapely.geometry import Point, Polygon</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">#Email Variables</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">SMTP_SERVER = 'smtp.gmail.com' #Email Server (don't change!)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">SMTP_PORT = 587 #Server Port (don't change!)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">GMAIL_USERNAME = 'somebody@gmail.com' #change this to match your gmail account</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">GMAIL_PASSWORD = 'ImDumbButNotTHATDumb' #change this to match your gmail password</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">SENDTO = 'ThisCouldBeYou@gmail.com' #change to the recipient of the emails</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">## Coordinate around Ithaca (smaller grid)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#nearby_coords = [</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># (42.44387782645627, -77.01612142816262),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># (42.2569086411454,-76.99969683890008),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># (42.3432446683892, -76.17009222210787),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># (42.57580936472674, -76.28671583838107),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># ]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># Coordinate around Ithaca (larger grid)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">nearby_coords = [</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (42.5894692373013, -77.13750089643533),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (42.13873798563936, -77.11683620792473),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (42.1355764571338, -75.91998110781731),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (42.62563890419801, -75.89559117314741)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">nearby_poly = Polygon(nearby_coords)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># BIG polygon for testing. No predictions were near Ithaca the day I was coding, so I made a bigger polygon.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">huge_coords = [</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (43.44387782645627, -78.01612142816262),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (41.2569086411454,-78.99969683890008),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (41.3432446683892, -75.17009222210787),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (43.57580936472674, -75.28671583838107),</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># Just substitude "huge_poly" for "nearby_poly" in the code below, if you need to test during unfavorable predictions.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">huge_poly = Polygon(huge_coords)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># Predictor Parameters</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">PRED_BINARY = "/home/mqh1/balloons/cusf/cusf_predictor_wrapper/apps/pred"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">GFS_PATH = "/tmp/gfs"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">NEARBY_OUTPUT_FILE = "/home/mqh1/public_html/nearby_predictions.kml"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">ALL_OUTPUT_FILE = "/home/mqh1/public_html/all_predictions.kml"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># Launch Parameters - Update as appropriate for your launch site</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># Launch parameters based on NWS data from 01/01/2018 - 12/22/2019 averages</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">LAUNCH_LAT = 42.9414</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">LAUNCH_LON = -78.7193</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">LAUNCH_ALT = (218+500)/2.0; # Barometric and GPS varied. I took the average.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">ASCENT_RATE = 5.26</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">DESCENT_RATE = 5.0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">BURST_ALT = 31420</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># Set the launch time to the current UTC day, but set the hours to the 12Z sonde</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">current_day = datetime.datetime.utcnow()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">LAUNCH_TIME = datetime.datetime(current_day.year, current_day.month, current_day.day, 11, 15)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># Parameter Variations</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># These can all be left at zero, or you can add a range of delta values</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">launch_time_variations = range(0,168,12) # Every 12 hours from now until 7 days time.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># A list to store prediction results</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">nearby_predictions = []</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">all_predictions = []</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">nearby = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># Create the predictor object.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">pred = Predictor(bin_path=PRED_BINARY, gfs_path=GFS_PATH)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># Iterate through the range of launch times set above</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">for _delta_time in launch_time_variations:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> # Calculate the launch time for the current prediction.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> _launch_time = LAUNCH_TIME + datetime.timedelta(seconds=_delta_time*3600)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> print ('Running prediction for ' + str(_launch_time))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> # Run the prediction</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> flight_path = pred.predict(</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> launch_lat=LAUNCH_LAT,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> launch_lon=LAUNCH_LON,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> launch_alt=LAUNCH_ALT,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ascent_rate=ASCENT_RATE,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> descent_rate=DESCENT_RATE,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> burst_alt=BURST_ALT,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> launch_time=_launch_time)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> # If we only get a single entry in the output array, it means we don't have any wind data for this time</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> # Continue on to the next launch time.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if len(flight_path) == 1:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> continue</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> #print(flight_path[-1])</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> coords = flight_path[-1]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> latlong = (coords[1], coords[2])</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #print latlong</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> landingsite = Point(latlong)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #print landingsite.within(nearby_poly)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #print landingsite.within(huge_poly)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> # Generate a descriptive comment for the track and placemark.</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pred_time_string = _launch_time.strftime("%Y%m%d-%H%M")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pred_comment = "%s %.1f/%.1f/%.1f" % (pred_time_string, ASCENT_RATE, BURST_ALT, DESCENT_RATE)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> # Add the track and placemark to our list of predictions</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> all_predictions.append(flight_path_to_geometry(flight_path, comment=pred_comment))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> all_predictions.append(flight_path_landing_placemark(flight_path, comment=pred_comment))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if landingsite.within(nearby_poly):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> # If nearby, add the placemark to our nearby predictions list</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> nearby_predictions.append(flight_path_to_geometry(flight_path, comment=pred_comment))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> nearby_predictions.append(flight_path_landing_placemark(flight_path, comment=pred_comment))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> print("Prediction Succeeds: %s" % pred_comment)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> nearby += 1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"># Write out the prediction data to the KML file</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">kml_comment = "Sonde Predictions - %s" % gfs_model_age()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">write_flight_path_kml(all_predictions, filename=ALL_OUTPUT_FILE, comment=kml_comment)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">write_flight_path_kml(nearby_predictions, filename=NEARBY_OUTPUT_FILE, comment=kml_comment)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">###################</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"># Email portion</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">class Emailer:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> def sendmail(self, recipient, subject, content):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> #Create Headers</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> headers = ["From: " + GMAIL_USERNAME, "Subject: " + subject, "To: " + recipient,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> "MIME-Version: 1.0", "Content-Type: text/html"]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> headers = "\r\n".join(headers)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> #Connect to Gmail Server</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> session.ehlo()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> session.starttls()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> session.ehlo()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> #Login to Gmail</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> session.login(GMAIL_USERNAME, GMAIL_PASSWORD)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> #Send Email & Exit</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> session.sendmail(GMAIL_USERNAME, recipient, headers + "\r\n\r\n" + content)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> session.quit</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">sender = Emailer()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">sendTo = SENDTO</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">emailSubject = "Sonde predictions nearby: " + str(nearby)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">emailContent = str(nearby) + ' predictions have been detected near Ithaca.<br><br>' +\</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> '\nNearby Predictions: <a href=http://thehojos.com/~mqh1/nearby_predictions.kml>http://thehojos.com/~mqh1/nearby_predictions.kml</a><br><br>' +\</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> '\nAll Predictions: <a href=http://thehojos.com/~mqh1/all_predictions.kml>http://thehojos.com/~mqh1/all_predictions.kml</a>'</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">sender.sendmail(sendTo, emailSubject, emailContent)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">print("Email Sent")</span><br />
<br /></div>
kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-12227141170471291852019-02-22T20:59:00.000-08:002019-02-22T20:59:03.809-08:00DTMF Board with BU8872<h2>
Objective</h2>
<div>
I wanted to create an Arduino shield with a BU8872 DTMF chip on it so that I can decode DTMF from an audio source with an Arduino sketch. Since the chip itself was only available in a surface-mount SSOP-16 form factor, I elected to do the entire board with surface mount components.</div>
<div>
<br /></div>
<h2>
Schematic</h2>
<div>
<br /></div>
<div>
I followed the recommended schematic in the datasheet. I'm routing the audio input into the A5 pin on the arduino header. This was done just in case I wanted to attempt audio decoding natively on the Arduino. The three digital pins map to D5,6,7 on the Arduino. I found a surface-mounted crystal that should work with the chip as well.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAgsnmePFKhvl6TPDoOoblVn438-lvI1d5y77o_S4d66aPxFoX28G_lKJkmKV-Kwfd8qbviIH-tBy6JrQk9tVTYgP6QfiyioQh_5Vz1ClNFG6iabMRJ3F_p8KWG40t-X7TPfUPlm-xmqQ/s1600/Schematic.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="564" data-original-width="763" height="295" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAgsnmePFKhvl6TPDoOoblVn438-lvI1d5y77o_S4d66aPxFoX28G_lKJkmKV-Kwfd8qbviIH-tBy6JrQk9tVTYgP6QfiyioQh_5Vz1ClNFG6iabMRJ3F_p8KWG40t-X7TPfUPlm-xmqQ/s400/Schematic.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h2 style="clear: both; text-align: left;">
Board Layout</h2>
<div>
The layout was pretty straightforward. Because I was hand-etching this board, I elected to place components on the back of the board. This was to ease the soldering of the traces to the header pins. In a stacking header, the bottom of the shield is the pin side, and the top has the plastic female sockets. It would be difficult to solder under those plastic sockets to establish the connection, so I put everything on the bottom of the board.</div>
<div>
<br /></div>
<div>
Note, I used a ground plane on this board, but the traces bisected the board. Though not pictured in this board layout, after assembling the board, I bridged a few traces with 1206 Zero ohm resistors to jumper the ground connection around so that I had a full ground plane. </div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUqB46bmfJcJ_6f6kj69LBQNDx79NeJSx5heW-QQ7dzYPV6jeAJd2RumBPWJNcSnT5iRFcWX0nVe2LwhcUilDlXpMD5rKp0KYztklvO1dsvB9JprMatA2VL2p793V89UUAyHu2uDDZGxI/s1600/Board+Layout.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="587" data-original-width="627" height="373" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUqB46bmfJcJ_6f6kj69LBQNDx79NeJSx5heW-QQ7dzYPV6jeAJd2RumBPWJNcSnT5iRFcWX0nVe2LwhcUilDlXpMD5rKp0KYztklvO1dsvB9JprMatA2VL2p793V89UUAyHu2uDDZGxI/s400/Board+Layout.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h2 style="clear: both; text-align: left;">
Finished board</h2>
<div class="separator" style="clear: both; text-align: left;">
The finished board is pictured here. As mentioned above, you can see the two 1206 zero ohm resistors bridging the long traces, assuring that the ground plane has conductivity across the entire board. In a future revision, I'll formally put pads on the board layout to document their placement.</div>
<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/AVvXsEhJhWn8xu2sIQKWWoz66lPkyb_0wAiV8TW-m7tB_ItKCOVEJkH1dNOIwI9ByuzWyfVfWnMtkwwwIESaUkyGE0eLejdt2t_ki8HkgCOf_auP4lUXqySKKWhLcRTKK-nsGdxSyygAwP1hyphenhyphenUA/s1600/Finished+Board.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1194" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJhWn8xu2sIQKWWoz66lPkyb_0wAiV8TW-m7tB_ItKCOVEJkH1dNOIwI9ByuzWyfVfWnMtkwwwIESaUkyGE0eLejdt2t_ki8HkgCOf_auP4lUXqySKKWhLcRTKK-nsGdxSyygAwP1hyphenhyphenUA/s400/Finished+Board.jpg" width="297" /></a></div>
<br />
<h2>
Test Setup</h2>
You can see the board sandwiched on the arduino to the right. There is a logging shield on top, then the DTMF shield, and finally, an Arduino Leonardo underneath. I actually tested this using a VHF receiver module, and transmitting from an HT to send the tones. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg44yQtmeggbNyqmk-uvqIjp_NEQy46YmOtJZEXAhvXLZRAnxuTls0EJsgKEFrueLq8jAry7hIQpNSHqzVCWs4hbElTSSius_kWN40lUmQh9Q6fHxkVDtUnIKTgKleiSBuNnv8VWNt6tr4/s1600/Testing.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg44yQtmeggbNyqmk-uvqIjp_NEQy46YmOtJZEXAhvXLZRAnxuTls0EJsgKEFrueLq8jAry7hIQpNSHqzVCWs4hbElTSSius_kWN40lUmQh9Q6fHxkVDtUnIKTgKleiSBuNnv8VWNt6tr4/s400/Testing.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h2>
Coding challenges</h2>
<div>
The code for this board is fairly straightforward. I only ran into one vexing issue The "DST" pin is supposed to drop cleanly after the DTMF audio tone is dropped. In practice, there seems to be some "jitter" where the DST pin oscillates between 0 and 1 at the end of the tone. The datasheet has a little RC filter which might have compensated for that, but I really didn't understand how to calculate appropriate values for the filter components. In a future board, I'll probably design in the filter, and if I don't want it, I can always jumper it with 0 ohm resistors. Anyway, the code snip below is very simple, and demonstrates what I had to do to get around the jitter issue on the DST pin.</div>
<div>
<br /></div>
<h2>
The Code</h2>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">#define EST_PIN 5</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">#define ACK_PIN 6</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">#define SD_PIN 7</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">#define EST_JITTER 40 // Number of consecutive reads of EST that must be "off" before assuming tone is over</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">int ReadDTMF()</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">{</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> int i, dtmf;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> dtmf = 0;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> // Iterate for the 4 bits of data we need to get from the BU8872</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> for (i = 0; i <4; i++) {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> digitalWrite(ACK_PIN, 1); // Pull ACK high</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> delayMicroseconds(10); // Wait a bit</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> dtmf += (digitalRead(SD_PIN) << i); // Read the value from the SD pin, shifted appropriately and add to the rest</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> digitalWrite(ACK_PIN, 0); // Pull ACK low</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> delayMicroseconds(10); // Wait a bit </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> return(dtmf);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">void setup() </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">{</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> Serial.begin(115200);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> while(!Serial); // Arduino Leonardo issue - wait for the serial port</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> Serial.println("Starting");</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> Serial.flush();</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> pinMode(EST_PIN, INPUT);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> pinMode(ACK_PIN, OUTPUT);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> pinMode(SD_PIN, INPUT);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> // When powered up, the BU8872 is awakened by sending 4 pulses on the ACK pin. </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> // A ReadDTMF will do the trick. We just ignore the result.</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> int ignored = ReadDTMF(); </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">void loop() </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">{</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> int dtmf;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> int i;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> // If we have a DTMF tone, grab it</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> if (digitalRead(EST_PIN)) {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> dtmf = ReadDTMF();</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> Serial.print("Got DTMF code: "); Serial.println(dtmf);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> // We have jitter on the EST pin. Make sure it is clear for several consecutive milliseconds before assuming the tone is over.</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> i = 0;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> while (i < EST_JITTER) {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> if (digitalRead(EST_PIN)) { </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> i = 0; // If the pin jitters high, restart our count</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> } else {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> i++;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> delay(1);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> } </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> Serial.println("RST Clear");</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
</div>
<div>
<br /></div>
<h2>
Sample Output</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLjxXJHebPFNAkDxjdKW9pueKVvhCaQhFhzGJ2GHbRpN2pmqXRxgvGrHR8HqQZZrPl2qnrHo5Cfq8yDlVu2NE92p86_owkrAYKvTW26WrJdEOMX7QdlXjnzWF_Q8GkUus5m1njq-jNklM/s1600/Output.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLjxXJHebPFNAkDxjdKW9pueKVvhCaQhFhzGJ2GHbRpN2pmqXRxgvGrHR8HqQZZrPl2qnrHo5Cfq8yDlVu2NE92p86_owkrAYKvTW26WrJdEOMX7QdlXjnzWF_Q8GkUus5m1njq-jNklM/s400/Output.jpg" width="400" /></a></div>
<div>
<div style="text-align: center;">
<br /></div>
</div>
<h2>
Future Enhancements</h2>
<div>
<ol>
<li>Add the RC filter to the output section.</li>
<li>Test RC filter values to see if the jitter can be eliminated.</li>
<li>Put placeholders in the schematic and board layout for the ground plane jumpers.</li>
<li>Add a trim pot on the audio input line.</li>
<li>Bonus points: Add a test mode to the board and analog pin that puts a peak detector circuit on the pin (or maybe a separate one) and uses the ADC to calculate the RMS voltages of the input audio, to facilitate adjusting the input audio volume.</li>
</ol>
</div>
<h2>
Bill of Materials</h2>
<div>
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse; width: 495px;">
<colgroup><col style="mso-width-alt: 1564; mso-width-source: userset; width: 33pt;" width="44"></col>
<col style="mso-width-alt: 4721; mso-width-source: userset; width: 100pt;" width="133"></col>
<col style="mso-width-alt: 9016; mso-width-source: userset; width: 190pt;" width="254"></col>
<col style="width: 48pt;" width="64"></col>
</colgroup><tbody>
<tr height="19" style="height: 14.4pt;">
<td class="xl66" height="19" style="height: 14.4pt; width: 33pt;" width="44"><b>RefID</b></td>
<td class="xl66" style="width: 100pt;" width="133"><b> Digi-Key</b></td>
<td class="xl66" style="width: 190pt;" width="254"><b>Description</b></td>
<td class="xl67" style="width: 48pt;" width="64"><b>QTY</b></td>
</tr>
<tr height="19" style="height: 14.4pt;">
<td height="19" style="height: 14.4pt;">C1, C2</td>
<td class="xl65">445-1270-1-ND</td>
<td class="xl65">CAP CER 12PF 50V 5% NP0 0603</td>
<td class="xl68">2</td>
</tr>
<tr height="19" style="height: 14.4pt;">
<td height="19" style="height: 14.4pt;"><br />C3</td>
<td class="xl65"><br />445-1316-1-ND</td>
<td class="xl65"><br />CAP CER 0.1uF 25V 10% X7R 0603</td>
<td class="xl68"><br />1</td>
</tr>
<tr height="19" style="height: 14.4pt;">
<td height="19" style="height: 14.4pt;">C5</td>
<td>399-6049-1-ND</td>
<td>CAP ALUM 10UF 20% 63V SMD</td>
<td class="xl68">1</td>
</tr>
<tr height="19" style="height: 14.4pt;">
<td height="19" style="height: 14.4pt;">Q1</td>
<td class="xl65">BU8872FS-E2CT-ND</td>
<td class="xl65">IC DTMF RCVR FOR PHN SSOP-A16 TR</td>
<td class="xl68">1</td>
</tr>
<tr height="19" style="height: 14.4pt;">
<td height="19" style="height: 14.4pt;">Y1</td>
<td>CTX1023CT-ND</td>
<td>CRYSTAL 4.194304MHZ 12PF SMD</td>
<td class="xl68">1</td>
</tr>
</tbody></table>
</div>
<div>
<br /></div>
kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-46567391162191311172018-03-05T19:37:00.000-08:002019-02-16T18:37:10.117-08:00PCB Etching notes<h2>
PCB Etching Notes</h2>
<br />
I did a little research, and found it still took some trial and error to come up with a PCB etching procedure that worked reliably for me. I also noted that, since I don't etch boards all that often, I kept forgetting how I do it. So, with that in mind, here are my notes on PCB Etching for my "Note To Self" category.<br />
<br />
<h3>
Materials</h3>
<br />
<ul>
<li><a href="https://www.radioshack.com/products/radioshack-16oz-pcb-etchant-solution" target="_blank">PCB Etchant Solution</a></li>
<li><a href="https://www.amazon.com/gp/product/B003KU4DSW/" target="_blank">HP Premium Presentation 120g Laser Paper, Glossy, 8.5x11 250 Sheet</a></li>
<li><a href="https://www.amazon.com/gp/product/B01M3V6AQQ" target="_blank">Teenitor Top Quality 20Pcs 100x70x1.5mm Single Sided Copper Clad Laminate PCB Circuit Board</a></li>
<li><a href="https://www.amazon.com/gp/product/B005T8PE4A" target="_blank">MG Chemicals Liquid Tin, 125 ml Bottle</a></li>
<li><a href="https://www.amazon.com/gp/product/B00ZI7MI96" target="_blank">Scotch Thermal Laminator, 2 Roller System, Fast Warm-up, Quick Laminating Speed (TL901C-T )</a></li>
<li><a href="https://www.amazon.com/gp/product/B008FP1GNW" target="_blank">Hydrox Alcohol 99% Isopropyl Pint 16 oz Pack 2</a></li>
<li>Acetone</li>
<li>Steel Wool</li>
</ul>
<h3>
Circuit design</h3>
<div>
<ul>
<li>I use Diptrace to design my PCBs</li>
<li>Set the trace width and spacing to 16 mil, if possible. Thicker traces like this work better for hand etching. I've succeeded with 10 mil, but the traces were very thin and uneven. Thicker is better.</li>
<li>To put letters on the board (copper characters), use "Objects / Place Text". Hit Enter to complete text entry. Then right click on the text. Under "Properties" set the "Type" to "Signal". That will leave the letters as copper on the board, and leave some space around it.</li>
</ul>
<h3>
Saving Gerbers</h3>
</div>
<div>
<ul>
<li>Nothing special. Save the Top layer for use in etching.</li>
</ul>
<h3>
Print using Gerbv</h3>
<ul>
<li>Note, I use Gerbv in Windows. I don't know how these instructions might work on Linux or Mac systems.</li>
<li>By default, gerbv will show the layer in color, rather than in a strong black monochrome. I set the following properties before printing:</li>
<ul>
<li>Under "Layer / Change Color"</li>
<ul>
<li>Set Opacity slider to 255.</li>
<li>Set Color name to "#09090e"</li>
<li>The image will turn black on the screen. </li>
</ul>
<li>Under "Layer / Modify Orientation"</li>
<ul>
<li>Set "Mirroring about Y axis"</li>
<li>This adjusts for the fact that we're putting the paper face down, reversing the image on the copper.</li>
</ul>
</ul>
<li>Do test prints, check that it's very dark, and that the size is right.</li>
<li>Laser print on the Gloss paper and cut it out.</li>
</ul>
<h3>
Copper Clad preparation</h3>
<div>
<ul>
<li>Scrub the copper clad with steel wool to get it shiny.</li>
<li>Clean it with Isopropyl alcohol.</li>
<li>Keep fingers away from the surface.</li>
</ul>
<h3>
Toner transfer</h3>
</div>
<div>
<ul>
<li>Use 1 or 2 pieces of scotch tape to adhere the gloss paper, face down, onto the copper clad.</li>
<li>Warm up the Laminator on the 5 mil (hotter) setting.</li>
<li>Run the copper clad, with paper on upper face, through the laminator about a dozen times. I rotate the copper clad end to end as I do it. After about 8 passes, as the copper is getting really hot, I rotate the copper clad 90 degrees and run it through sideways a few times. When I think it's nearly done, I may do a pass or two with the paper side down.</li>
<li>The copper clad should be unpleasantly hot to handle by the time you're done.</li>
<li>After about a dozen passes, drop the copper clad into a pan of water. Keep it submerged for about 5-7 minutes.</li>
<li>Remove the copper clad from the water, and peel off the paper. If all goes well, the paper should pull away leaving the toner on the board.</li>
<li>The toner should be well secured to the board. Go ahead and rub it with your fingertip to make sure that any glue or paper pulp is removed from the bare copper. Swish it in the water and make sure the copper looks clean.</li>
<li>As the toner dries, it's not uncommon for it to turn a bit white. That's OK. When it does that, make sure the bare copper spots (to be etched) do NOT have white on them. If they do, the acid won't etch the copper away. I usually just keep rubbing with my fingertip until the copper areas remain copper colored when the board is dry.</li>
</ul>
<h3>
Etching</h3>
</div>
<div>
<ul>
<li>Dry the board off, and then drop it into a pan of the etchant.</li>
<li>It takes about 10 minutes or so for the copper to come off. Note, the copper turns pink during one stage of the etching. That's NOT the fiberglass PCB. The pink copper is still conductive, and needs to be etched away. Let is soak longer.</li>
<li>When it's done, you should see yellow PCB where the etching occurred.</li>
<li>Remove from the etchant, and rinse with water.</li>
<li>Note, you can save the etchant and reuse it.</li>
<li>After etching is done, remove the toner from the board with acetone. I put some on a few napkins and scrub the board.</li>
<li>Rinse the board off again, until it's nice and clean. </li>
<li>Inspect the copper and traces to make sure it all came out right.</li>
</ul>
<h3>
Liquid Tin</h3>
</div>
<div>
<ul>
<li>I put liquid tin on the board after etching. It protects the copper from tarnishing so that soldering will be more effective later.</li>
<li>Put the PCB in a dish and pour liquid tin on it. The copper will turn silver immediately.</li>
<li>Rinse with water. Save the unused liquid tin.</li>
</ul>
<div>
<br /></div>
</div>
</div>
kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com2tag:blogger.com,1999:blog-1904678747905486184.post-29653100009740465312018-01-08T20:58:00.000-08:002018-01-11T16:45:00.015-08:00Hojo and the case of the deaf Tentec Omni V<h2>
Hojo and the case of the deaf Tentec Omni V</h2>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSDiXahn8_brXC0frCd_5sKNBNgUy66C3UiMrfo13nLI8knEpAKJDcuj8nOpSuy9QkKjHKSVdFu5GTeMPC4BA8PRPmdXj9mHHgMYpmlgRWmVnPSQdRnqd41W_d04G-z54Ak0GByjVlKBg/s1600/Ten-Tec-Omni-V.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="277" data-original-width="640" height="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSDiXahn8_brXC0frCd_5sKNBNgUy66C3UiMrfo13nLI8knEpAKJDcuj8nOpSuy9QkKjHKSVdFu5GTeMPC4BA8PRPmdXj9mHHgMYpmlgRWmVnPSQdRnqd41W_d04G-z54Ak0GByjVlKBg/s400/Ten-Tec-Omni-V.jpg" width="400" /></a></div>
<br />
A friend from the local ham club handed me his Tentec Omni V. He hadn't used it in a while, and was preparing to sell it to another ham when he noticed it appeared to be very weak on receive. He asked me to take a look.<br />
<h3>
<br />
Power supply</h3>
<br />
Right off the bat, I checked the power supply. It was reading low. The trimmer pot was right next to the activity LED, so I couldn't resist dialing it up to a proper voltage.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu15hK53cR0E9oz2z1uPXwU4dJe2nNhar3kC26e_gGIkvff6YV0bRANL2__cF8i4T9VtTJswLItzstTc0qbiVua0nFi6rL_h0-saVBiSjEAJ7IUKuvq3J8JsUTxtfRCDGCKSwMVJj_Ujo/s1600/20180107_150104.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu15hK53cR0E9oz2z1uPXwU4dJe2nNhar3kC26e_gGIkvff6YV0bRANL2__cF8i4T9VtTJswLItzstTc0qbiVua0nFi6rL_h0-saVBiSjEAJ7IUKuvq3J8JsUTxtfRCDGCKSwMVJj_Ujo/s320/20180107_150104.jpg" width="320" /></a></div>
<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/AVvXsEitjYee0W1Gos93Xs9f3BoOkAN8G2MQnmYju5yJ7lKMd1107x_EmDVcLU3QwL70XdUy9ZgSxJy7-4Elaou_jptepRzpO-EW12iB_hIPSobpPZA1LBc_GRo80o58zJD5uNA5IrEzdsaStyU/s1600/20180109_195252.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitjYee0W1Gos93Xs9f3BoOkAN8G2MQnmYju5yJ7lKMd1107x_EmDVcLU3QwL70XdUy9ZgSxJy7-4Elaou_jptepRzpO-EW12iB_hIPSobpPZA1LBc_GRo80o58zJD5uNA5IrEzdsaStyU/s320/20180109_195252.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBajxq1iRhNmA6mh-Gh8xzT4zplCFZyZegIOdRWppB9PD1vet5WiwF4WBOJaRHxVNHHebhENNDihCGzVaKIVEQnKwJC7cB352lhaScfH45xirPffmGFbkiMoxxxMUyfhSJoObXoCi0MDw/s1600/20180107_150309.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBajxq1iRhNmA6mh-Gh8xzT4zplCFZyZegIOdRWppB9PD1vet5WiwF4WBOJaRHxVNHHebhENNDihCGzVaKIVEQnKwJC7cB352lhaScfH45xirPffmGFbkiMoxxxMUyfhSJoObXoCi0MDw/s320/20180107_150309.jpg" width="320" /></a></div>
<br />
<h3>
Initial problems</h3>
I powered up the rig and found the LED display blank. I opened the covers and wiggled a few things directly behind the LED display. It flashed back on. The board was not seated very well, apparently.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEKQVyKOY-4XEl8qAW2FcSAEOWjPcw1-oRE79_uacnIZoO9OiZPHkhQtdcmzT900t-O184qfR4FGCw0wJKRNrEQ2BwObz1xOKYJ7M6qIF6hR5wWkaWbawlqwrrzEjurkev35MdyTAREHw/s1600/20180109_193843.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEKQVyKOY-4XEl8qAW2FcSAEOWjPcw1-oRE79_uacnIZoO9OiZPHkhQtdcmzT900t-O184qfR4FGCw0wJKRNrEQ2BwObz1xOKYJ7M6qIF6hR5wWkaWbawlqwrrzEjurkev35MdyTAREHw/s320/20180109_193843.jpg" width="320" /></a></div>
<br />
<br />
At the same time, one of two incandescent bulbs behind the S-meter was intermittent. I snugged up the fixture with a pair of pliers, and the bulb became more reliable.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil7lcnx4pIWxeM60xz6uKAvBFsPinERuGcna1adgiLJRkK3Yl_IwniluhGEEzh04pDVFW0mprVdGwM2Rmf109pjQgZz7en3x2u9U4lOv6xKD-M8uaHOJe-z9iEH6Wc71Lw4Kx2cS2EQhQ/s1600/20180109_193908.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil7lcnx4pIWxeM60xz6uKAvBFsPinERuGcna1adgiLJRkK3Yl_IwniluhGEEzh04pDVFW0mprVdGwM2Rmf109pjQgZz7en3x2u9U4lOv6xKD-M8uaHOJe-z9iEH6Wc71Lw4Kx2cS2EQhQ/s320/20180109_193908.jpg" width="240" /></a></div>
<br />
<br />
Having taken care of those little physical problems, I could finally try injecting a signal into the radio. Sure enough, it was quite hard of hearing. I needed a signal of about -20 dbm to be discernible. I confirmed the problem existed across multiple bands.<br />
<br />
<h3>
Diagnostics</h3>
I opened up the radio and started tracing the signal. I injected a tone on 14 Mhz (1) and followed the path. It got through the antenna selection circuits and initial attenuator just fine. It reached the front-end mixer board (2), and exited that board mixed to 9 Mhz (3). I also verified that the signal disappeared when the injected signal was stopped. So far so good. The signal passed through the 9 MHZ IF board (3) -> (4) unmolested and was amplified slightly. From there, it went into the Pass Band Tuning board (4), and finally into the AF/IF board (5). There's where the trouble began.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwF55_xFRziUtHgdGadP878T_1Atud0-mABse0NCqu6kl8oJWoFp-nA85sUPvD92dE61pFF9DvVxQA4RG-349iwGVR-1YTJjMwCqhHrlc0B7N9Ir0KTnknJiTNSVoku307dt5vN7Iq-N4/s1600/20180109_194142.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwF55_xFRziUtHgdGadP878T_1Atud0-mABse0NCqu6kl8oJWoFp-nA85sUPvD92dE61pFF9DvVxQA4RG-349iwGVR-1YTJjMwCqhHrlc0B7N9Ir0KTnknJiTNSVoku307dt5vN7Iq-N4/s400/20180109_194142.jpg" width="300" /></a></div>
<br />
<br />
I measured a good signal coming into the board (5 above). It passes through a few amplifier stages first thing. I checked at the end of that stage and found no signal. Tracing back, I found the signal disappeared after passing through a J310 Fet.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_GjLJGSWqfRfJhpXWFoCTzYlvkgYurkf5b1hyphenhyphenyjheC1UX-uSc3gAKhyphenhyphenffJbmHVOGWrMIRl28Ru4b7-K9PONOLy-dBQnzrB1hV6ZM0c3XiABt6wf3hqCeTU6pBVAhAUGiMXAJgswtRuRM/s1600/Omni+5+FET+problem.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="501" data-original-width="749" height="267" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_GjLJGSWqfRfJhpXWFoCTzYlvkgYurkf5b1hyphenhyphenyjheC1UX-uSc3gAKhyphenhyphenffJbmHVOGWrMIRl28Ru4b7-K9PONOLy-dBQnzrB1hV6ZM0c3XiABt6wf3hqCeTU6pBVAhAUGiMXAJgswtRuRM/s400/Omni+5+FET+problem.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I next confirmed that there was power on the "+REG" rail. It was reading 8.78 volts. Unfortunately, I had no idea what the voltage was <i>supposed</i> to be. After about 40 minutes of tracing the +REG rail back to a power board, I found a knockoff sentence in the service manual that +REG should be 8.5 volts. So, it was a touch high, but shouldn't have been a problem for this situation.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Having narrowed it down to this Fet, I checked my parts bin, and voila, I had a few in stock!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3 style="clear: both; text-align: left;">
The repair</h3>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh407GcFsKyHVG6GXU-pRCKWs4XD2n_P62JY-7NSGLDQi6_O4afv51r5rujt30r01cQIJ4-v_BllFYgjpOo4Fo6mL_jTIM0XRe5pucU0JwZ1AMUWcac4atU7qFx2dSw_Z5lDOkUoHiOCio/s1600/20180108_122006.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh407GcFsKyHVG6GXU-pRCKWs4XD2n_P62JY-7NSGLDQi6_O4afv51r5rujt30r01cQIJ4-v_BllFYgjpOo4Fo6mL_jTIM0XRe5pucU0JwZ1AMUWcac4atU7qFx2dSw_Z5lDOkUoHiOCio/s320/20180108_122006.jpg" width="240" /></a></div>
The board had approximately a jillion connectors on it. I carefully photographed everything before removing it.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Now that I had a better view of the FET in question, I confirmed the model, and that my parts-bin FET matched.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqgGdnuIoywF1tUpkDyMBV2Pe3W4tZMxFMvm74KB4jWYqNcM8Kr02bmBqVDweNF4LHrgIhNiXh_UOMLdahI5G5WSTOqU6P8e9snDtybuxamc94xZD0HSxKrVCymLUHF465dywt8F4CB6s/s1600/20180108_122908.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="743" data-original-width="581" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqgGdnuIoywF1tUpkDyMBV2Pe3W4tZMxFMvm74KB4jWYqNcM8Kr02bmBqVDweNF4LHrgIhNiXh_UOMLdahI5G5WSTOqU6P8e9snDtybuxamc94xZD0HSxKrVCymLUHF465dywt8F4CB6s/s320/20180108_122908.jpg" width="250" /></a></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPFxqpHygk3K7XMTHC-kl4TSs-ERFHn_BHT5yWPhW22oQoqxNqpuKI1kkUu017Cka-mfQjz2WBhi6Jjc1M5mWd4WDknXinVb9d8t6hhmftMMLFde1jDZPlcup-q2z4oD77hQhR3AszzHQ/s1600/20180108_123001.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1157" data-original-width="781" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPFxqpHygk3K7XMTHC-kl4TSs-ERFHn_BHT5yWPhW22oQoqxNqpuKI1kkUu017Cka-mfQjz2WBhi6Jjc1M5mWd4WDknXinVb9d8t6hhmftMMLFde1jDZPlcup-q2z4oD77hQhR3AszzHQ/s320/20180108_123001.jpg" width="216" /></a><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I pulled the FET and replaced it.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4eMQAL94u-cnxHxKe6NdUz9QZu8tzr30iEpGNm_bXN_vccZyIGgeq6Oxz4Tj1SDN1RlqIbaKYoHW-2FAVKmtaCpf7OE5KdKmd0mm-C9lUWiOp3VMFCDVHqtkflWtwGJYLJ6jKdBZpW6A/s1600/20180108_123527.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4eMQAL94u-cnxHxKe6NdUz9QZu8tzr30iEpGNm_bXN_vccZyIGgeq6Oxz4Tj1SDN1RlqIbaKYoHW-2FAVKmtaCpf7OE5KdKmd0mm-C9lUWiOp3VMFCDVHqtkflWtwGJYLJ6jKdBZpW6A/s320/20180108_123527.jpg" width="240" /> </a></div>
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVeaPQzFGPDJ9BOaxIvKOmziZ9r8Eoaw1BmZgZoLtTUSjGtpNBuvPnjbB-bNwfjClqa9oCeQhzZW18bCp597ynDWDRE7vcmosVSuGK-g-3BpsoHEdB6L-OmDvLjVEyWVZvZC8d5h4YUjY/s1600/20180108_124116.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1409" data-original-width="1465" height="307" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVeaPQzFGPDJ9BOaxIvKOmziZ9r8Eoaw1BmZgZoLtTUSjGtpNBuvPnjbB-bNwfjClqa9oCeQhzZW18bCp597ynDWDRE7vcmosVSuGK-g-3BpsoHEdB6L-OmDvLjVEyWVZvZC8d5h4YUjY/s320/20180108_124116.jpg" width="320" /></a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaPmR5n0G2dIg6j1xoTxKc9_racOG9-thIeDRSN93aeqwC6y9UtedKW2FsNKmddHpQvA7AJeWQyvKWVPzwzCxcwmeTZrFeOLr7l9Pjkvf7T4nQ1gnS9ESo3bUugtQx2WqeuqjhX8ycIRA/s1600/20180108_124111.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1273" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaPmR5n0G2dIg6j1xoTxKc9_racOG9-thIeDRSN93aeqwC6y9UtedKW2FsNKmddHpQvA7AJeWQyvKWVPzwzCxcwmeTZrFeOLr7l9Pjkvf7T4nQ1gnS9ESo3bUugtQx2WqeuqjhX8ycIRA/s320/20180108_124111.jpg" width="254" /></a></div>
<br />
<br />
<h3>
Testing</h3>
After putting things back together, the radio was hearing loud and clear. My Service Monitor can generate signals as low as -130 DBM. The signal was clearly discernible all the way down.<br />
<br />
Talking with the owner, he was satisfied that the repair was sufficient, so I stopped there, rather than attempting to find alignment instructions.<br />
<b><br /></b>
<b>Success!</b>kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-17746738995440298122018-01-01T20:17:00.001-08:002018-01-01T20:20:13.173-08:00Zeta FX-79 Buffalo Build - Port planning, Smartport and RSSI<h2 class="tr_bq">
Zeta FX-79 Buffalo Build - Port planning, Smartport and RSSI</h2>
<h3>
Serial Port Planning</h3>
The Omnibus F4 Pro V2 offers 3 UARTs.<br />
<ul>
<li>UART1 - Used for SBUS</li>
<li>UART6 - Available</li>
<li>UART3 / I2C - Available if I2C is not needed</li>
</ul>
<div>
My <a href="https://hobbyking.com/en_us/ublox-neo-m8n-gps-with-compass.html?___store=en_us" target="_blank">Ublox Neo-M8N GPS with Compass</a> module will need UART6 for the GPS, and the I2C pins for the Compass functionality. Unfortunately, I want to do Smartport as well, but don't have a UART. So, instead, I'll use softserial for the Smartport connection.</div>
<div>
<br /></div>
<div>
My configuration will be as follows:</div>
<div>
<ul>
<li>UART1 - Used for SBUS</li>
<li>UART6 - GPS</li>
<li>UART3 / I2C - Compass</li>
<li>Softserial - Smartport</li>
</ul>
<h3>
Smartport</h3>
<div>
The Softserial ports are available on the Omnibus F4 Pro V2 via two pads on the front of the board. I followed the <a href="https://github.com/iNavFlight/inav/blob/master/docs/Board%20-%20Omnibus%20F4.md" target="_blank">FrSky SmartPort using SoftwareSerial</a> procedure at the bottom of the Omnibus F4 page. They call for a 1k ohm resistor between the RX and TX pins. I had one in 0603 in my parts bin, so I put it between the pads, and then attached a small wire-wrap wire to the RX pin. It ended up working fine.</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivqisIbA6awWRT6D-MqAa3vUv3IsYgs6Z-1Ij4SZFb1s3vtv4uFVGfU6YuaVQiMwysr9UTRMxbJDtcwov8THbe1UCCfaStGa04JWGWQcnhhNyko3GjZUu26ghIEeL4_4-bqL3jHOcZ4Hg/s1600/20180101_125617.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivqisIbA6awWRT6D-MqAa3vUv3IsYgs6Z-1Ij4SZFb1s3vtv4uFVGfU6YuaVQiMwysr9UTRMxbJDtcwov8THbe1UCCfaStGa04JWGWQcnhhNyko3GjZUu26ghIEeL4_4-bqL3jHOcZ4Hg/s400/20180101_125617.jpg" width="400" /></a></div>
I love surface mount soldering! Here's a 1K 0603 resistor from my parts bin.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwabYhUZqje0E0HWD_yIqHAndZ1MkKWxHOfaFpQ7QJFWUnd_FbcGM6njBmoliLx7paVNNzSIauznYwNJXomZ0EdEQHp0Me73SH6DBMXD7HALP7P5jBml0SzcFDJqqdx0NAmwVsj5Hi9aU/s1600/softserial+closeup+1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1305" data-original-width="1600" height="326" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwabYhUZqje0E0HWD_yIqHAndZ1MkKWxHOfaFpQ7QJFWUnd_FbcGM6njBmoliLx7paVNNzSIauznYwNJXomZ0EdEQHp0Me73SH6DBMXD7HALP7P5jBml0SzcFDJqqdx0NAmwVsj5Hi9aU/s400/softserial+closeup+1.jpg" width="400" /></a><br />
There's the resistor, temporarily sitting on top of the processor. I circled the two pads it's going to be crossing below.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuxPjHkCptHpxumTbIWcwlkPz7-G0jLO5rRBteZanzJqViXZ6-6OeMP_x3ahMYKT5WqOXWhLzRffVPIKiZuUQuDim9hX64yRKm52OwkKN-8mx4AvNO32d3tkWGlB38UuJHaTvFur07Ab8/s1600/softserial+closeup+2.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1273" data-original-width="1600" height="317" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuxPjHkCptHpxumTbIWcwlkPz7-G0jLO5rRBteZanzJqViXZ6-6OeMP_x3ahMYKT5WqOXWhLzRffVPIKiZuUQuDim9hX64yRKm52OwkKN-8mx4AvNO32d3tkWGlB38UuJHaTvFur07Ab8/s400/softserial+closeup+2.jpg" width="400" /></a><br />
<div>
Here's the resistor installed, with a bit of Wire Wrap wire connecting to the RX pin. </div>
</div>
<div>
<br /></div>
<div>
After confirming that all worked well, I went ahead and secured this wire with a dab of glue to the top of the processor chip, for strain relief.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
In order to use the Softserial port, it needs to be enabled in the iNav Configurator.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC1MNdH1p-fshXTlm6awCKrpZ5ZDGH_6_Co8UEZ3cgzwJll0IM198V-IG-vLUcA5puLW4WQmw13dbEVnDhK8Swj4Pgq9_phSDqTuiLUXT41ClY913ozxSR8vTYQNWWlHR0F6_MNmxgjHU/s1600/Enable+Software+Serial.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1004" data-original-width="1443" height="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC1MNdH1p-fshXTlm6awCKrpZ5ZDGH_6_Co8UEZ3cgzwJll0IM198V-IG-vLUcA5puLW4WQmw13dbEVnDhK8Swj4Pgq9_phSDqTuiLUXT41ClY913ozxSR8vTYQNWWlHR0F6_MNmxgjHU/s400/Enable+Software+Serial.jpg" width="400" /></a></div>
I enabled Softserial, and while I was at it, also enabled telemetry.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNUMXKnCS-Cc8EdtXqnT6fTt4ue_wWotsepI8kuOBTfWQA31ApBbm6WX8gzS9PW4kg2C5JK1PHdZx_2Ds7TYvPzplIzIW0UFxXf1_tQJBfVMfQbaOszHNBF8ynxYIr9XyeDypdIqPkIb4/s1600/Port+definition.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1004" data-original-width="1443" height="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNUMXKnCS-Cc8EdtXqnT6fTt4ue_wWotsepI8kuOBTfWQA31ApBbm6WX8gzS9PW4kg2C5JK1PHdZx_2Ds7TYvPzplIzIW0UFxXf1_tQJBfVMfQbaOszHNBF8ynxYIr9XyeDypdIqPkIb4/s400/Port+definition.jpg" width="400" /></a></div>
After a reboot, I went into the ports page, found the Softserial port, and configured it for Smartport at 57,600 bps, as suggested.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
The final step was to go into the CLI and apply two settings:<br />
<br />
<blockquote>
set smartport_uart_unidir=OFF<br />
set telemetry_inversion=on</blockquote>
Having done that, I was able to go onto my transmitter, do a "discover", and telemetry values populated from the flight controller.<br />
<br />
One additional note. The GPS telemetry does not appear for a "discover" on the radio until you have a GPS lock. This caused me quite a bit of frustration. Once the telemetry is discovered, it will be on the list on the radio, thereafter. You do not have to rediscover it after it is in the list.<br />
<br />
<br />
<h3>
RSSI</h3>
<br />
The Omnibus F4 V2 uses a tiny little pad in the middle of the board to receive RSSI data from the receiver. Many people are soldering a small wire to the pad, and just hanging it off the Flight Controller, with a bunch of glue and hope holding it in place. I didn't really like that solution. Instead, I opted to hijack the RAM pins to make the RSSI externally available.<br />
<br />
The RAM pins on the Omnibus F4 pro V2 are wired together, but otherwise isolated, if you do not solder a jumper elsewhere on the board, linking them either to VCC or the 5v rail. Since I left the jumper undone, the RAM pins are just tied to each other. Since I'm powering my Camera and VTX via an external wiring harness, the RAM pins are unused.<br />
<br />
I soldered a small jumper from the RSSI pad to one of the RAM pins. I will then solder a heavier gauge wire into the other RAM pin hole, and connect that to the wiring harness going off to the receiver. This should provide greater strain relieve for the RSSI jumper. I think this is a much more resilient solution. Here's the jumper wire going to one of the RAM pins. This picture does not illustrate the wire harness leading off the board.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRj8uAdORwP3JuSE7Y7qpDkBacfREQU_3uIk84Wgh874LSVCSZhzXbB-dEzMZogi2qncMavfF0NaIVCIubGlqA647aKZeriMtSDqzjX49qsnaAWkX6ZLhO_Kdtd0wM-H5PnXplZd3UVVw/s1600/20171222_144448.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRj8uAdORwP3JuSE7Y7qpDkBacfREQU_3uIk84Wgh874LSVCSZhzXbB-dEzMZogi2qncMavfF0NaIVCIubGlqA647aKZeriMtSDqzjX49qsnaAWkX6ZLhO_Kdtd0wM-H5PnXplZd3UVVw/s400/20171222_144448.jpg" width="400" /></a></div>
<div>
<br /></div>
One thing to note. I was concerned that the RSSI pin might have problems. The MCU on the F4 board is running at 3.3 volts. The receiver runs at 5 volts. I was worried that the RSSI pin might be overdriven by the receiver. I wondered whether a voltage divider would be needed to scale the voltage down. Fortunately, FrSky had considered this. The RSSI value is documented to be a PWM value between 0 - 3.3 volts. So, even though the receiver is running at 5 volts, it is safe to run the wire to the Flight Controller. So, the result was, I didn't have to do anything special. I felt better having researched it, however.<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-53496002969640007762017-12-28T20:43:00.001-08:002018-01-01T20:18:23.205-08:00Zeta FX-79 Buffalo Build - Wiring plan<h2>
Zeta FX-79 Buffalo Build - Wiring plan</h2>
<br />
The stock configurations for the FX-79 seem to recommend running with 3s lipos, so that's what I'm planning to do. I'll be using two 5000 mah batteries in parallel. My Flight Controller is rated up to 5s, as far as I can tell on the forums, so I have the option of upgrading later if I wish.<br />
<br />
The Omnibus F4 Pro V2 comes with an onboard 3 amp BEC. However, as I read the forums, I understand that it can get rather warm. As a precaution, I'm planning to run very little through the onboard BEC.<br />
<br />
<h3>
Power Plan</h3>
<ul>
<li>Direct from batteries</li>
<ul>
<li>Flight controller - rated to 5s (I think).</li>
<li>Runcam and VTX (through a filter). Both are rated up to 6s.</li>
<li>ESC (via the Flight Controller for current measuring)</li>
</ul>
<li>BEC on Flight Controller</li>
<ul>
<li>GPS</li>
<li>Uart inverter</li>
</ul>
<li>External BEC</li>
<ul>
<li>Servos</li>
<li>Receiver</li>
</ul>
<li>External BEC (auxiliary port)</li>
<ul>
<li>Lights or special effects</li>
</ul>
</ul>
<div>
I roughed out a wire plan on my office whiteboard.</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4ko2vmk2mQlPheEw5Oa5ULo5HxmpskMeAs_8xEcKebJtBv2ZRe-va-tkOINyPcQeuMava_aRdWAzhyphenhyphenmSQq6DZDY_ZuZ7WlYblZEUsyMlnTylfHNryyB0pcpzKCDa6YI0164gsLaGdamM/s1600/20171220_154813.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4ko2vmk2mQlPheEw5Oa5ULo5HxmpskMeAs_8xEcKebJtBv2ZRe-va-tkOINyPcQeuMava_aRdWAzhyphenhyphenmSQq6DZDY_ZuZ7WlYblZEUsyMlnTylfHNryyB0pcpzKCDa6YI0164gsLaGdamM/s640/20171220_154813.jpg" width="480" /></a></div>
<br />
<h3>
About Club24A</h3>
<br />
There are known problems with this board with regards to reporting accurate current if VCC is jumpered into the Camera or VTX pins. It's known as "Club24A" in the forums. I'm avoiding that problem entirely by not using the onboard jumper to apply power to the RAM pins. I'm actually hijacking the RAM pins for another purpose (RSSI). I'm providing the power to the camera and VTX via the wiring harness, apart from the Omnibus board, so I do not expect any of the Club24A issues.<br />
<br />
<h3>
Riser pins</h3>
<br />
Since I'm providing power to most of the external devices via the external BEC rather than through the FC, it's led to a rather convoluted wiring harness. While the FC provides 3 pins in most places, for powered servo cables, I'm generally using just the signal wire, and drawing power from my external BEC. I decided to solder wires directly onto the Flight Controller and terminate with female servo connectors. This makes the flight controller a bit of a hassle to wire up, but with care, it should be alright. <br />
<br />
I'm planning to use extension cables everywhere, so that the FC can be removed for calibration or reprogramming if necessary. Also, being the most convoluted part of the build, it should be fairly easy to transplant, if the plane crashes badly enough that I need to replace the foam.<br />
<br />
Here's the flight controller wiring, about 3/4 done. I'll update this picture when it's complete. Note the heavy cables which lead to the batteries and ESC. The servo cables patch into other cables to provide power.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq6hR5yhy_FmGSa00tFU7Y9zpF7hHvTnKaL4XyYG3O9oNI6K3WSib6bv_U5Q14dtiNMFV0fafKRhdpltTMVMKzO0as4gYu4CoJ78vfBQKWYlFA1eYkJt5AMZqA5XXnQ7oCCtaCbOx7Akw/s1600/20171228_200346.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq6hR5yhy_FmGSa00tFU7Y9zpF7hHvTnKaL4XyYG3O9oNI6K3WSib6bv_U5Q14dtiNMFV0fafKRhdpltTMVMKzO0as4gYu4CoJ78vfBQKWYlFA1eYkJt5AMZqA5XXnQ7oCCtaCbOx7Akw/s400/20171228_200346.jpg" width="400" /></a></div>
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-19988827098078101362017-12-25T16:51:00.003-08:002017-12-25T16:51:36.383-08:00Zeta FX-79 Buffalo Build - Preliminaries<h2>
Zeta FX-79 Buffalo Build</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXS1iiSLisPQbTlMwKjvWYKf5R1CS3AZvrveZcTPAT4KmwCwGP_9RjEwEhPm6YK0xXPFoSzNg0LHMbmZQRA3bQrqxRs7lyXiF_sktuCsWBbuMkAyIMZYK8YquumElPV7sk1kLswu5yBVk/s1600/thumbnail.jpg" imageanchor="1"><img border="0" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXS1iiSLisPQbTlMwKjvWYKf5R1CS3AZvrveZcTPAT4KmwCwGP_9RjEwEhPm6YK0xXPFoSzNg0LHMbmZQRA3bQrqxRs7lyXiF_sktuCsWBbuMkAyIMZYK8YquumElPV7sk1kLswu5yBVk/s320/thumbnail.jpg" width="320" /></a><br />
<br />
My wife bought me a <a href="https://www.banggood.com/ZETA-FX-79-Buffalo-FPV-Flying-Wing-EPO-2000mm-Wingspan-RC-Airplane-Kit-p-1092449.html?cur_warehouse=USA" target="_blank">Zeta FX-79 Buffalo flying wing</a> for Christmas. I'll be chronicling the build in this blog post. My motivation for this plane was to have an FPV platform to use for balloon "Search and Rescue" operations. I'd like to have an FPV camera, and a higher resolution camera for post-flight analysis. I'd also like to be able to fly my <a href="http://www.kenwood.com/usa/com/amateur/th-d72a/" target="_blank">Kenwood TH-D72A radio</a> as an airborne APRS digipeater platform. Since my trackers are very low power (10mw or so), the hope is that an airborne digipeater might be helpful in recovery operations.<br />
<br />
I purchased the fittings from a variety of sources. The Bill of Materials follows. <br />
<br />
<br />
<ul>
<li><a href="https://www.banggood.com/ZETA-FX-79-Buffalo-FPV-Flying-Wing-EPO-2000mm-Wingspan-RC-Airplane-Kit-p-1092449.html?cur_warehouse=USA" target="_blank">Zeta FX-79 Buffalo</a></li>
<li><a href="https://hobbyking.com/en_us/propdrive-v2-3548-900kv-brushless-outrunner-motor.html?___store=en_us" target="_blank">Propdrive V2 3548 900kv Brushless Outrunner</a></li>
<li><a href="https://hobbyking.com/en_us/hobbyking-yep-60a-2-6s-sbec-brushless-speed-controller.html?___store=en_us" target="_blank">YEP 60A (2~6S) SBEC Brushless Speed Controller</a></li>
<li><a href="https://hobbyking.com/en_us/ubec-duo-4a-5-12v-4a-5v.html?___store=en_us" target="_blank">UBEC DUO 4A/5~12V & 4A/5V</a></li>
<li><a href="https://hobbyking.com/en_us/gws-style-slowfly-propeller-12x3-8-black-ccw-4pcs.html" target="_blank">GWS Style Slowfly Propeller 12x3.8 Black</a></li>
<li><a href="https://hobbyking.com/en_us/corona-939mg-metal-gear-servo-2-5kg-0-14sec-12-5g.html?___store=en_us" target="_blank">(5) Corona 939MG Metal Gear Servo 2.5kg / 0.14sec / 12.5g</a></li>
<li><a href="https://alofthobbies.com/frsky-x8r-8-16-channel-receiver-antenna-combo.html" target="_blank">FrSky X8R - 8/16 Channel Receiver (Antenna Combo)</a></li>
<li><a href="https://www.banggood.com/Antenna-Mount-Holder-for-Frsky-X8R-X6R-L9R-Receiver-3D-Printed-p-988709.html?cur_warehouse=CN" target="_blank">Antenna Mount Holder for Frsky X8R</a></li>
<li><a href="http://shop.myairbot.com/index.php/flight-control/omnibus-f4-pro-v2.html" target="_blank">OMNIBUS F4 Pro (v2) Flight Controller</a></li>
<li><a href="https://hobbyking.com/en_us/ublox-neo-m8n-gps-with-compass.html?countrycode=US" target="_blank">Ublox Neo-M8N GPS with Compass</a></li>
<li><a href="https://www.getfpv.com/fpv/cameras/runcam-eagle-2-fpv-camera-4-3.html" target="_blank">RunCam Eagle 2 FPV Camera - 4:3</a></li>
<li><a href="https://www.getfpv.com/fpv/video-transmitters/lumenier-tx5g6r-mini-600mw-5-8ghz-fpv-transmitter-with-raceband-w-pigtail-sma.html" target="_blank">Lumenier TX5G6R Mini 600mW 5.8GHz FPV Transmitter</a></li>
<li><a href="https://hobbyking.com/en_us/zippy-flightmax-5000mah-3s1p-20c.html?___store=en_us" target="_blank">ZIPPY Flightmax 5000mAh 3S1P 20C</a></li>
<li><a href="http://smallpartscnc.com/index.php?route=product/product&path=20_185&product_id=226" target="_blank">Zeta FX-79 Buffalo Aluminum Motor Mount</a></li>
</ul>
<div>
I'll be doing the build with the Omnibus F4 Pro V2 flight controller, which includes an OSD and can relay Smartport Telemetry back to my <a href="https://alofthobbies.com/frsky-taranis-plus-transmitter.html" target="_blank">Tanaris Plus</a> transmitter.</div>
<div>
<br /></div>
<div>
In future posts, I'll document the build process and initial flights.</div>
kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-32792725701816776662017-08-20T08:46:00.000-07:002017-08-20T08:46:31.220-07:00AFSK modulation experiments - success!<h2 class="tr_bq">
AFSK modulation experiments - success!</h2>
<br />
So, in the previous blog entry, I confirmed that I had come up with some numbers and timer values to make the frequencies I needed. For posterity, I'll document them here.<br />
<br />
<h3>
DAC configration</h3>
I'm running my DAC with 24 data points. I generated my sinewave table using the script that I <a href="https://hojoham.blogspot.com/2017/08/generating-sinewave-table-for-my-dac.html" target="_blank">blogged previously</a>. Based on the results from <a href="https://hojoham.blogspot.com/2017/08/afsk-modulation-experiments-part-4.html" target="_blank">AFSK modulation experiments - part 4</a>, I set the PPM on the Si5351b to 30, and the DAC_PCT to 35 to achieve about 3000hz deviation. It looks as follows:<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">#define DAC_PCT 35 // Percentage of DAC output</span><span style="font-size: x-small;">#define SINE_RES 24</span><span style="font-size: x-small;">const uint16_t sinewave[SINE_RES] = {</span><span style="font-size: x-small;"> (0 * DAC_PCT / 100) + 2048, (530 * DAC_PCT / 100) + 2048, (1023 * DAC_PCT / 100) + 2048,</span><span style="font-size: x-small;"> (1448 * DAC_PCT / 100) + 2048, (1773 * DAC_PCT / 100) + 2048, (1978 * DAC_PCT / 100) + 2048,</span><span style="font-size: x-small;"> (2047 * DAC_PCT / 100) + 2048, (1978 * DAC_PCT / 100) + 2048, (1773 * DAC_PCT / 100) + 2048,</span><span style="font-size: x-small;"> (1448 * DAC_PCT / 100) + 2048, (1024 * DAC_PCT / 100) + 2048, (530 * DAC_PCT / 100) + 2048,</span><span style="font-size: x-small;"> (0 * DAC_PCT / 100) + 2048, (-530 * DAC_PCT / 100) + 2048, (-1023 * DAC_PCT / 100) + 2048,</span><span style="font-size: x-small;"> (-1448 * DAC_PCT / 100) + 2048, (-1773 * DAC_PCT / 100) + 2048, (-1978 * DAC_PCT / 100) + 2048,</span><span style="font-size: x-small;"> (-2047 * DAC_PCT / 100) + 2048, (-1978 * DAC_PCT / 100) + 2048, (-1773 * DAC_PCT / 100) + 2048,</span><span style="font-size: x-small;"> (-1448 * DAC_PCT / 100) + 2048, (-1024 * DAC_PCT / 100) + 2048, (-530 * DAC_PCT / 100) + 2048,</span><span style="font-size: x-small;">};</span></blockquote>
<h3>
Clock speed</h3>
<br />
I'm testing on the Nucleo-L152RE, which has a STM32L152RET6 processor. My flght board uses an STM32L152CB, which is quite similar. I'm running it at a clock speed of 32 MHZ, and the prescalars set such that the APB1 clock speed is also 32mhz.<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><br />
</span><span style="font-size: x-small;">RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;</span><span style="font-size: x-small;"> RCC_OscInitStruct.HSIState = RCC_HSI_ON;</span><span style="font-size: x-small;"> RCC_OscInitStruct.HSICalibrationValue = 16;</span><span style="font-size: x-small;"> RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;</span><span style="font-size: x-small;"> RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;</span><span style="font-size: x-small;"> RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;<span style="white-space: pre;"> </span>// 32mhz</span><span style="font-size: x-small;"> RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV2;</span><span style="font-size: x-small;"> if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)</span></blockquote>
<h3>
<br />
Timer calculations</h3>
<br />
Based on the 32mhz clock, I calculated timers as follows. The goal for the DAC timer was to be able to simply toggle the "counter" value back and forth, in order to change the tone between 1200hz and 2200hz. You can calculate the Clock Ticks yourself by dividing:<br />
<br />
<blockquote class="tr_bq">
Clock_Ticks_Hz = 32000000 / (DAC Datapoints * Prescaler * Counter)</blockquote>
<br />
<br />
<div>
<table border="1" style="text-align: center; width: 100%;"><tbody>
<tr> <th>Function</th> <th>Timer</th> <th>DAC sinewave<br />
data points</th> <th>Prescaler</th> <th>Counter</th> <th>Clock ticks (hz)</th></tr>
<tr> <td>Baud Timer<br />
1200hz</td> <td>TIM2</td> <td><span style="text-align: start;">n/a</span></td><td>13,333</td> <td>2</td> <td>1200.03001</td> </tr>
<tr> <td>DAC timer<br />
1200 hz</td> <td><span style="text-align: start;">TIM6</span></td> <td><span style="text-align: start;">24</span></td> <td><span style="text-align: start;">101</span></td> <td>11</td> <td>1200.120012</td> </tr>
<tr> <td>DAC timer<br />
2200 hz</td> <td><span style="text-align: start;">TIM6</span></td> <td>24</td><td>101</td> <td>6</td> <td>2200.220022</td> </tr>
</tbody></table>
</div>
<br />
<blockquote>
<span style="font-size: x-small;"> htim2.Instance = TIM2;</span><br />
<span style="font-size: x-small;"> htim2.Init.Prescaler = 13333 - 1;</span><br />
<span style="font-size: x-small;"> htim2.Init.Period = 2 - 1;<span style="white-space: pre;"> </span>// 1200 hz</span><br />
<span style="font-size: x-small;"> htim2.Init.CounterMode = TIM_COUNTERMODE_UP;</span><br />
<span style="font-size: x-small;"><br />
</span> <span style="font-size: x-small;"> if (HAL_TIM_Base_Init(&htim2) != HAL_OK)</span><br />
<span style="font-size: x-small;"> {</span><br />
<span style="font-size: x-small;"> Error_Handler(__FILE__, __LINE__);</span><br />
<span style="font-size: x-small;"> }</span></blockquote>
<br />
<blockquote>
<span style="font-size: x-small;"> htim6.Instance = TIM6;</span><br />
<span style="font-size: x-small;"> htim6.Init.Prescaler = 101 - 1;</span><br />
<span style="font-size: x-small;"> htim6.Init.Period = 11 - 1;<br />
<span style="white-space: pre;"> </span>// 1200 hz</span><br />
<span style="font-size: x-small;"> htim6.Init.CounterMode = TIM_COUNTERMODE_UP;</span><br />
<span style="font-size: x-small;"><br />
</span><br />
<span style="font-size: x-small;"> if (HAL_TIM_Base_Init(&htim6) != HAL_OK)</span><br />
<span style="font-size: x-small;"> {</span><br />
<span style="font-size: x-small;"> Error_Handler(__FILE__, __LINE__);</span><br />
<span style="font-size: x-small;"> }</span><br />
<span style="font-size: x-small;"> // We turn on the ARPE register so that the counter is only updated AFTER a clean</span><br />
<span style="font-size: x-small;"> // count completes. Otherwise, we run the risk of overcounting an interval.</span><br />
<span style="font-size: x-small;"> htim6.Instance->CR1 |= TIM_CR1_ARPE; <span style="white-space: pre;"> </span>// Turn on auto-preload register</span></blockquote>
<br />
<h3>
The ARPE bit</h3>
<br />
Note that on the DAC timer (TIM6) we set the ARPE bit in the Control Register. This causes any changes to the counter to take effect AFTER the next timer pop. This assures that each timer cycle is complete, so that the DAC data points are properly spaced.<br />
<h3>
<br />
Switching between 1200hz and 2200hz</h3>
Because I'm using the DAC to make the sine wave, and just adjusting the TIM6 timer to change the frequency, I am able to greatly simplify the code that most APRS implementations use. Rather than using a 512 element phase array, I'm simply using a 24 element sine array for the DAC. I no longer need to track the phase position when switching. Rather, I just adjust the timer counter.<br />
<br />
The code is simple, but it confused me at first, because AX.25 is using NRZI encoding. So, here's a bit about that, before showing the code.<br />
<br />
<span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px;">From Wikipedia:</span><br />
<blockquote class="tr_bq">
<span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px;">At the datalink level, AX.25 specifies </span><a href="https://en.wikipedia.org/wiki/High-Level_Data_Link_Control" style="background: none rgb(255, 255, 255); color: #0b0080; font-family: sans-serif; font-size: 14px; text-decoration-line: none;" title="High-Level Data Link Control">HDLC</a><span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px;"> (ISO 3309)</span><sup class="reference" id="cite_ref-3" style="background-color: white; color: #222222; font-family: sans-serif; font-size: 11.2px; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/AX.25#cite_note-3" style="background: none; color: #0b0080; text-decoration-line: none;">[3]</a></sup><span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px;"> frames transmitted with </span><a class="mw-redirect" href="https://en.wikipedia.org/wiki/NRZI" style="background: none rgb(255, 255, 255); color: #0b0080; font-family: sans-serif; font-size: 14px; text-decoration-line: none;" title="NRZI">NRZI</a><span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px;"> encoding. </span></blockquote>
In NRZI encoding, you're not sending the actual bits, but rather toggling whatever bit you are sending, based on the next data value. I borrowed a few lines from the <a href="https://www.tracksoar.com/source/" target="_blank">Tracksoar </a>code, and modified them to my purposes:<br />
<br />
<span style="font-size: x-small;"><span style="white-space: pre;"> </span>if ((current_byte & 1) == 0) {</span><br />
<span style="font-size: x-small;"><span style="white-space: pre;"> </span>// Toggle tone (1200 <> 2200)</span><br />
<span style="font-size: x-small;"><span style="white-space: pre;"> </span>current_timer_counter ^= (COUNTER_1200 ^ COUNTER_2200);<span style="white-space: pre;"> </span>// Switch to the opposite counter value</span><br />
<span style="font-size: x-small;"><span style="white-space: pre;"> </span>__HAL_TIM_SET_AUTORELOAD(&htim6,current_timer_counter);<span style="white-space: pre;"> </span>// Set frequency</span><br />
<span style="font-size: x-small;"><span style="white-space: pre;"> </span>}</span><br />
<br />
That's it. No math about phase arrays and accmulators! Yay!<br />
<br />
<h3>
Initial test failures</h3>
<br />
I only had 3 tiny bugs in my code which prevented APRS from working. <br />
<br />
<br />
<ol>
<li>I actually FORGOT the HAL_TIM_SET_AUTORELOAD command after setting the current_timer_counter. lol. </li>
<li>The more subtle one was that I had misread the manual, and thought that the ARPE bit was set by default. When I tested without it, there were hesitations in the middle of the transmission. It was obvious what was going on when I heard it, and simple to fix.</li>
<li>I contrived the test by hard-coding GPS values into the strings that the aprssend() call uses. I used the wrong number of digits in the Longitude, and so my Kenwood D72 caught my callsign, it wouldn't decode it until I fixed that coordinate. Along the way, I noticed that my APRS comment was also too long. I wanted it to read "Mr. Watson, come here, I want you." Unfortunately, that's too many characters. So, I changed it to "Mr. Watson, Come here!..."</li>
</ol>
<h3>
Successful test</h3>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/nwUgrsfEdxs/0.jpg" src="https://www.youtube.com/embed/nwUgrsfEdxs?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<div>
<br /></div>
<div>
<br /></div>
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com3tag:blogger.com,1999:blog-1904678747905486184.post-1853172025109004642017-08-12T21:43:00.001-07:002017-08-12T21:43:19.812-07:00AFSK modulation experiments - part 4<h2>
AFSK modulation experiments - part 4</h2>
<br />
I left off the last time with some concerns that the deviation might be too wide on the VCXO, and also that when using the VCXO, the Si5351 was somewhat off frequency (about 5 khz). I set out to work on both of those issues tonight.<br />
<br />
I began by setting up my scope and service monitor so that I could measure the P2P value of the modulating sine wave, and the deviation of the resulting signal.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqTVVJpWUd602bRlcSmEf_jFMSdYMwvHoBWc8ih_XiPE9epINwCvSoQ4ONRnl4cIyz2kX6vlazRGMqR8eGkA9Ho0Dq3Zo9v74n866DwnePOGX4vrybEB4JSxbzHgGK2JGCoKAVLomyI2I/s1600/20170812_203745.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqTVVJpWUd602bRlcSmEf_jFMSdYMwvHoBWc8ih_XiPE9epINwCvSoQ4ONRnl4cIyz2kX6vlazRGMqR8eGkA9Ho0Dq3Zo9v74n866DwnePOGX4vrybEB4JSxbzHgGK2JGCoKAVLomyI2I/s400/20170812_203745.jpg" width="400" /> </a></div>
<br />
Here, we see a 1200hz sine wave the VCXO signal should be ve being generated by the DAC. The P2P value is 0.980 volts. This is from setting the sine wave at 30% amplitude. We also see that the wave is centered at (2.18 + 1.20) / 2 = 1.69 volts. That's just fine, since it should be centered around 1.65 volts.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqniapKWhlMrqC1Xr3gUbckK7fEkIgBODvezG2oNCZZHgyCDsXVA-356GtjR4p-orCh5F5ALZFc55331k93YjmF_JCq7hnx9u9XaqcEn46kCI7J3247w9q-Anvecb5DObclHhoTP6KheY/s1600/20170812_203739.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqniapKWhlMrqC1Xr3gUbckK7fEkIgBODvezG2oNCZZHgyCDsXVA-356GtjR4p-orCh5F5ALZFc55331k93YjmF_JCq7hnx9u9XaqcEn46kCI7J3247w9q-Anvecb5DObclHhoTP6KheY/s400/20170812_203739.jpg" width="400" /></a></div>
<br />
The resulting deviation for the wave above (on the 0-6 scale) is coming in at about 2.7 khz. That's a touch low.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
So, I ran the tests over and over gathering data. I also varied the PPM value to see the effect.<br />
<br />
<br />
<div>
<table border="1" style="text-align: center; width: 100%;"><tbody>
<tr> <th>PPM value</th> <th>Sine wave %</th> <th>P2P voltage (volts)</th> <th>Deviation (hz)</th> </tr>
<tr> <td>30</td> <td><span style="text-align: start;">50</span></td> <td><span style="text-align: start;">1.52</span></td> <td><span style="text-align: start;">3,500</span></td> </tr>
<tr> <td>30</td> <td><span style="text-align: start;">30</span></td> <td><span style="text-align: start;">0.98</span></td><td>2,700</td></tr>
<tr> <td>30</td> <td><span style="text-align: start;">40</span></td> <td><span style="text-align: start;">1.24</span></td><td>3,300</td></tr>
<tr> <td>40</td> <td><span style="text-align: start;">40</span></td> <td><span style="text-align: start;">1.24</span></td><td>3,700</td></tr>
<tr> <td>40</td> <td><span style="text-align: start;">30</span></td> <td><span style="text-align: start;">0.98</span></td><td>3,200</td></tr>
</tbody></table>
</div>
<br />
<h3>
Deviation Results</h3>
The PPM value definitely has an impact on the deviation. Assuming that we would want the <i>capability</i> of 5 khz deviation for an FM signal, but then we would only want to modulate the signal to 3 khz, the ppm should be (5000 hz / 144.390) = 35 PPM. In a <a href="http://hojoham.blogspot.com/2017/07/choosing-pull-value-for-si3151-vcxo-for.html" target="_blank">previous post</a>, I came up with the number 24, but that was when I was considering modulating to 3.2 khz, not 5 khz.<br />
<br />
So, it appears that for flight use, I should be setting my PPM to 35 ppm, and setting my sinewave appropriately to get about a 3khz deviation. That should be at about 30% or so. I noticed a bit of variability when I was testing this evening, due to the fact that I was using breakout boards and jumpers all over. I suspect this is a process I'll need to repeat when I have the production boards spun up.<br />
<br />
<h3>
<b>Correcting for the incorrect frequency</b></h3>
<br />
I dabbled with the "Correction" call to fix the frequency of the VCXO this evening.<br />
<br />
MySi5351.set_correction(-12940);<br />
<br />
In the end, the value above was sufficient to center up the frequency where I was testing, at 144.330 mhz. According to the documentation, I can expect to do this with every board I build.<br />
<br />
<h3>
Conclusions</h3>
<br />
<br />
<ol>
<li>I'll build my flight code with a PPM of 35.</li>
<li>I'll build my flight code with a Calibration option. When set, the tracker will generate a fixed tone (or maybe alternated between 1200 and 2200) so that I can confirm that the deviation is correct, and also so that I can diddle the "correction" value to assure the tracker is on frequency.</li>
</ol>
<br />
<br />
<br />
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-42163026758861351102017-08-11T18:21:00.002-07:002017-08-11T21:23:04.698-07:00AFSK modulation experiments - part 3<h2>
AFSK modulation experiments - part 3</h2>
<br />
So, <a href="http://hojoham.blogspot.com/2017/08/afsk-modulation-experiments-part-2.html" target="_blank">Part 2</a> of this little journey featured our hero barking up the wrong tree a bit. I made two mistakes.<br />
<ol>
<li>I assumed that I had to modulate the VC pin on the Si5351b with values from -3v3 .. 3v3. That is incorrect. The proper values for the VC pin on the Si5351b are from 0 .. 3v3. The "typical" value is listed as VDD / 2 (IE: 1.65 volts). I presume (see below) that this means that any modulation should be centered at 1.65 volts.</li>
<li>I assumed that the output of my signal generator was making an AC signal. Of course, it wasn't, as I had things wired up. It was a DC signal.</li>
</ol>
<div>
The mistakes above led to some seriously confusing results, and some pretty bad sounding signals.</div>
<div>
<br /></div>
<h2>
Taking a step back</h2>
<div>
<br /></div>
<div>
I decided to do some Science, and assure that I wasn't making any more bad assumptions. I set up a test environment on my bench so that I could try moving the VC pin between 0 .. 3v3, and see the resulting impact on the signal being generated.</div>
<div>
<br /></div>
<div>
I wired up my Si5351b breakout board to my STM Nucleo-L152RE. I ran the output into my spectrum analyzer so that I could get a good look at what was happening. I wired the VC pin to a variable DC power supply so that I could vary it carefully, and see where the signal wound up.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2u7fSYucwx34txrtPmupzGFzS2ONW-Gi3SLWGM68IbUAnze9EhixdJJ-kSCHaIVtOUQc-OIoFfeJvW4jt6p2pokMFNTIBrqP_mS4mjXMjs-mnQDs_5C7r27KYATwU7HK93OLT3-NwJUQ/s1600/20170811_172019.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2u7fSYucwx34txrtPmupzGFzS2ONW-Gi3SLWGM68IbUAnze9EhixdJJ-kSCHaIVtOUQc-OIoFfeJvW4jt6p2pokMFNTIBrqP_mS4mjXMjs-mnQDs_5C7r27KYATwU7HK93OLT3-NwJUQ/s400/20170811_172019.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Test 1: Baseline without VCXO</h3>
<div>
<br /></div>
<div>
For the first test, I wanted to just set the frequency of the Si5351b to 144.330 <i>without</i> using the VCXO. This test was intended to see where the Si5351b was centered, without using the VC, so I had an idea of how well calibrated it was.</div>
<div>
<br />
Here are the relevant lines which initialized the Si5351. I am using the <a href="https://github.com/etherkit/Si5351Arduino" target="_blank">Etherkit Si5351 library</a>.</div>
<br />
<div>
MySi5351.set_freq(14433000000ULL, SI5351_CLK0);</div>
<div>
MySi5351.output_enable(SI5351_CLK0, ENABLE);</div>
<div>
<br /></div>
<div>
This is the result.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGWxRGzoJbwf0jP4P0PACmWuT7K6foNjDC2BTwrS8mhUh4x5as3_E-MmiwShdI07sEjyQsHWdHyA7Bf2_UGZ6J2DrOyqfoi9WrKRfqSTf9fggC1qebxoI3WzkNTweihAKxkkdORAI5BIA/s1600/DSA815+NO+SIGNAL.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="800" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGWxRGzoJbwf0jP4P0PACmWuT7K6foNjDC2BTwrS8mhUh4x5as3_E-MmiwShdI07sEjyQsHWdHyA7Bf2_UGZ6J2DrOyqfoi9WrKRfqSTf9fggC1qebxoI3WzkNTweihAKxkkdORAI5BIA/s400/DSA815+NO+SIGNAL.png" width="400" /></a></div>
<div>
<br /></div>
<div>
My spectrum analyzer is reasonably well calibrated. The center frequency of the Si5351b came in at 144.330004 mhz. Dang. Not bad at all! My little breakout board actually uses a TCXO for the oscillator, and I think that helps with the accuracy.</div>
<div>
<br /></div>
<h3>
Test 2: VC at 0 volts</h3>
<div>
<div>
MySi5351.set_vcxo(86598000000ULL, 40);</div>
<div>
// Set CLK0 to be locked to VCXO</div>
<div>
MySi5351.set_ms_source(SI5351_CLK0, SI5351_PLLB);</div>
<div>
// Tune to 144.330 MHz center frequency</div>
<div>
MySi5351.set_freq_manual(14433000000ULL, 86598000000ULL, SI5351_CLK0);</div>
<div>
MySi5351.update_status();</div>
<div>
MySi5351.output_enable(SI5351_CLK0, ENABLE);</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja-TIRGhtstnaWJGrP59cyvi9gowCxxfHRT9W9zocE6FMPFsAhEfp07ZOxGAwY5MHhWx4OiEFWdOasVQylgbzIyhV8DMex2POp6M0G5K03osHmdKR5JDnorVcrZI_6TttX4QZsTmjHANU/s1600/DSA815+VCO+0v.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="800" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja-TIRGhtstnaWJGrP59cyvi9gowCxxfHRT9W9zocE6FMPFsAhEfp07ZOxGAwY5MHhWx4OiEFWdOasVQylgbzIyhV8DMex2POp6M0G5K03osHmdKR5JDnorVcrZI_6TttX4QZsTmjHANU/s400/DSA815+VCO+0v.png" width="400" /></a></div>
<div>
<br /></div>
<div>
OK, that did just what one would expect. It pulled the signal down to 144.323462 mhz. That's 6.538 khz down. Note, I set the PPM value to "40" in the initial tests, which is the value that was in the samples in the Etherkit Si5351 library I'm using. Diddling with the PPM value will follow.</div>
<div>
<br /></div>
<div>
<h3>
Test 3: VC at 3.3 volts</h3>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8zmA7MbkE82W7dtnrgt3iXCA1_F_hl8uoHl7MDcajIdSh9GmGEyX5lm2XUbB0q803h9pDohCKK2lYiAf32ryeM4tpb3jAEEYQPobcnr9EyJv1TWZzdcwooOxBTodjybxW-l_66HN7Uq8/s1600/DSA815+vco+3v278.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="800" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8zmA7MbkE82W7dtnrgt3iXCA1_F_hl8uoHl7MDcajIdSh9GmGEyX5lm2XUbB0q803h9pDohCKK2lYiAf32ryeM4tpb3jAEEYQPobcnr9EyJv1TWZzdcwooOxBTodjybxW-l_66HN7Uq8/s400/DSA815+vco+3v278.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Great, OK, that set the top end of the swing. It's at 144.332962. I was a little surprised that it seemed a little asymmetric. It's only 2.962 khz above the center (vs the 6,538 below we saw).</div>
<div>
<br /></div>
<h3>
Test 4: VC at 1.65 volts</h3>
<div>
<br /></div>
<div>
OK, this one, I would expect should show the signal centered up again.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbHEemduQWbSgJLRz3CpcF-J4nk2itw5Q06P9nqxWFuGRhXcmAJXi8pJQ0t-pn8lsQX5iuRUCP_5d7oYnm3-zxyOcYAocro-642JZL2YRGH8eZ5k_Y4i7EgTXiXB7SG0elTPneeasHE8A/s1600/DSA815+vco+1v65.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="800" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbHEemduQWbSgJLRz3CpcF-J4nk2itw5Q06P9nqxWFuGRhXcmAJXi8pJQ0t-pn8lsQX5iuRUCP_5d7oYnm3-zxyOcYAocro-642JZL2YRGH8eZ5k_Y4i7EgTXiXB7SG0elTPneeasHE8A/s400/DSA815+vco+1v65.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Ruh Roh. We should be at 144.330. We're at 144.327212. That's about 5khz off where I expected. Not cool. If I split the difference between the low and high values, I should have been at 144.328212, which would still have been 1.788 khz off.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3 style="clear: both; text-align: left;">
Test 5: What voltage do I need for Center frequency?</h3>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2Ja1bIpM59m5jv_z5Ebr4YPlzMj8LeSCZiDl8-gS9tAQHalAfJvnD7_vKuOE3ZteA7C8nB1x5LkkKL5SYDCD_h5Caxkb_LpPbocFzliE3A4CX2FL6U4f3dS-stmwBepYozdYUAy0wG2c/s1600/DSA815+vco+2v430.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="800" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2Ja1bIpM59m5jv_z5Ebr4YPlzMj8LeSCZiDl8-gS9tAQHalAfJvnD7_vKuOE3ZteA7C8nB1x5LkkKL5SYDCD_h5Caxkb_LpPbocFzliE3A4CX2FL6U4f3dS-stmwBepYozdYUAy0wG2c/s400/DSA815+vco+2v430.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
OK, I was able to get it centered up. Rather than being at 1.65 volts, I had to apply 2.43 volts. Curious.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3 style="clear: both; text-align: left;">
Test 6: How does modulation look at 1.65 volts with the DAC?</h3>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, my DAC was all set up to make about 1 volt P2P, centered at 1.65 volts. I put that 1200 hz modulation into the VC pin to see what it would look like,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-JvrR-94l-Bedi0rtf7HYxdheZJlbkq5h7r3twLIezRM0g_5HEmjvBCE-ekx2Q9pK1Ff2dSMqqxFogry9D0HWdO-YDgri7XFCZk14wuEaKXZFWtjuTIQ41YExShCP887TSWP5TPqnkUY/s1600/DSA815+1200.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="800" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-JvrR-94l-Bedi0rtf7HYxdheZJlbkq5h7r3twLIezRM0g_5HEmjvBCE-ekx2Q9pK1Ff2dSMqqxFogry9D0HWdO-YDgri7XFCZk14wuEaKXZFWtjuTIQ41YExShCP887TSWP5TPqnkUY/s400/DSA815+1200.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div>
Sure enough, it looks symmetric around 133.327 mhz, the same as when the VC pin is just held at 1.65 volts.</div>
<div>
<br />
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
</div>
<br />
<h3 style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
Other thoughts on the frequency error</h3>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
In a later test, I had the VCXO set at 146.000 mhz. When set up that way, the frequency was dead nuts on at 1.65 volts. Modulating the frequency looked just fine, too.</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
I suspect that the frequency error has something to do with an error introduced by the multisynth multipliers and dividers. I'm not too concerned, as I may be able to address it either by using the calibration subroutines, or different multipliers.</div>
<h3 style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
Deviation and the PPM value</h3>
</div>
<div>
OK, so I had set the PPM value in all of these tests to 40. At 144.330 mhz, that should make for a deviation of 3.608 khz. My observed deviation was 144.332962 - 144.323462 = 9.500 khz, </div>
<div>
<br /></div>
<div>
Hmm... Is that how you measure deviation? If so, mine's WAY too big.</div>
<div>
<br /></div>
<div>
<h3>
Test 7: Different PPM values</h3>
</div>
<div>
<br /></div>
<br />
<div>
<table border="1" style="text-align: center; width: 100%;"><tbody>
<tr> <th>PPM value</th> <th>0 volt reading</th> <th>3.3 volt reading</th> <th>Delta </th> </tr>
<tr> <td>30</td> <td><span style="text-align: start;">144.325164 mhz</span></td> <td><span style="text-align: start;">144.332289 mhz</span></td> <td><span style="text-align: start;">7,127 hz</span></td> </tr>
<tr> <td>40</td> <td><span style="text-align: start;">144.323462 mhz</span></td> <td><span style="text-align: start;">144.332962 mhz</span></td> <td><span style="text-align: start;">9,500 hz</span></td></tr>
</tbody></table>
</div>
<div>
<br /></div>
<div>
I also tried a test with 20 PPM (which isn't supported according to the documentation), and it seemed to show the same readings as 30 PPM.<br />
<br />
If I understand "deviation" in this context, I think these numbers are too big. I need to understand this better.<br />
<br /></div>
<h3>
Next steps</h3>
<div>
<br /></div>
<div>
Strictly speaking, the frequency being off isn't too much of a problem. The Si5351 has a calibration routine which I can use to center this up. It's just odd that the center frequency is different when using the VCXO. I'm a little more concerned about the deviation right now. The lowest deviation setting still seems to be too wide, unless I'm misunderstanding what to expect with regard to this kind of experiment.</div>
<div>
<br /></div>
<div>
Things to do:</div>
<div>
<ol>
<li>Call the calibration routine to see if I can get it centered up.</li>
<li>Experiment with the amplitude of the VC signal to see the effect on the signal, and received modulation.</li>
<li>See if different multipliers work to improve the frequency accuracy of the VCXO. I used 6 for these tests. I could try 4 or 8</li>
</ol>
<div>
<br /></div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-5792435411619818202017-08-11T15:41:00.001-07:002017-08-11T15:41:39.664-07:00Generating a sinewave table for my DAC<h2 class="tr_bq">
Generating a sinewave table for my DAC</h2>
<br />
Unlike other AFSK implementations, I don't actually need a sinewave table with a lot (like 512) of values in it. In fact, I'll be using just 24 values in my sinewave table for my DAC. <br />
<br />
I decided to write a program to generate my table. While I was at it, I decided that I would have it build in a scaling factor as a "#define". By changing that one #define, I can change the amplitude of the sinewave with a recompile, rather than having to re-generate a whole new table.<br />
<br />
<h3>
Sinewave.pl</h3>
<blockquote>
#!/usr/bin/perl<br /># Usage: sinewave.pl samples<br /># Generates a sinewave table containing the specified number of samples.<br /># For example, "sinewave.pl 36" yields:<br /># #DEFINE DAC_PCT 100<br /># #DEFINE SINE_RES 36<br /># const uint16_t sinewave[SIN_RES] = { .... }<br /># The DAC_PCTxx define is a percentage multipler against all of the values in the table. Useful if your DAC output is too high.<br /># By changing this one DEFINE in your code, you can scale the sinewave table at compile time. Note, that the DAC values will remain<br /># centered on the sine(0) value, and will scale "inward" toward that number. For example, on a 12 bit DAC, sin(0) is going to be at 2048.<br /># Even if you scale up and down, the sine wave will be centered around 2048.<br />#<br /># The output of this program is actually a C program which an be compiled to confirm the table is built properly. When satisfied,<br /># you can just copy/paste the sinewave table and the few necessary defines into your own program.<br />use strict;<br />my $DACBITS = 12; # Number of bits the DAC (or pwm) is using<br />my $COLUMNS_PER_LINE = 3; # Number of values per row<br />if ($#ARGV != 0) {<br /> print STDERR "Usage: $0 samples\n";<br /> exit 4;<br />}<br />my $center_value = 2 ** $DACBITS / 2; # The peak 2 peak of the sine wave is twice $center_value, so we divide by two.<br />my $PI = 3.1415926;<br />my $samples = $ARGV[0];<br />my $degrees = 0;<br />my $column;<br />my $value;<br />my $row;<br />print("\#include \"stdint.h\"\n");<br />print("\#include <stdio.h>\n");<br />print("main()\n");<br />print("{\n");<br /><br />print("\#define DAC_PCT 100 // Percentage of DAC output\n");<br />print("\#define SINE_RES $samples\n");<br />print("const uint16_t sinewave\[SINE_RES\] = {\n");<br />for ($row = 0; $row < ($samples / $COLUMNS_PER_LINE); $row++) {<br /> print("\t");<br /> for ($column = 0; (($degrees < 360) && ($column < $COLUMNS_PER_LINE)); $degrees += 360/$samples) {<br /> $value = int($center_value * sin($degrees/180.0 * $PI)); # Perl sin() is in Radians. Convert.<br /> print("(${value} * DAC_PCT / 100) + $center_value, ");<br /> $column++;<br /> }<br /> print("\n");<br />}<br />print("};\n");<br />print("int i;\n\n");<br />print("for (i = 0; i < SINE_RES; i++) {\n");<br />print("\t");<br />print("printf(\"\%d\\n\", sinewave[i]);");<br />print("\n"); print("\t}\n"); print("}\n");</blockquote>
<h3>
What it does</h3>
<div>
Rather than just creating the sinewave table, it actually generates a short C program which can be compiled in Unix to confirm that the table is properly formed, and that the values look correct.</div>
<h3>
<br />Sample run for 24 data points</h3>
<div>
<blockquote class="tr_bq">
mqh1@debian:~/wisp2$ ./sinewave.pl 24<br />#include "stdint.h"<br />#include <stdio.h><br />main()<br />{<br />#define DAC_PCT 100 // Percentage of DAC output<br />#define SINE_RES 24<br />const uint16_t sinewave[SINE_RES] = {<br /> (0 * DAC_PCT / 100) + 2048, (530 * DAC_PCT / 100) + 2048, (1023 * DAC_PCT / 100) + 2048,<br /> (1448 * DAC_PCT / 100) + 2048, (1773 * DAC_PCT / 100) + 2048, (1978 * DAC_PCT / 100) + 2048,<br /> (2047 * DAC_PCT / 100) + 2048, (1978 * DAC_PCT / 100) + 2048, (1773 * DAC_PCT / 100) + 2048,<br /> (1448 * DAC_PCT / 100) + 2048, (1024 * DAC_PCT / 100) + 2048, (530 * DAC_PCT / 100) + 2048,<br /> (0 * DAC_PCT / 100) + 2048, (-530 * DAC_PCT / 100) + 2048, (-1023 * DAC_PCT / 100) + 2048,<br /> (-1448 * DAC_PCT / 100) + 2048, (-1773 * DAC_PCT / 100) + 2048, (-1978 * DAC_PCT / 100) + 2048,<br /> (-2047 * DAC_PCT / 100) + 2048, (-1978 * DAC_PCT / 100) + 2048, (-1773 * DAC_PCT / 100) + 2048,<br /> (-1448 * DAC_PCT / 100) + 2048, (-1024 * DAC_PCT / 100) + 2048, (-530 * DAC_PCT / 100) + 2048,<br />};<br />int i;<br />for (i = 0; i < SINE_RES; i++) {<br /> printf("%d\n", sinewave[i]);<br /> }<br />}<br />mqh1@debian:~/wisp2$</blockquote>
</div>
<h3>
Compile and run the output</h3>
<div>
<br /></div>
<div>
<blockquote class="tr_bq">
mqh1@debian:~/wisp2$ ./sinewave.pl 24 > t.c<br />mqh1@debian:~/wisp2$ cc t.c<br />mqh1@debian:~/wisp2$ ./a.out<br />2048<br />2578<br />3071<br />3496<br />3821<br />4026<br />4095<br />4026<br />3821<br />3496<br />3072<br />2578<br />2048<br />1518<br />1025<br />600<br />275<br />70<br />1<br />70<br />275<br />600<br />1024<br />1518<br />mqh1@debian:~/wisp2$</blockquote>
</div>
<div>
<br /></div>
<div>
In the output above, you can see that it's got a sinewave centered at 2048, with values ranging from (almost) 0 to 4095.</div>
<div>
<br /></div>
<h3>
Re-scaling the sine wave</h3>
<div>
To change the scale out the sinewave, I simply modify the #define</div>
<div>
<br /></div>
<blockquote class="tr_bq">
#define DAC_PCT 50 // Percentage of DAC output</blockquote>
<br />
This will set the DAC amplitude at 50%<br /><div>
<br /></div>
<div>
<blockquote class="tr_bq">
mqh1@debian:~/wisp2$ vi t.c<br />mqh1@debian:~/wisp2$ cc t.c<br />mqh1@debian:~/wisp2$ ./a.out<br />2048<br />2313<br />2559<br />2772<br />2934<br />3037<br />3071<br />3037<br />2934<br />2772<br />2560<br />2313<br />2048<br />1783<br />1537<br />1324<br />1162<br />1059<br />1025<br />1059<br />1162<br />1324<br />1536<br />1783</blockquote>
</div>
<div>
Note that the center is still around 2048, but the amplitude only goes up and down by about 1024.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-21622865002873931102017-08-02T21:10:00.004-07:002017-08-11T15:03:59.421-07:00Plotting a maidenhead grid square in aprsisce<h2>
Plotting a maidenhead grid square in aprsisce</h2>
<br />
The WSPR protocol uses <a href="http://www.arrl.org/grid-squares" target="_blank">Maidenhead grid squares</a> to plot location. The granularity of a 6-character grid square is approximate 3x4 miles, which is fine for WSPR balloons in the air. Unfortunately, if a payload crashes on the ground, it's not as useful. Twice, now, I've tried to locate a WSPR payload on the ground by driving around and trying to hear the signal. I find it useful to have Aprsisce running in my car, and plotting the grid square on the map, so that I know when I'm reaching the borders of the search area. Unfortunately, I can never remember how I did it. This blog entry is a "note to self" for the next time this comes up.<br />
<br />
<h3>
Convert grid square to KML</h3>
Visit <a href="http://www.w8an.net/grid/maidenhead.pl" target="_blank">this site,</a> and enter the 6 character grid square. It outputs a .kml file.<br />
<br />
<h3>
Convert the KML file to a GPX file</h3>
Visit <a href="https://kml2gpx.com/" target="_blank">this site</a> and conver the kml to gpx.<br />
<br />
<h3>
Load the GPX file as an overlay in aprsisce</h3>
Inside aprsisce: Configure / Overlay / Add GPX file...<br />
<br />
Set the opacity and color so that it shows nicely on the map.<br />
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-46293591909676927542017-08-02T20:07:00.003-07:002017-08-11T15:09:06.689-07:00AFSK modulation experiments - Part 2<h2>
AFSK modulation experiments - Part 2</h2>
<h3>
Prelude</h3>
<div>
The experiments below were an initial attempt at modulation. After posting this blog, I discovered I made an error. the VC pin should take values between 0 .. 3v3. I was attempting to modulate with an AC voltage, which was broken in several different ways. Live and learn.</div>
<div>
<br /></div>
<div>
The erroneous post follows, for posterity. However, corrections will be evident in blog posts made after this one.</div>
<div>
<br /></div>
<div>
<b>Read below at your own peril. I made lots of mistakes!!!</b></div>
<h3>
Test code</h3>
So, I'm using the <a href="https://github.com/etherkit/Si5351Arduino" target="_blank">Etherkit Library</a> to generate my signals. I used a little test code this evening to configure the VCXO and generate a signal at 144.330. I then attached my signal generator to the VC pin and adjusted the frequency and amplitude to see if I could modulate my signal. It worked!<br />
<br />
The code is mostly just the <a href="https://github.com/etherkit/Si5351Arduino/tree/master/examples/si5351_vcxo" target="_blank">example code </a>available on his site.<br />
<blockquote class="tr_bq">
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">// ASTXR-12-26.000MHz-512545 TCXO is 26 MHZ. We use 0PF, since it's a TCXO and not a crystal.</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.init(SI5351_CRYSTAL_LOAD_0PF, 26000000UL, 0UL);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">// power down the unused clocks</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.set_clock_pwr(SI5351_CLK1, DISABLE);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.set_clock_pwr(SI5351_CLK2, DISABLE);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">// Turn off transmit on unused clocks</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">XMITOFF(SI5351_CLK1);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">XMITOFF(SI5351_CLK2);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.set_clock_pwr(SI5351_CLK0, ENABLE);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">XMITOFF(SI5351_CLK0);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_8MA);<span style="white-space: pre;"> </span>// Max power</span></blockquote>
</blockquote>
<blockquote class="tr_bq">
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.set_vcxo(86598000000ULL, 40);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">// Set CLK0 to be locked to VCXO</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.set_ms_source(SI5351_CLK0, SI5351_PLLB);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">// Tune to 144.390 MHz center frequency</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.set_freq_manual(14433000000ULL, 86598000000ULL, SI5351_CLK0);</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.update_status();</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">MySi5351.output_enable(SI5351_CLK0, ENABLE);</span></blockquote>
</blockquote>
<br />
Note, I have not yet fiddled with the PPM parameter as discussed in the <a href="http://hojoham.blogspot.com/2017/07/choosing-pull-value-for-si3151-vcxo-for.html" target="_blank">previous blog</a>. I left it at "40" from the example.<br />
<br />
<b>Amplitude fiddling</b><br />
<br />
I noticed that the amplitude of the signal generator output changed significantly when plugged into the VC pin. I dialed the amplitude up and down until I reached a reasonable level, without distortion. I noted that under load, the P2P amplitude was about 1.16v. When attached to the VC pin, the amplitude went down to about 0.6v p2p. <br />
<h3>
<br />DAC fiddling</h3>
Knowing the amplitude, I was curious what output level the DAC would generate with the sine wave tables I was using for maximum amplitude. Not surprisingly, it was about 3v p2p. Not a shocker, since the Si5351 is operating at 3v3. I needed to lower the amplitude of the DAC output to match what I was getting from the signal generator (1.16v).<br />
<br />
The RC filter, tested in the <a href="http://hojoham.blogspot.com/2017/07/afsk-modulation-experiments-part-1.html" target="_blank">Part 1 blog for this project</a>, cleaned up the signal significantly, and also reduces the amplitude. That's a start.<br />
<br />
<h3>
DC Blocking Cap</h3>
<br />
The signal generator makes an AC signal, swinging positive and negative. The DAC makes a sine wave that is strictly positive. I introduced a DC blocking cap into the circuit to convert it to AC, and clean it up a bit.<br />
<br />
<h3>
Test circuit</h3>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCCYwoAgAvfhumNCaYOiO8epbkW7cGR0hj3sJ-eij1oGwg9nj14LojFL94wOeC_YprC_s4kGh4COHWx7eC1q3JZrpQW_PT_WQK58DhZcnN8AnVUqkuE7MMWlkYaC-f-vhTmqwlr8mhAgM/s1600/DAC+Filter.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="563" data-original-width="835" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCCYwoAgAvfhumNCaYOiO8epbkW7cGR0hj3sJ-eij1oGwg9nj14LojFL94wOeC_YprC_s4kGh4COHWx7eC1q3JZrpQW_PT_WQK58DhZcnN8AnVUqkuE7MMWlkYaC-f-vhTmqwlr8mhAgM/s400/DAC+Filter.jpg" width="400" /></a></div>
<br />
This circuit was sufficient to convert the DAC output to filtered AC. The P2P voltage was about 1.5 volts, but it was sufficient for testing. Sure 'nuff, it worked. Putting the "AC Signal Out" from this filter into the VC pin on the Si5351b modulated the signal, and the tone created on the Nucleo DAC was readable on an FM receiver.<br />
<br />
Progress!<br />
<br />
<h3>
Afterword</h3>
<br />
So, upon further examination, I discovered that I was in error. The VC pin on the Si5351 requires 0 .. 3v3, all positive. The experiments I was doing were generating an AC signal, but the modulation was faulty. I'll have more on this in a future blog post.<br />
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-56931529326233936002017-07-29T19:01:00.001-07:002017-08-12T21:33:54.187-07:00Choosing "pull" value for the Si5351 VCXO for APRS<h2>
Choosing "pull" value for the Si5351 VCXO for APRS</h2>
<br />
When configuring the VCXO frequency on the Si5351b, there is a register setting for the "Pull range". It is described as follows in Silicon Labs publication AN619 "Manually Generating an Si5351 Register Map":<br />
<br />
<blockquote class="tr_bq">
Set VCXO_Param register value according to the equation below. Note that 1.03 is a margining factor to ensure the full desired pull range is achieved. For a desired pull-range of +/– 30 ppm, the value APR in the equation below is 30, for +/– 60 ppm APR is 60, and so on.</blockquote>
This sounds a lot like the FM Deviation to me, though I wish they used those words. <br />
<br />
For APRS, the deviation for the 2200hz tone should be about 3.5khz. The 1200hz tone will be proportionally lower. So, I need to do some math:<br />
<br />
Desired pull: 3,500 hz.<br />
APRS frequency: 144.390 Mhz.<br />
<br />
PPM = 3,500 / 144.390 = 24.2 . Rounded to an integer, it's "24".<br />
<br />
The <a href="https://github.com/etherkit/Si5351Arduino" target="_blank">Etherkit Si5351Arduino library</a>, which I've ported to the STM32CubeMX environment, claims that the PPM value must be in the range of 30 .. 240. I guess I'll set it to "<b>30</b>" and see how it goes.<br />
<br />
Since the library does all the number crunching to calculate the register values, I don't need to calculate them myself..<br />
<br />
<h3>
<span style="color: red;">Correction</span></h3>
<span style="color: red;">Subsequent to posting this blog, I realized that I really want to set the PPM for 5 khz deviation (standard FM), but only <i>modulate </i>my signal to 3-3.5 khz. Redoing the math: PPM = 5000 / 144.390 = 34.6, rounded to 35.</span><br />
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-72186124492024093562017-07-10T19:36:00.002-07:002017-07-10T19:36:45.926-07:00AFSK modulation experiments - Part 1<h2>
AFSK modulation experiments - Part 1</h2>
<br />
So, on the next version of my Wisp tracker, I would like to attempt AFSK (APRS) modulation in addition to the WSPR modulation. The Si5351b clock generator chip provides a VC input pin, which allows for FM modulation. By using the DAC on the Microcontroller to make the appropriate sine waves, I should be able to achieve the proper 1200 and 2200hz tones necessary to modulate AFSK.<br />
<br />
Step 0 of this project is to make a sine wave on an ARM Cortex processor similar to the one I will use in flight. The STM Nucleo L152RE fits the bill nicely. I use the L151 processor on my Wisp tracker. I did a fair bit of prototyping for the Wisp1 with this Nucleo.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJjQPKP-fk_n0VI2kkPK7cPEro5Q0k1_m69kKdTJjU_K4no7j-xOz1Vx7OocABC4_KDlSjP8IdFbNujQ8bBJhNLkJYPsVryn4wM4l2ni8D8i3plHqLmtAoDxaM9pKtgojh-y4IywH1o9w/s1600/NUCLEO-L152RE.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="525" data-original-width="700" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJjQPKP-fk_n0VI2kkPK7cPEro5Q0k1_m69kKdTJjU_K4no7j-xOz1Vx7OocABC4_KDlSjP8IdFbNujQ8bBJhNLkJYPsVryn4wM4l2ni8D8i3plHqLmtAoDxaM9pKtgojh-y4IywH1o9w/s400/NUCLEO-L152RE.jpg" width="400" /></a></div>
<br />
<br />
Using STM32CubeMx, I was able to build some skeleton code to drive the DAC. I found a Sinewave table online that someone had built that fit the bill nicely. It had 128 points.<br />
<br />
I ran the code, and it generated an absolutely beautiful Sine wave. Sorry I forgot to take a picture. Unfortunately, when I tried to increase the frequency of the sine wave, I couldn't get above about 1500hz before the microcontroller failed to make a signal. I didn't look into it deeply, but I suspect there simply wasn't time for the DAC to process the values between interrupts.<br />
<br />
I reduced the number of samples from 128 to 36. It made a respectable sine wave.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirXr9fc1ton3NEOqEEZS75gDL9uDcj_nUhuD97j-47EMBb_UtuxP4kx6VQ8i0yUokbVBGWvitxasOANw68yDmjJV4NdXOJC7gQWa8jOAjP0JI_sZmQ28TD8qCAZbhUW-nRm504D_5J56A/s1600/20170710_201143%255B1%255D.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirXr9fc1ton3NEOqEEZS75gDL9uDcj_nUhuD97j-47EMBb_UtuxP4kx6VQ8i0yUokbVBGWvitxasOANw68yDmjJV4NdXOJC7gQWa8jOAjP0JI_sZmQ28TD8qCAZbhUW-nRm504D_5J56A/s400/20170710_201143%255B1%255D.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Having done that, I was curious how it would look with 12 samples. As expected, it was rather lumpy.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyPc_HPQNEwx6a3eAkhccyU7uMUyeHx8vM67calhND0PFzSd2wGzPBzVncJdstZxXhZ7F5Knu55clt-LMcdNeh2fNNeiIBRAQyzRyeFue58jRUHWCgiRdnvj01kS-LhQWRUJZzfqBpRWY/s1600/20170710_195610%255B1%255D.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyPc_HPQNEwx6a3eAkhccyU7uMUyeHx8vM67calhND0PFzSd2wGzPBzVncJdstZxXhZ7F5Knu55clt-LMcdNeh2fNNeiIBRAQyzRyeFue58jRUHWCgiRdnvj01kS-LhQWRUJZzfqBpRWY/s400/20170710_195610%255B1%255D.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, I wondered whether I could throw a simple RC filter into the mix to smooth out the sine wave. I built one with a 330 ohm resistor and 0.1uF cap. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEmUFiDqVw9NVsFydLNJrbdWQpwAeVmIs94IzgPQHnPtcB4bVWGiWUyWj6zjKlqWMMvz-sst6sOFLLgflaMnrtxxsNJ7irrBS5IJ8vrMk19U-AmzKmXCQidXmGf-o62pdJCciiyZbL74I/s1600/Low-pass-filter-diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="142" data-original-width="526" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEmUFiDqVw9NVsFydLNJrbdWQpwAeVmIs94IzgPQHnPtcB4bVWGiWUyWj6zjKlqWMMvz-sst6sOFLLgflaMnrtxxsNJ7irrBS5IJ8vrMk19U-AmzKmXCQidXmGf-o62pdJCciiyZbL74I/s640/Low-pass-filter-diagram.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />
According to an <a href="http://www.learningaboutelectronics.com/Articles/Low-pass-filter-calculator.php#answer1" target="_blank">online calculator</a>, with those values, the filter cutoff frequency should be about 4825 hz, which is well above the 2200hz I was experimenting with. Voila. This is the sine wave with just 12 data points, run through the RC filter.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6t3-gQO0K_yKQ_M4vxdQlsL2ZYoHKWe8ARq9cr_8L1X5LxmFBVuNiIORMoPcgKPPmv9sfOeFUzhpt0BmCKRZbyN7TgbVRgSkKXaien8Fh4Gba_lV-VotEOhM-omGhZjaOMzM06xT7LoA/s1600/20170710_212724%255B1%255D.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6t3-gQO0K_yKQ_M4vxdQlsL2ZYoHKWe8ARq9cr_8L1X5LxmFBVuNiIORMoPcgKPPmv9sfOeFUzhpt0BmCKRZbyN7TgbVRgSkKXaien8Fh4Gba_lV-VotEOhM-omGhZjaOMzM06xT7LoA/s400/20170710_212724%255B1%255D.jpg" width="400" /></a></div>
<br />
<h3>
About attenuation</h3>
<br />
Note that the signal before filtering was about 3.3v peak to peak. After the filter, it was about 2.7v peak to peak. I didn't expect this much attenuation from the filter, but still, it's not bad. It could simply be due to the breadboard and cheezy connections I was using. Still, provided that 2.7v is sufficient to swing the signal on the Si5351b to achieve the proper deviation, I should be fine.<br />
<br />
<h3>
Alternatives</h3>
<br />
Should the attenuation prove too much to make a good signal on the Si5351, I have the option of running without a filter, and just fooling with the number of samples in the sine wave until I strike a good compromise. Still, I'd really <i>like</i> to use the filter if I can. I figure the GIGO (Garbage In, Garbage Out) philosophy applies here. The cleaner the signal I put into the Si5351, the nicer the output should be. <br />
<br />
Watch future blog posts for more experiments.<br />
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com1tag:blogger.com,1999:blog-1904678747905486184.post-35354315066156167952017-06-06T20:26:00.000-07:002017-06-29T08:36:05.308-07:00High Altitude Balloon flight - 6/3/17 from Rochester, NY Hamfest<h2>
High Altitude Balloon flight</h2>
<br />
Having <a href="http://hojoham.blogspot.com/2017/06/modifying-kodak-pixpro-fz43-for.html">modified a camera and built a controller</a>, I wanted to fly it to see how the camera worked. I assembled the payload into a foam box and rigged it up with a parachute. <br />
<br />
<h3>
Photos of the launch</h3>
<br />
Are available in <a href="https://goo.gl/photos/7nLS2sq7FoNiT3Ri6" target="_blank">this album</a><br />
<br />
<h3>
Payload parameters</h3>
<br />
<br />
<div>
<table border="1" style="text-align: center; width: 100%;"><tbody>
<tr> <th>Parameter</th> <th>Value</th> </tr>
<tr> <td>Payload mass</td> <td>650 g</td> </tr>
<tr> <td>Parachute</td> <td>30" octagonal (corner to corner)</td> </tr>
<tr> <td><a href="http://descentratecalculator.onlinetesting.net/" target="_blank">Estimated Descent Rate</a></td> <td>5.91 m/s (using Hexaagonal)</td> </tr>
</tbody></table>
</div>
<br />
<b><br />
</b> <b><a href="http://predict.habhub.org/" target="_blank">Flight prediction</a> input</b><br />
<br />
<br />
<div>
<table border="1" style="text-align: center; width: 100%;"><tbody>
<tr> <th>Parameter</th> <th>Value</th> </tr>
<tr> <td>Location</td> <td>Set with map to the Hamfest venue</td> </tr>
<tr> <td>Launch Altitude</td> <td>Unset (0)</td> </tr>
<tr> <td>Launch Time</td> <td>15:00</td> </tr>
<tr> <td>Launch Date</td> <td>6/3/2017</td> </tr>
<tr> <td>Ascent Rate</td> <td>Initially set to 5.5 m/sec. Predictor overwrote it to 6.3.</td> </tr>
<tr> <td>Burst Altitude</td> <td>Left to default at 30,000. Predictor over wrote it</td> </tr>
<tr> <td>Descent Rate</td> <td>6.0 m/sec</td> </tr>
<tr> <td><b>Burst Calculator</b></td> <td><br /></td> </tr>
<tr> <td>Payload Mass</td> <td>650g</td> </tr>
<tr> <td>Balloon</td> <td>Kaymont 1200</td> </tr>
<tr> <td>Target Ascent Rate</td> <td>5.5 m/sec</td> </tr>
<tr> <td><b>Advanced</b></td> <td><br /></td> </tr>
<tr> <td>Gas</td> <td>Hydrogen</td> </tr>
</tbody></table>
</div>
<br />
<b>Flight prediction Output and Actuals</b><br />
<br />
<br />
<div>
<table border="1" style="text-align: center; width: 100%;"><tbody>
<tr> <th>Parameter</th> <th>Predicted Value</th> <th>Actual Value</th> </tr>
<tr> <td>Burst Altitude</td> <td>34315 m</td> <td>33880</td> </tr>
<tr> <td>Time to burst</td> <td>93 m</td> <td>88 m</td> </tr>
<tr> <td>Ascent Rate</td> <td>6.12 m/sec</td> <td>6.388 m/sec</td> </tr>
<tr> <td>Launch Volume</td> <td>103.8 cu ft</td> <td>103.8 cu ft (est)</td> </tr>
<tr> <td>Descent Rate</td> <td>5.91 m/sec</td> <td>10.12 overall<br />
3.2 m/sec last 2000 feet</td> </tr>
<tr> <td>Descent Time</td> <td>133 m</td> <td>143 m</td> </tr>
</tbody></table>
</div>
<h3>
<br />Flight path comparison</h3>
<div>
<br /></div>
<div>
The flight followed the prediction almost exactly! It landed 10.24 miles further SSE than predicted. The parachute performed very well. I need to re-measure it to assure it's a 30" (and not 36") chute. That might explain the discrepancy. NB: I measured it. Yup, it was a 36" chute. That explains a lot!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi1DxnjCPfBjyAsMwzXFuNLx77DKE4UqKVhjdP0qlQCi6ZJH0eZ5OHjWozMvyBm39XwP-EQt-RSOb9wb5Y5j20mnKLrF4GPZT4zxBMjUZnASLvwyD7ZaPiRoLTV2tgW_I5nlzygBjBSoQ/s1600/comparison.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="993" data-original-width="1567" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi1DxnjCPfBjyAsMwzXFuNLx77DKE4UqKVhjdP0qlQCi6ZJH0eZ5OHjWozMvyBm39XwP-EQt-RSOb9wb5Y5j20mnKLrF4GPZT4zxBMjUZnASLvwyD7ZaPiRoLTV2tgW_I5nlzygBjBSoQ/s400/comparison.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h3 style="clear: both; text-align: left;">
Temperature data</h3>
<div>
<br /></div>
<div>
Charts in aprs.fi showed the internal tracker bottoming out about -39 degrees celsius, and the external tracker at -42c. I didn't work really hard on taping up the box, but it seems that such a large open box with a still camera really doesn't have much thermal mass. It'll be interesting to see how that changes when I have a video camera in there on the next flight.</div>
<div>
<br /></div>
<h3>
Lessons Learned</h3>
<div>
<br /></div>
<div>
<ul>
<li>Using a time profile for scheduling the snapshot frequency worked just fine. It was a good way to get more picture density during interesting periods of the flight.</li>
<li>I need to work on sealing the payload box better to see if I can stabilize the temperatures some. Everything functioned, but I would have preferred the cameras stayed warmer.</li>
<li>Using the "Landscape" mode on the Kodak Pixpro yielded blurry pictures. I got some great images, but more than 50% were blurry. I'm going to try "Sport" mode next time.</li>
<li>The camera performed well enough that I have purchased a second one to use as a video mode camera in the payload, and run two at once.</li>
<li>I need to remeasure the parachute to see if I can sort out the discrepancy in descent rate.</li>
</ul>
</div>
kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com3tag:blogger.com,1999:blog-1904678747905486184.post-72961124714836263202017-06-04T17:09:00.002-07:002017-06-04T17:09:30.915-07:00Modifying a Kodak Pixpro FZ43 for external shutter control<h2>
Modifying a Kodak Pixpro FZ43 for external shutter control</h2>
<br />
I've been using REALLY cheap 808 Keychain cameras for video on my flights. I decided I wanted to upgrade to something a little nicer, to get better video and still quality. There are some cameras out there with open firmware that people are using, but they're on the used market, and won't be available forever. I figured I'd try to venture off on my own and see what I could do.<br />
<br />
Design points:<br />
<br />
<ul>
<li>Relatively inexpensive (sub-$100) camera that has decent resolution for video and stills.</li>
<li>External microcontroller to run the shutter. I targetted the Atmel ATTINY13, since I have about 5 of them in my junk box.</li>
<li>AA powered camera, so that I can use Energizer Ultimate Lithiums (good in cold weather)</li>
<li>Depending on battery life when testing, I might want to wire in more batteries in parallel to allow for more pictures.</li>
</ul>
<div>
After trolling around on Amazon, I settled on the Kodak Pixpro FZ43. I scored it on Amazon Prime for $64. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4UlaHnXd-CvrHzM_69E1r6m3QlWvoQtqY1SC5NtcwX3cZufibcl11_Iuh6CNtUyQKRWC_Nad0O70yG21FNL_QQkMjkD4vlrEeF7P9vqn1Z1OYwMAMG3qONKnR74_haz0hM9mOcQyxeXc/s1600/Pixpro+FZ43.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="372" data-original-width="500" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4UlaHnXd-CvrHzM_69E1r6m3QlWvoQtqY1SC5NtcwX3cZufibcl11_Iuh6CNtUyQKRWC_Nad0O70yG21FNL_QQkMjkD4vlrEeF7P9vqn1Z1OYwMAMG3qONKnR74_haz0hM9mOcQyxeXc/s320/Pixpro+FZ43.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The specs for the camera indicated that it could take about 120 pictures on a pair of batteries. I would definitely want to wire in more. </div>
<div>
<h3>
Modification</h3>
</div>
<div>
<br /></div>
<div>
I opened up the camera, and it was a simple matter to find a little semi-riser where traces led from the shutter. As expected, pressing the shutter shorts a connection to ground. I connected two tiny wire-wrap wires to do some testing.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy9RMUtutA2g1_XA0yDx-Yqc5t8nQ9Z1kYhVRwn-_y673HnImH4ecfGKoxAVPMRO2bQh_OmUQ-TBOW3Abs2Eq8Q0reGxKljnz_yrhpqU2Gh_CPBjkh5tcPfi-_KbFFVaVbiP1IkxlAhVw/s1600/20170529_194729.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy9RMUtutA2g1_XA0yDx-Yqc5t8nQ9Z1kYhVRwn-_y673HnImH4ecfGKoxAVPMRO2bQh_OmUQ-TBOW3Abs2Eq8Q0reGxKljnz_yrhpqU2Gh_CPBjkh5tcPfi-_KbFFVaVbiP1IkxlAhVw/s320/20170529_194729.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I whacked together a little circuit diagram to control the shutter from my ATTINY13 chip. I was unsure how much current the shutter might sink, so rather than wiring it directly to the chip, which can only handle about 20ma, I elected to control the shutter via a transistor switch. A 2N3904 served nicely, and I had a about 8 of 'em in my parts box.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHwVO32CkL3uKq0EnG5QGw9ncgnNCdQpyu5VoEbRMBT1bXniraCaggNWUwQzQM5fsueGiyH9hIEDLifhUrXwXeO4_Nkoz0v1iRYQ9h4I3M2IML5pczXBFNk-lKronbI8Jju7db4gmM9uM/s1600/Timer+Schematic.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="745" data-original-width="1027" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHwVO32CkL3uKq0EnG5QGw9ncgnNCdQpyu5VoEbRMBT1bXniraCaggNWUwQzQM5fsueGiyH9hIEDLifhUrXwXeO4_Nkoz0v1iRYQ9h4I3M2IML5pczXBFNk-lKronbI8Jju7db4gmM9uM/s400/Timer+Schematic.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I confirmed that I could trigger the shutter by holding the pin (PB3 in my setup) high for 1/2 second. I assumed there would be some button de-bouncing done by the camera, so I started with 1/2 second, and it worked, so I left it. It worked like a champ.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3 style="clear: both; text-align: left;">
First Test</h3>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
With the camera working by microcontroller, I decided to do a duration test to see how the batteries held up. I turned off the flash, and left the camera running, taking one picture per minute, overnight with just a pair of internal batteries. The documentation stated about 120 pictures. I got 460! Those Ultimate Lithium batteries really rock! Also, there was no flash, and we were operating at room temperature, so in flight, I'm SURE there would be less capacity. I settled on wiring in two additional batteries in parallel with the camera, for flight, assuming that I could do 400-500 still shots in flight without difficulty.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
For balloon operations, I also like to have a beeper on the payload. I decided to put that under microcontroller as well, since hell, I'm a geek and idle hands are the devil's playground! The final schematic looked like this.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<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/AVvXsEg0i0wWWsHR9wgkTuWf-tZYFtsh17JGl3_8_SDgW74Wn3Ch6qnAhL3jwhBb2oEl2B0TZDt3Z2AFpLLdskDesRxAvjvSSt3_YCw1sf0qpYisWI-HDA6xufATNf7Hkc-2RShyphenhyphenCf6goQJDbjw/s1600/Timer+Schematic+2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="771" data-original-width="1177" height="261" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0i0wWWsHR9wgkTuWf-tZYFtsh17JGl3_8_SDgW74Wn3Ch6qnAhL3jwhBb2oEl2B0TZDt3Z2AFpLLdskDesRxAvjvSSt3_YCw1sf0qpYisWI-HDA6xufATNf7Hkc-2RShyphenhyphenCf6goQJDbjw/s400/Timer+Schematic+2.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Again, I used a transistor for the beeper. In testing, it was drawing well under 20ma, but I wasn't sure what the surge current was, so rather than take a chance, I tossed in another transistor.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Here are the final mods to the camera. I found a third pin that had the VCC rail on it. I put a wire to that, and secured it down with a little kapton tape. The wires are strain-relieved by knots on the inside of the case, which are too big to pass through the holes I drilled.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvl7Q5M86VJ79n8DnMzN4Fpd15asbbcJnZYrpt4Vszap5fy-8GcI6aDomA_vRhgwCesXlR6a3q869IYXlDz-a5q-HBOp0djOMTtibDDBJmvtRO1cHPAy_-pzDHZCC6TAJ4NmBGneCSim8/s1600/20170529_201442.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvl7Q5M86VJ79n8DnMzN4Fpd15asbbcJnZYrpt4Vszap5fy-8GcI6aDomA_vRhgwCesXlR6a3q869IYXlDz-a5q-HBOp0djOMTtibDDBJmvtRO1cHPAy_-pzDHZCC6TAJ4NmBGneCSim8/s400/20170529_201442.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I decided I would attach the camera to my controller and external batteries via a connector with some riser pins on it. Here's the finished product.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS1YB69H4NsNTLjrb-wUWRMA8QRv3NQ_7frwYIQMmgVKPuWzfWr9-gixK1PVDvXu_XzkZRVD4Zyo1euOjNLxiC0p-cSHfD2ihVrSe94CqSlYCF_6RZWn_FcgAJHKkM7lPYhRle-X05iGc/s1600/20170529_204548.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS1YB69H4NsNTLjrb-wUWRMA8QRv3NQ_7frwYIQMmgVKPuWzfWr9-gixK1PVDvXu_XzkZRVD4Zyo1euOjNLxiC0p-cSHfD2ihVrSe94CqSlYCF_6RZWn_FcgAJHKkM7lPYhRle-X05iGc/s400/20170529_204548.jpg" width="300" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Having tested all functions on breadboard, I just needed to whack together a little board for the payload. Here's the finished product, sitting on top of the breadboard mock-up. Subsequent to this picture, I wired in a few LEDs which fire when the transistors do. This just gives some visual indication that things are working, even if the camera or beeper aren't attached.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I set up the board to be powered from a bus which consists of the two external batteries wired in parallel to the internal camera batteries. The circuit, therefore, runs on 3.0 volts, which is well within spec of the ATTINY13. I did reset a "brownout" software fuse on the chip to make sure that it didn't reboot if it had a bit of voltage drop.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I built the board with an 8-DIP socket on it, so that I could externally program the chip, test it on my breadboard, and then just pop it off, and transfer it to the flight board. That way I didn't need to put programming risers on the flight board.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjotNvuHbC02S3Vio967gLL8XYle9oJxzhjDTyxyMz0vwr26k9CUuv_2LwnsWE3XPICNomnmMv8Q44LMwhpnYl-qcvs0mZuFJPvWJTKjatmYtajt3Umzu0OhkIH65hD-M1gCeG5H8M-b8E/s1600/20170529_215554.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjotNvuHbC02S3Vio967gLL8XYle9oJxzhjDTyxyMz0vwr26k9CUuv_2LwnsWE3XPICNomnmMv8Q44LMwhpnYl-qcvs0mZuFJPvWJTKjatmYtajt3Umzu0OhkIH65hD-M1gCeG5H8M-b8E/s320/20170529_215554.jpg" width="320" /></a></div>
<div>
<br />
I ran predictions for my first flight. It estimated 93 minutes to burst, and 135 minutes to landing. So, I wrote code for the ATTINY such that it took 6 pictures per minute in a 15 minute around burst time, and around landing time. I scaled back the picture rate during "boring" times for the flight.<br />
<br />
Final flight configuration<br />
<br />
Here's a picture of all the "guts" of my first flight payload. The green thing on the left is the tracker, which runs on one AAA battery. Then, I have the camera, flight board, beeper, and the two batteries that supplement the camera. The two batteries in the upper left are for the camera itself.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitParnd20V4qBdAbLUzcxro8CEjz-r37Z30vo5Mem0DKdRPdZBK4zTEC1leL33IFe_KSW1hG3YgjVG8kFqnNF5xGqFAMet9JLzwP9d3heykwA9iS1LkGjcf8xGa2_FfIWH0dyOGZpiOig/s1600/20170531_210117.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitParnd20V4qBdAbLUzcxro8CEjz-r37Z30vo5Mem0DKdRPdZBK4zTEC1leL33IFe_KSW1hG3YgjVG8kFqnNF5xGqFAMet9JLzwP9d3heykwA9iS1LkGjcf8xGa2_FfIWH0dyOGZpiOig/s400/20170531_210117.jpg" width="400" /></a></div>
<br />
<br />
The first flight showed that this system worked like a champ! I was getting 6 pictures per minute at burst, and at landing time. This allowed me balance battery power (and weight) against the desire to get interesting pictures.<br />
<br />
First flight. Two minutes after apogee, on the descent. That's Lake Ontario in the background.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKcoulsSDLGYeh81Fnr6DezF9wQFZVf8tJSN7sDRs9v0A0YR80xUIMepo4f59xPD83NBoxkO_h1xxlXVLwUDWf-BgyiHQCL3M8Cd610v6sAEui94P3_YlMp9-MqVgvEg5Fwyxy0XCETbo/s1600/100_0176.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKcoulsSDLGYeh81Fnr6DezF9wQFZVf8tJSN7sDRs9v0A0YR80xUIMepo4f59xPD83NBoxkO_h1xxlXVLwUDWf-BgyiHQCL3M8Cd610v6sAEui94P3_YlMp9-MqVgvEg5Fwyxy0XCETbo/s400/100_0176.JPG" width="400" /></a></div>
<br />
<h3>
Next Steps</h3>
<br />
While the shutter mechanism worked great, I was disappointed in the focus of the pictures. The camera does auto-focus on the center of the screen, An unfortunate number of the photos were out of focus. I'm going to mess with the settings to see if I can do better, or perhaps have it hard-code to "focus on infinity".<br />
<br />
Also, this worked very nicely. I'm getting a second camera which I will wire similarly. I'd like to have one taking stills and another taking video. I'll wire up the video record shutter (a different button) on the second camera, in addition to the shutter, so I'll have a 4-wire configuration. The microcontroller will then be able to switch between video and stills, should I choose.<br />
<br />
<br />
<br /></div>
kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-48863852274340030382017-01-19T20:40:00.001-08:002017-01-27T13:00:52.683-08:00Hojo and the case of the faulty FT-2800M<h2>
Hojo and the case of the faulty FT-2800M</h2>
<br />
<h3>
Background</h3>
A friend, Joe / W2IFB mentioned that he had a Yaesu FT-2800M fail on him. He had been keyed in a long QSO for more than 10 minutes when the radio failed, catastrophically. Thinking that he had blown the final, he tried replacing the final transistor. Unfortunately, it didn't work. He reported that the radio was basically in a "short" when plugged in.<br />
<br />
He gave me the radio and said "It's yours! If you fix it, maybe I'll buy it back!" I accepted the challenge.<br />
<br />
<h3>
Initial testing</h3>
<br />
I took the radio and set the current limiting on my power supply to 300ma, figuring that would be sufficient to demonstrate a problem. I plugged the radio in, and sure enough, it was drawing current HARD. Placing my ohm meter across the power leads, it showed 0 ohms. It's in a dead short.<br />
<br />
<h3>
Investigation</h3>
<br />
I opened up the radio and snooped around the board a little. I saw the power transistor that had been replaced, but didn't see any shorts nearby. It also seemed unlikely that a problem in the final would cause a dead short when the radio was still powered off. I also observed what appears to be a two-turn inductor coil that may have gotten a bit smushed. None of this looked like the cause of the short, however.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqt5vx9t4Fol4OfPn_3a8RFsfg1SsZQJJO1grXMdLyv0wbsMbgc5_e1vwMA3i4Gi4NiRS6xGD0cFqyGGsi0XXsheYZfCw1sy7mOQA03RdEecXP4UWfnAA39vFFeHYwLJOFwEbVrNY2tLg/s1600/Board+annotated.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqt5vx9t4Fol4OfPn_3a8RFsfg1SsZQJJO1grXMdLyv0wbsMbgc5_e1vwMA3i4Gi4NiRS6xGD0cFqyGGsi0XXsheYZfCw1sy7mOQA03RdEecXP4UWfnAA39vFFeHYwLJOFwEbVrNY2tLg/s320/Board+annotated.jpg" width="320" /></a><br />
<br />
I pulled out the schematics and took a look at the routing of the power. I assume the short must be very early in the circuit, since the unit uses a soft power switch, and it hasn't even been powered on. Glancing at the schematic, and board, I saw a few voltage regulators, and a protection diode.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7I1PrerHjodOOdn02Mlqepif9wADaCXI3J_r_G8VkjeA6TzNuZTJ2ZbHr-qp4NeTzMnkcq1rEYsAs1HvBYdWa-LBtwL2cnZKbhalXn0KqIYc4PeuoV4sU2z-dJ4kWY38hsTcQAzCK56w/s1600/schematic.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7I1PrerHjodOOdn02Mlqepif9wADaCXI3J_r_G8VkjeA6TzNuZTJ2ZbHr-qp4NeTzMnkcq1rEYsAs1HvBYdWa-LBtwL2cnZKbhalXn0KqIYc4PeuoV4sU2z-dJ4kWY38hsTcQAzCK56w/s400/schematic.jpg" width="400" /></a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The protection diode was right near the edge of the board, and an obvious first thing to check. It's a clamping diode, so a surge of some kind may have caused it to fail.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyBe-6Sy9AbOePNSG0DaZptx85rOwVBIKS8N9EuLzjfAZk7Emeey9rAV5wr-cNzz5nw-cPJ554gtZ3tceD_6yvjyPM8WLloL1yKPKY4f2s1ovcsJkk23pv-3xtq32BiKhg9z-Azr0L_xM/s1600/Diode.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyBe-6Sy9AbOePNSG0DaZptx85rOwVBIKS8N9EuLzjfAZk7Emeey9rAV5wr-cNzz5nw-cPJ554gtZ3tceD_6yvjyPM8WLloL1yKPKY4f2s1ovcsJkk23pv-3xtq32BiKhg9z-Azr0L_xM/s320/Diode.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: left;">
I removed the diode from the board, and sure enough! It's a dead short. 0 ohms in both directions. Further, I hooked it to the power supply and confirmed that the diode was permitting full voltage rom the supply through it in both directions. It's blown.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbBsqPf6BSzShQNpO0VPlsGnhKN6xGbIOFuchkLTW956b4m7452VBbZ0FiciNXHld9DIMzms15ErmGef3BavxB3Xlii2a9QRC98E9eEDvSZZ3L9vNSejMj89r6IhWdJdLHWWzhasGHfIg/s1600/20170119_215222.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbBsqPf6BSzShQNpO0VPlsGnhKN6xGbIOFuchkLTW956b4m7452VBbZ0FiciNXHld9DIMzms15ErmGef3BavxB3Xlii2a9QRC98E9eEDvSZZ3L9vNSejMj89r6IhWdJdLHWWzhasGHfIg/s320/20170119_215222.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Yaesu is kind enough to list the manufacturers part number in their service manual. Digi-key has <a href="http://www.digikey.com/product-detail/en/stmicroelectronics/P6KE18A/497-11385-1-ND/2674540" target="_blank">the part</a> for $0.48. I'll tuck one onto my next order.</div>
<h3 style="clear: both; text-align: left;">
Further testing</h3>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
With the diode removed, the power leads no longer showed a short. Encouraged, I decided to simply hook power to the board and see if the current draw was reasonable. The head was still detached, so I didn't expect the radio to power on. Sure enough, the current draw was down in the 10s of milliamps. I think that's reasonable.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Hooking up a more beefy power supply, I was able to run through a full suite of tests, and confirm that it was simply the diode at fault. The radio was working just fine.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3 style="clear: both; text-align: left;">
Repair and Alignment</h3>
<div>
I ordered up the diode and got it in from Digi-Key. The installation was trivial.</div>
<div>
<br /></div>
<div>
I went ahead and did a few tests prior to aligning the radio. It was transmitting about -650 hz off frequency at 146.000. Most other metrics seemed good, though it was only making about 50 watts on high power (should be 65).</div>
<div>
<br /></div>
<div>
<h3>
The Jig</h3>
</div>
<div>
The perform the alignment, I needed to inject signals into the microphone port. I decided to make a jig that I could use for this project, and in the future. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyP65Hu_kluhGDNCcASRQzzCTXaXmsHdJxd5ztDYSQHVkF84Sf8LkXmG1w7xJMfzXpOkMIaAYXf9ejrPpekusTqSqx7jYrJHpLGuy26GHnDR-cGN0Q7l0BD9-But7xeDKyJ62887-oCsc/s1600/20170123_210704.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyP65Hu_kluhGDNCcASRQzzCTXaXmsHdJxd5ztDYSQHVkF84Sf8LkXmG1w7xJMfzXpOkMIaAYXf9ejrPpekusTqSqx7jYrJHpLGuy26GHnDR-cGN0Q7l0BD9-But7xeDKyJ62887-oCsc/s320/20170123_210704.jpg" width="320" /></a></div>
I built a 6-pin cable to use for the project, and sorted out the pinout. Yaesu uses a common ground for the Mic and PTT. The Mic inputs go to the BNC port. The PTT goes to the toggle switch.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUwy8FieXHr6d6WUy-jU24pvAGOIgjhtUSAQzJqWIaROwpHFRt1IMT5yhrQV_kLzt1IBoexIcuOWegDO0M3YQvCnCZTwL-oB2eEpBRjfZEVaKeDpouotYaE5me-PG-aQSzIgvHtCbo3Ac/s1600/20170123_210905.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUwy8FieXHr6d6WUy-jU24pvAGOIgjhtUSAQzJqWIaROwpHFRt1IMT5yhrQV_kLzt1IBoexIcuOWegDO0M3YQvCnCZTwL-oB2eEpBRjfZEVaKeDpouotYaE5me-PG-aQSzIgvHtCbo3Ac/s320/20170123_210905.jpg" width="320" /></a></div>
The finished product. Now I can pump signals right from my service monitor into the mic port on the radio. The toggle switch makes it easy to engage the PTT without holding a button,<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<div>
<br /></div>
<h3>
Alignment Details</h3>
<div>
I followed the alignment procedure from the manual. Notes here for posterity.</div>
<div>
<br /></div>
<br />
<table border="1" style="text-align: center; width: 100%;"><tbody>
<tr> <th>Adjustment</th> <th>Original Value</th> <th>Adjusted Value </th></tr>
<tr> <td>PLL Reference</td> <td>-645 hz</td> <td>-15 hz</td> </tr>
<tr> <td>TP-TVC</td> <td>1.547 v</td> <td>1.502</td> </tr>
<tr> <td>TP-TVC</td> <td>0.925 v</td> <td>Not adjusted. Broken Trim Pot.<br />
Target value was 1.3 v.</td> </tr>
<tr> <td>TUN 137</td> <td>1.987 v</td> <td>2.009 v</td> </tr>
<tr> <td>TUN 146 </td> <td>2.050 v</td> <td>2.051 v</td> </tr>
<tr> <td>TUN 160</td> <td>2.026 v</td> <td>2.026 v</td> </tr>
<tr> <td>TUN 173</td> <td>2.018 v</td> <td>2.018 v</td> </tr>
<tr> <td>TXPW H</td> <td>50 w</td> <td>65 w</td> </tr>
</tbody></table>
<div>
<br /></div>
All other setting values were already optimal when measured, and were left alone. Current readings on transmit were all well under published maximums.<br />
<br />
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com2tag:blogger.com,1999:blog-1904678747905486184.post-61579219784240537532017-01-15T20:43:00.001-08:002017-01-15T20:43:12.579-08:00RCA WV988 VTVM recap and repair<h2>
The purchase</h2>
<br />
I found an RCA WV988 VTVM at a hamfest. It was labeled "Works - $10". I figured it would be a fun project to learn a little about recapping and tube based equipment. It has a minor crack in the face, but I don't really care. I'm more interested in this VTVM for the "puttering" aspects than for usability. Still, it'll be nice to have an analog meter on my bench if I get it working well. It's got a nice big display, and the crack doesn't impede use.<br />
<br />
I managed to find a manual for it online. It's one one electrolytic cap, which I'll replace. It's also got a selenium rectifier, which can release toxic "magic smoke" at failure. The interwebz recommend replacing that with a diode and series resistor.<br />
<br />
<h3>
A peek inside</h3>
<br />
A previous owner had soldered in a D-cell battery to operate the Ohm meter. I'll pull that out, and put in a battery holder. Also, clearly in view are the electrolytic capacitor and the selenium rectifier that will need to go.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaOszg8l_fvGz99KIcr9aMjjoElE68xHQudTbYx6Qdjyx8N6vvtS2mDuxleDtZSnulz2rgPqOto6D1bhNxwj1xLwsFCkPWjABW85-cJeS3wQ11QaFxC8LFH-38L76YrU6vRNj92sK3VuM/s1600/inspection.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaOszg8l_fvGz99KIcr9aMjjoElE68xHQudTbYx6Qdjyx8N6vvtS2mDuxleDtZSnulz2rgPqOto6D1bhNxwj1xLwsFCkPWjABW85-cJeS3wQ11QaFxC8LFH-38L76YrU6vRNj92sK3VuM/s640/inspection.jpg" width="640" /></a></div>
<br />
<h3>
Checking it out</h3>
<br />
I went through and tried all the basic functions. They were all pretty good, though it was slightly out of calibration. I'll go through and attempt a recalibration after repairing it.<br />
<h3>
Installing a battery holder</h3>
<br />
Easy enough. I desoldered the D-cell, and put in a AA battery holder. I drilled a small hole in the plastic holder, and countersunk it a little. I used the existing screw to install the new holder. I soldered in the wires and used a bit of heat shrink to insulate.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWodBjWsCR5Raxbr39E5Wv8Ela6-q4ynKIiqd5APSQKaUmk2obh65EPfNIl6vVflZfoaEXL3y7ZNbzP_twvojqiVW3AEfMMDPsSq0uDTHaXbzmn4DjSnrTE_0yIi8iGWIg5YzfLyWO4pk/s1600/20161210_121243.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWodBjWsCR5Raxbr39E5Wv8Ela6-q4ynKIiqd5APSQKaUmk2obh65EPfNIl6vVflZfoaEXL3y7ZNbzP_twvojqiVW3AEfMMDPsSq0uDTHaXbzmn4DjSnrTE_0yIi8iGWIg5YzfLyWO4pk/s320/20161210_121243.jpg" width="240" /></a></div>
The Old Battery, Soldered in.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjndfQax4GESfU9U8o7YrBWm0H7QJ1txsDCAe44ReaIW7nigsrJ3tGTtrTPcl3nnGGzL9uEFjNfi8Z03pLlGZX3vIybDfrbLsre1NaU74FSaf_5qUK5LyHAb6qh4UoVxvoYplx2oMlZ33Y/s1600/20161210_121526.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjndfQax4GESfU9U8o7YrBWm0H7QJ1txsDCAe44ReaIW7nigsrJ3tGTtrTPcl3nnGGzL9uEFjNfi8Z03pLlGZX3vIybDfrbLsre1NaU74FSaf_5qUK5LyHAb6qh4UoVxvoYplx2oMlZ33Y/s320/20161210_121526.jpg" width="240" /> </a></div>
Battery removed. I'll reuse that screw in the center of the old holder.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpeHllR_b2JxIWiZPgi8kZrF7y6I7mU0yGNlvj5vMBX-j046Zldmbfpkx2K3eHjYOUNs4S6Sz2SUf8owCClEDAO-9V5k0P8n4tsCysnhfkH1_htjNMrMwiaJLlusJRrN-LR5VprH4J20A/s1600/20161210_123033.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpeHllR_b2JxIWiZPgi8kZrF7y6I7mU0yGNlvj5vMBX-j046Zldmbfpkx2K3eHjYOUNs4S6Sz2SUf8owCClEDAO-9V5k0P8n4tsCysnhfkH1_htjNMrMwiaJLlusJRrN-LR5VprH4J20A/s320/20161210_123033.jpg" width="240" /></a></div>
Hole drilled in AA holder, and countersunk a little, so the screw isn't in the way of the battery.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi85mGxalHCyttcmLwxnWrnGrXp1qEInkvVLOy0cVcRcC6uHfKA9fIpa9ySlIIyVz6aJq2FL3nrLKD_Oo-NwMJ_NU7ro5IYFwAf5ceJwMnyXkGtZBYChw-b_i3hWyvWb7Vvf58NbLlCx00/s1600/20161210_124255.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi85mGxalHCyttcmLwxnWrnGrXp1qEInkvVLOy0cVcRcC6uHfKA9fIpa9ySlIIyVz6aJq2FL3nrLKD_Oo-NwMJ_NU7ro5IYFwAf5ceJwMnyXkGtZBYChw-b_i3hWyvWb7Vvf58NbLlCx00/s320/20161210_124255.jpg" width="240" /></a></div>
Installed, with a little shrink-wrap on the wiring.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC60eFiAJAdy7l59L72dCsKali2P9qxC-8Mh7HeoO4OOsAcT2qYfY0c1z75-Nz0BhkjqyKnDs9BrNAtiAVMnkywvR07jJvUbS3v5JNNOd2KNU9dWLQG8XrEL5YTCgDreSTrze-tjKREsU/s1600/20161210_124309.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC60eFiAJAdy7l59L72dCsKali2P9qxC-8Mh7HeoO4OOsAcT2qYfY0c1z75-Nz0BhkjqyKnDs9BrNAtiAVMnkywvR07jJvUbS3v5JNNOd2KNU9dWLQG8XrEL5YTCgDreSTrze-tjKREsU/s320/20161210_124309.jpg" width="240" /></a></div>
Now the battery is easily replaced.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<h3>
Replacing the cap and rectifier</h3>
<br />
The cap was a 20uF 200v. That was easily replaced. The rectifier is rated tat 20mA. It's easily replaced with a 1N4004 diode and a 2 Watt, 820 ohm series resistor. I followed the basic recipe in <a href="http://w3hwj.com/index_files/RBSelenium2.pdf" target="_blank">Rich Bonkowski's (W3HWJ) excellent article</a>. I tried a few different resistors until I got a voltage that matched what I was reading prior to the replacement.<br />
<br />
Since I was installing one additional component (the resistor) in series, I drilled two new holes in the board, and ran the diode to one of the new holes, and then connected the resistor from the adjoining hole to the other rectifier pin. Since there was no trace on the board for that connection, I simply extended the leads to one another, twisted them once, and soldered them together. The result looked nice and tidy.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimpR0m1Fh5aIsdXT3XCMrVduaTZJPJDQNNEoz2HOONr8E82_NkHDaRQaCtOOwSn1mNqNgQr38u-wYSdeOGG-NKrp5a8MjelZ8UTZokYkY_YbWiew4kViheHj2Rj5KvKROTAcZmP7Uhbyw/s1600/20161226_202100.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimpR0m1Fh5aIsdXT3XCMrVduaTZJPJDQNNEoz2HOONr8E82_NkHDaRQaCtOOwSn1mNqNgQr38u-wYSdeOGG-NKrp5a8MjelZ8UTZokYkY_YbWiew4kViheHj2Rj5KvKROTAcZmP7Uhbyw/s320/20161226_202100.jpg" width="320" /></a></div>
The old rectifier and cap.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheo4X2_i3hxPeOgfSpRGmh5bfTVCUnScaMyG4UJZ8Wn2WXtxyimfGTYSIgMmNOTy1Ze9vwVA0wHOccqRzB5KdWAqiTguB8Yh3gvdCZwApwz_TTHTv6K0wZaSA1OJn8Zi5kF_quWAntz4U/s1600/Board+annotated.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheo4X2_i3hxPeOgfSpRGmh5bfTVCUnScaMyG4UJZ8Wn2WXtxyimfGTYSIgMmNOTy1Ze9vwVA0wHOccqRzB5KdWAqiTguB8Yh3gvdCZwApwz_TTHTv6K0wZaSA1OJn8Zi5kF_quWAntz4U/s320/Board+annotated.jpg" width="320" /></a></div>
The PCB from the back side. The two new holes (bottom box) have leads through them from the diode and resistor. I simply twisted together and soldered them. The existing pads from the rectifier and cap are marked.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxQH0ws7-1AuAUY-6LftGBQNIXCkNn6JKtpgs7G70BKxP4h3QBKa1c6dM28NBeHGdUR4Fj_5nVbNOuwa13j4jtWRnP4C3ZsD61h-gl_B7rR3y_HfJ4Z-TIxuCnK2U7HQ8XFDFFSk2_kQ4/s1600/20161226_202128.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxQH0ws7-1AuAUY-6LftGBQNIXCkNn6JKtpgs7G70BKxP4h3QBKa1c6dM28NBeHGdUR4Fj_5nVbNOuwa13j4jtWRnP4C3ZsD61h-gl_B7rR3y_HfJ4Z-TIxuCnK2U7HQ8XFDFFSk2_kQ4/s320/20161226_202128.jpg" width="320" /></a><br />
The final installation of the diode, resistor and new cap.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<h2>
Testing</h2>
<div>
Upon testing, it appears that the DC voltage calibration was off, and it is at the limit of the variable resistor for tuning. It's off by around 1 volt. More follows as I sort out the issue.</div>
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0tag:blogger.com,1999:blog-1904678747905486184.post-82886434588560758482017-01-15T14:04:00.002-08:002017-01-15T20:41:57.063-08:00Building and using a Schmitt Trigger Oscillator<h2>
Building and using a Schmitt Trigger Oscillator</h2>
<br />
<h3>
Inspiration</h3>
Alan Wolke / W2AEW has a <a href="https://www.youtube.com/user/w2aew/featured" target="_blank">youtube channel</a> in which he does all manner of informational posts about electronics, RF and Ham Radio. He did <a href="https://www.youtube.com/watch?v=9cP6w2odGUc" target="_blank">a great video</a> showing how to do TDR measurements by using an oscilloscope and a Schmitt Trigger Oscillator which he built up from some scraps on his bench. I decided to build one for my own use.<br />
<br />
<h3>
Build and Test</h3>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyI1rA7e78YsneTZ0dNp_MmL3XaGjb8LKdmTgR1kygYspaCuH9jv8cvA8ZBs4hk-piaaaCQgLxh96D3n6oesR7cAdc-6ZDLyNin0Q4jkYaWzoobd7CCS-W3WHot3etX8m5WVGvpfwEWs0/s1600/layout.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="169" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyI1rA7e78YsneTZ0dNp_MmL3XaGjb8LKdmTgR1kygYspaCuH9jv8cvA8ZBs4hk-piaaaCQgLxh96D3n6oesR7cAdc-6ZDLyNin0Q4jkYaWzoobd7CCS-W3WHot3etX8m5WVGvpfwEWs0/s320/layout.jpg" width="320" /></a></div>
Being anal the way I am, I worked up the schematic and board layout in Diptrace. I decided to use thru-hole parts. Unfortunately, I'm not a wiz at Diptrace. It doesn't have great provisions to work in three dimensions. Some of the traces overlap or take weird routes, where I intended to just route around with some wire jumpers.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
I had most everything in my scrap box. I elected to use a CR-2032 (3V) button battery, seen on the left, since it would keep the whole thing small. I just had to order some <a href="http://www.digikey.com/products/en?keywords=296-4301-5-ND" target="_blank">Schmitt Trigger Oscillators from Digi-Key</a>. <br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOsjhi8dNeGNB47yT9XmqspAUyYeo8A8KW6zSTBDI5HynGi9qQ8_p0qMs6wdK8TVY9Op9G_bxv75p1TX1JsiI_KmOnmj1gvPDHymLE_f_ibU_TNWsNghM8WBWGCkfjvu7koHNVLSq0n3o/s1600/20170114_174413.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOsjhi8dNeGNB47yT9XmqspAUyYeo8A8KW6zSTBDI5HynGi9qQ8_p0qMs6wdK8TVY9Op9G_bxv75p1TX1JsiI_KmOnmj1gvPDHymLE_f_ibU_TNWsNghM8WBWGCkfjvu7koHNVLSq0n3o/s320/20170114_174413.jpg" width="320" /></a></div>
Here's the finished product. There is some kapton tape wrapped around it simply to protect the bare wires soldered on the bottom. The BNC plug is crazy glued to the perf board.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2pkHfMAHfaJl0UJCWQYYpaMTvrC8yqQGRgQ7enInoXBsLahvGzU1QUu7N2ojUWPgV4SPZL21a3Rzj5jmoZdnHF2f79NZJor06665kUxqdrHi_VQR_DOIckZQx5DoGOko1zZ6K1wUCiLw/s1600/20170114_174623.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2pkHfMAHfaJl0UJCWQYYpaMTvrC8yqQGRgQ7enInoXBsLahvGzU1QUu7N2ojUWPgV4SPZL21a3Rzj5jmoZdnHF2f79NZJor06665kUxqdrHi_VQR_DOIckZQx5DoGOko1zZ6K1wUCiLw/s320/20170114_174623.jpg" width="320" /></a></div>
Running my initial test, I found two issues. First, the clock frequency was quite a bit different from Alan's, though I used the same values for the resistor and cap in the oscillator, <i>I thought!!!!</i><br />
<i><br /></i>
Upon re-watching his video, he used a 47nF cap. I used a 4.7nF cap. Oops. Well, the oscillator frequency came out about 24 khz. That's still completely serviceable. I opted not to bother fixing it.<br />
<br />
The second issue (which I don't understand) is that the rise time is not as fast as Alan observed. I'm getting a rise time of about 9 ns. He was getting about 2ns. I used the same 72AC14 Schmitt Trigger DIP that he was using. I'm not sure why it might be slower. Still, even at 9ns, it's perfectly fine, and still much better than the cheap signal generator on my desk (24ns) which is also much bulkier.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<h3>
Practical use</h3>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB5Y2dolyKSh7RuTJkVO_VtE44-Fk2sLKgyPdt6Tj-Zz6q-JfyA6NuU0SFJDZOcb-t8UTGFnfQj44rDGieTGHLcg8i05K9pi5NKzgrYqeHwHuIkLDqlFlGZpPHy5h5itIqwJIZWTm9ga0/s1600/20170115_150224.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB5Y2dolyKSh7RuTJkVO_VtE44-Fk2sLKgyPdt6Tj-Zz6q-JfyA6NuU0SFJDZOcb-t8UTGFnfQj44rDGieTGHLcg8i05K9pi5NKzgrYqeHwHuIkLDqlFlGZpPHy5h5itIqwJIZWTm9ga0/s320/20170115_150224.jpg" width="320" /></a></div>
As it happened, we needed to know the cable length in our W2CXM shack between a new location and the antennas on the roof. I used this Schmitt Trigger Oscillator to measure it.<br />
<br />
I observed 173ns. We are using Beldin 9913 coax, which has a velocity factor of 84%. Using 11.8 inches/second, at 84% that's 9.912 inches/sec. With 173 nanoseconds that yields 1714.78 inches (142.898 feet) round trip. That's about 71.5 feet to the end of the cable.<br />
<br />
Kevin / WB2EMS used a proper TDR cable measuring device and came up with 72 feet. So, we're definitely in the right ballpark.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguYwmbmWM_9erv74_IT8bPvQdzPiT7elAAF1JmCUkR4bVEM-aHlueutqDAOlq34QNr6TGi9bpzU-uJoIaQMLsstF98pPwIjB-1peLTXFfKBWiAZy6Tqichxi-mnoPaRUFYw_2ZeTizTvg/s1600/20170115_150229.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguYwmbmWM_9erv74_IT8bPvQdzPiT7elAAF1JmCUkR4bVEM-aHlueutqDAOlq34QNr6TGi9bpzU-uJoIaQMLsstF98pPwIjB-1peLTXFfKBWiAZy6Tqichxi-mnoPaRUFYw_2ZeTizTvg/s320/20170115_150229.jpg" width="320" /></a></div>
Here's the oscillator hooked up to a small LeCroy 60 mhz oscilloscope up in the penthouse of my building. That scope is nice and portable, which made it perfect for this task.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzHPkHmGkXldKHK9X0HPr2v2Z6usBddufAxJQkjLmBIsQ2ZULM8H3iXIFr8ZHFa_npr1RcCi9u1-wppWLkjTnoH02DPbiEitoV7kCCx5c7EF2K7wtkvWXOV_FfqOJPgS9ecIQ9w2sBbU8/s1600/20170115_153642.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzHPkHmGkXldKHK9X0HPr2v2Z6usBddufAxJQkjLmBIsQ2ZULM8H3iXIFr8ZHFa_npr1RcCi9u1-wppWLkjTnoH02DPbiEitoV7kCCx5c7EF2K7wtkvWXOV_FfqOJPgS9ecIQ9w2sBbU8/s320/20170115_153642.jpg" width="320" /></a></div>
Note the boondoggle of adapters one can end up with, if your bag-o-dapters is missing a few things! I made note of what to pick up at my next hamfest!<br />
<br />
All in all, it worked great and served the purpose. It's small and easy to use. I've popped it in my toolbox with my adapters and other "antenna and coax" tools. Project successful!<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<br />
<br />
<br />
<br />kd2eathttp://www.blogger.com/profile/00709005938404511244noreply@blogger.com0