{"id":1023,"date":"2026-06-24T15:08:59","date_gmt":"2026-06-24T23:08:59","guid":{"rendered":"https:\/\/salemdata.net\/johnpress\/?p=1023"},"modified":"2026-06-24T15:08:59","modified_gmt":"2026-06-24T23:08:59","slug":"achieving-166-%c2%b5s-clock-synchronization-across-7-t-beams","status":"publish","type":"post","link":"https:\/\/salemdata.net\/johnpress\/?p=1023","title":{"rendered":"Achieving 166 \u00b5s Clock Synchronization Across 7 T-Beams"},"content":{"rendered":"<p>After much effort, I finally achieved running 7 T-Beams for 17 minutes, and having them create internal clocks based on satellite pulse per second, aka &#8220;PPS&#8221;, and finding they spanned by <strong>166 \u00b5s.<\/strong><span id='easy-footnote-1-1023' class='easy-footnote-margin-adjust'><\/span><span class='easy-footnote'><a href='https:\/\/salemdata.net\/johnpress\/?p=1023#easy-footnote-bottom-1-1023' title='&lt;strong data-start=&quot;3164&quot; data-end=&quot;3170&quot;&gt;\u00b5s&lt;\/strong&gt; means microseconds. One microsecond is one millionth of a second. For comparison, one millisecond, abbreviated &lt;strong data-start=&quot;3282&quot; data-end=&quot;3288&quot;&gt;ms&lt;\/strong&gt;, is one thousandth of a second.'><sup>1<\/sup><\/a><\/span><br \/>\nOne hurdle I had to overcome was a physical one: 1) the top of the T-Beam contains the GPS antenna which is like a fat mint and it is inside the case next to the base of the black LoRa antenna protruding from the case 2) the GPS antenna needs to point towards the sky, 3) the T-Beam USB connector comes out of the bottom of the unit, opposite of the side with the antenna. So you cannot stand the T-Beam on its bottom when you have a USB cable attached to it. I therefore decided I needed to suspend the T-Beams and accomplished that quickly with some scrap Port-Orford-cedar and my latest tool: an air gun stapler. So I rigged a suspension unit and then tied with twine each of the T-Beams so their USB connector could freely exit the base. What I found was that if I leaned the T-Beams at a 45 degree angle, any movement could cause a RESET because of wobble between the unit and the USB-C cable.<\/p>\n<figure id=\"attachment_1024\" aria-describedby=\"caption-attachment-1024\" style=\"width: 455px\" class=\"wp-caption alignleft\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-1024\" src=\"https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5422-scaled.webp\" alt=\"7 T-Beams handing from a horizontal wooden beam. A Bernese Mountain Dog lurks in the background ready to protect the flock of T-Beams.\" width=\"455\" height=\"431\" srcset=\"https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5422-scaled.webp 2560w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5422-300x284.webp 300w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5422-1688x1600.webp 1688w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5422-768x728.webp 768w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5422-1536x1456.webp 1536w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5422-2048x1941.webp 2048w\" sizes=\"auto, (max-width: 455px) 100vw, 455px\" \/><figcaption id=\"caption-attachment-1024\" class=\"wp-caption-text\">7 Hung T-Beams<\/figcaption><\/figure>\n<figure id=\"attachment_1025\" aria-describedby=\"caption-attachment-1025\" style=\"width: 461px\" class=\"wp-caption alignleft\"><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-1025\" src=\"https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5424-scaled.webp\" alt=\"7 T-Beams tied with twine to a small wooden beam\" width=\"461\" height=\"296\" srcset=\"https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5424-scaled.webp 2560w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5424-300x193.webp 300w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5424-1920x1233.webp 1920w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5424-768x493.webp 768w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5424-1536x986.webp 1536w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/06\/DSC_5424-2048x1315.webp 2048w\" sizes=\"auto, (max-width: 461px) 100vw, 461px\" \/><figcaption id=\"caption-attachment-1025\" class=\"wp-caption-text\">Back Side of 7 Hung T-Beams<\/figcaption><\/figure>\n<p>I was able to capture over the USB-C interface the UART\u00a0 messages without any interference or RESETS &#8212; a problem that arose often in earlier tests.<\/p>\n<p>I logged twice: 1) internal logging in the T-Beam to is static on-board RAM memory, and 2) logging to the serial console which my laptop captures with a Perl script that wraps each received transmission with a high precision date-time stamp.\u00a0 My laptop is synchronized to my local stratum-1 time source, providing a stable reference for the Perl capture timestamps.<\/p>\n<p>After the run, e.g. 17\u00bd minutes, I combine both types of logs into a directory and run a Perl script which parses and digests the log contents and then populates a SQLite database.\u00a0 Here are three SQL summaries documenting the capture integrity, measured inter-unit agreement, and stability across the run.<\/p>\n<p>&nbsp;<\/p>\n<h2>SQL 1 &#8211; Audit<\/h2>\n<p>Every unit should show exactly one START, COMPLETE, and FROZEN event, write_errors must be zero.<\/p>\n<table class=\"tbeam-sql-results\">\n<tbody>\n<tr>\n<th>unit_name<\/th>\n<th>capture_starts<\/th>\n<th>capture_completes<\/th>\n<th>capture_frozen<\/th>\n<th>capture_duration_ms<\/th>\n<th>records<\/th>\n<th>write_errors<\/th>\n<th>ram_overwrites<\/th>\n<\/tr>\n<tr>\n<td>AMY<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1020015<\/td>\n<td>3295<\/td>\n<td>0<\/td>\n<td>2911<\/td>\n<\/tr>\n<tr>\n<td>BOB<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1020021<\/td>\n<td>3272<\/td>\n<td>0<\/td>\n<td>2888<\/td>\n<\/tr>\n<tr>\n<td>CY<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1020017<\/td>\n<td>3272<\/td>\n<td>0<\/td>\n<td>2888<\/td>\n<\/tr>\n<tr>\n<td>DAN<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1020001<\/td>\n<td>3278<\/td>\n<td>0<\/td>\n<td>2894<\/td>\n<\/tr>\n<tr>\n<td>ED<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1020007<\/td>\n<td>3292<\/td>\n<td>0<\/td>\n<td>2908<\/td>\n<\/tr>\n<tr>\n<td>FLO<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1020010<\/td>\n<td>3272<\/td>\n<td>0<\/td>\n<td>2888<\/td>\n<\/tr>\n<tr>\n<td>GUY<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1020028<\/td>\n<td>5316<\/td>\n<td>0<\/td>\n<td>4932<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>SQL 2: primary seven-unit synchronization result<\/h2>\n<p>This is the main query supporting the 166 \u00b5s statement.<\/p>\n<table class=\"tbeam-sql-results\">\n<tbody>\n<tr>\n<th>unit_name<\/th>\n<th>central_samples<\/th>\n<th>median_host_minus_tbeam_ms<\/th>\n<th>seven_unit_median_span_ms<\/th>\n<\/tr>\n<tr>\n<td>AMY<\/td>\n<td>214<\/td>\n<td>-3.651<\/td>\n<td>0.166<\/td>\n<\/tr>\n<tr>\n<td>BOB<\/td>\n<td>219<\/td>\n<td>-3.644<\/td>\n<td>0.166<\/td>\n<\/tr>\n<tr>\n<td>CY<\/td>\n<td>221<\/td>\n<td>-3.562<\/td>\n<td>0.166<\/td>\n<\/tr>\n<tr>\n<td>DAN<\/td>\n<td>218<\/td>\n<td>-3.653<\/td>\n<td>0.166<\/td>\n<\/tr>\n<tr>\n<td>ED<\/td>\n<td>218<\/td>\n<td>-3.728<\/td>\n<td>0.166<\/td>\n<\/tr>\n<tr>\n<td>FLO<\/td>\n<td>220<\/td>\n<td>-3.678<\/td>\n<td>0.166<\/td>\n<\/tr>\n<tr>\n<td>GUY<\/td>\n<td>225<\/td>\n<td>-3.688<\/td>\n<td>0.166<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Negative values mean that, under this calculation, the T-Beam\u2019s reported disciplined time was approximately 3.6 ms ahead of the laptop-side capture timestamp; the important synchronization figure is the 0.166 ms spread among the seven units, not the common offset from the host.<\/p>\n<h2>3. show stability across the entire run<\/h2>\n<p>This query avoids relying only on one whole-run median. It divides the run into host-time minute bins and calculates the median offset per unit in each bin, then reports the spread among all seven units.<\/p>\n<table class=\"tbeam-sql-results\">\n<tbody>\n<tr>\n<th>minute_bin<\/th>\n<th>units_present<\/th>\n<th>seven_unit_median_spread_ms<\/th>\n<\/tr>\n<tr>\n<td>0<\/td>\n<td>7<\/td>\n<td>0.475<\/td>\n<\/tr>\n<tr>\n<td>1<\/td>\n<td>7<\/td>\n<td>0.364<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>7<\/td>\n<td>0.632<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>7<\/td>\n<td>0.194<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>7<\/td>\n<td>0.376<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>7<\/td>\n<td>0.343<\/td>\n<\/tr>\n<tr>\n<td>6<\/td>\n<td>7<\/td>\n<td>0.481<\/td>\n<\/tr>\n<tr>\n<td>7<\/td>\n<td>7<\/td>\n<td>0.413<\/td>\n<\/tr>\n<tr>\n<td>8<\/td>\n<td>7<\/td>\n<td>0.411<\/td>\n<\/tr>\n<tr>\n<td>9<\/td>\n<td>7<\/td>\n<td>0.48<\/td>\n<\/tr>\n<tr>\n<td>10<\/td>\n<td>7<\/td>\n<td>0.267<\/td>\n<\/tr>\n<tr>\n<td>11<\/td>\n<td>7<\/td>\n<td>0.32<\/td>\n<\/tr>\n<tr>\n<td>12<\/td>\n<td>7<\/td>\n<td>0.223<\/td>\n<\/tr>\n<tr>\n<td>13<\/td>\n<td>7<\/td>\n<td>0.356<\/td>\n<\/tr>\n<tr>\n<td>14<\/td>\n<td>7<\/td>\n<td>0.573<\/td>\n<\/tr>\n<tr>\n<td>15<\/td>\n<td>7<\/td>\n<td>0.384<\/td>\n<\/tr>\n<tr>\n<td>16<\/td>\n<td>7<\/td>\n<td>0.33<\/td>\n<\/tr>\n<tr>\n<td>17<\/td>\n<td>7<\/td>\n<td>0.144<\/td>\n<\/tr>\n<tr>\n<td>18<\/td>\n<td>7<\/td>\n<td>0.606<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The Perl script (contains the schema), log files, and database are available upon request.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After much effort, I finally achieved running 7 T-Beams for 17 minutes, and having them create internal clocks based on satellite pulse per second, aka &#8220;PPS&#8221;, and finding they spanned by 166 \u00b5s. One hurdle I had to overcome was a physical one: 1) the top of the T-Beam contains the GPS antenna which is [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_gfmr_meta_descriptions":[],"_gfmr_multilingual_taxonomy_terms":[],"footnotes":""},"categories":[133,80,130,121,1],"tags":[],"class_list":["post-1023","post","type-post","status-publish","format-standard","hentry","category-mesh-network","category-meshtastic","category-reticulum","category-t-beam","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/posts\/1023","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1023"}],"version-history":[{"count":8,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/posts\/1023\/revisions"}],"predecessor-version":[{"id":1035,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/posts\/1023\/revisions\/1035"}],"wp:attachment":[{"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}