月份: 2023 年 8 月

The Most Practical Codebase for ESP8266

No Comments

Name it as TMPC-ESP8266-Gen1 code base for Arduino ESP8266,version 1.0。

  • 大概從七月中到現在約一個月的時間,終於抵定此 code base 的寫作以整理出這份個人覺得相當實用,功能堪稱齊全足以做為基石的 ESP8266 code base。
  • 這份 code base,是基於前專案的寫作動機,the human motions ir sensing project,才萌發想要再次整理出一份 codebase 的念頭與今終於如釋重負地實現了。
  • 而此版與前(最後一)版專案的差異,便是將該專案中的 supervisor 的部份專用的扣納入 codebase 中,而整份專案便退位而成為 example;即,本篇文章所附的這份 codebase,確確實實地只是此 human motions 專案的改版而已 XD,不過,角色上與意義上可說截然不同。這真的是一份 code base!!!
  • 應當補述,除上述外,還追加了 /time 中,可自訂時間的功能,不過也因加了它,竟如量子漲落般,既存的良扣(真的)平白生出新的 bug;哈,這只是自我安慰,是 bug 便是,該修的還是要修。
  • 筆者如此地投入了大量的時間與精力,便是冀望能做出一份實用的,能輕易複用無負擔的扣倍使,除自用外也分享給各位 Arduino 同好。筆者的意思是,至少至少,本版的抵定 release,該測的,該除錯的,也都沒有偷懶省略。歡迎任何糾錯回饋,功能改進建議等等。

  • 對了,忘了交代,這份扣倍使有使用到這篇文章的 lib,”ESP8266 使用 LittleFS/SPIFFS 儲存與載入 變數/參數/資料“,需去該處抓;當然也可不使用它,但就是會缺少儲存與檔案系統相關的功能。另外,最好是看一下前篇文章 human motions sensing 的介紹,較能瞭解 example 的功用與運作行為等。
  • 再附加說明一個就是,ESPNOW 的使用並不是那麼友善,乃因為它的獨佔排他性。然而它的諸多優點也在前篇文章描述過。而此功能的包裝與實作在 codebase 裏也佔了不小的篇幅。因此對於 ESPNOW,其較佳的用法原則簡言之,在任一裝置,無論是 supervisors/servers/clients 的前置作業被完善後(devices been accessed via http completely)可說彼此已了無懸念,因此將被通知進入 ESPNOW mode;彼此亦將於適當時機進入(被動[被通知]後的主動[適時進入],或主動[通知他人]後的主動[適時進入]。並且亦有指令於 ESPNOW mode 中脫離 ESPNOW mode。再加上 supervisor 此角色的功用,就是讓使用者能夠穿透到 ESPNOW 空間內而絲亳感受不到 ESPNOW 的包袱。而這些都已包裝實現在 codebase 內了。
    角色與場景和行為等因專案而異可說五花八門,要良順地溝通可說相形複雜,而 codebase 便讓這一切簡單多了。

20230811 update

冏了,才三天,bug 就冒出頭來了 XD
也很開心修掉這隻 bug。因為這隻我以前就都會這樣使用了。。。唉一直都沒發現到。。。純然的盲點。。。
還有其他部份的小修。
比一下扣便知改了什麼,改動一丁點而已不再說明。上扣。

  • 沒有最好,只有更好,下一版註記
  • 用到了 syncNTP,其須加入 syncMyTime,以先更新至最新時間才能被取代。
  • whichMode 的 timeout 時間再加長。
  • 扣倍使加入 /http?url 應是不錯的功能,可讓 devices 間接上網;這也可藉以突顯 ap+sta mode 的附加能力。
  • 由於 ESPNOW 的響應時間短(長的話,誤差變異大例如 tcp),所以可思考實現在不同個體皆具均等性的前題下,利用廣播:零對多 -> 之一對多 -> 之二對多,達到三者以上時間同步的應用方法。當零對一,一除了 ESPNOW 傳輸及必要的運算延遲(set as D0)外,還包含了 setTime 的延遲;當一對零時,零便需做一次 setTime(但不改變)使得所有人同樣地落後,零同時可探求 D0 值;(至此初步同步);同時,二可同時藉由一以探求 D0 值;最後二發送 D0 值,零可判斷接受或 reject 此 D0 值。現假定零是中元標準時間那麼零將再廣播所確立的 D0 值供校正。對了,需有 id 標記該回的校正;協定上可接續某時距發送兩次取第二次以消除雜訊及判斷同步的可靠度。
  • 所以在前一段的應用下,首先可加強扣倍使 ESPNOW 的運作邏輯,使得可輕易自動讓 n 個 devices 上線達到同步;就現有的扣只差臨門一腳了。

這第二支備份可以玩玩看;需準備剛好 6 支 devices,刷同樣的 code 不作任何修改,但記得加共同 ap 給用。簡單講,隨機産生 host/clients,全進入 espnow mode,隨機傳送 data 及廣播給其他人。可發覺空氣中的分子相當繁忙。。。六個 com window 之前有提過,可使用 coolterm。
對了還有因路由器良窊之故,程序初期,任一個 dev 都要去溝通到其他的 5 個 dev,而必須至少要有一個 dev 確實達成,才會使得進下一步,全進入 espnow mode。若遲遲未進下一步,則將提示的被 collected failed 的那(幾)個裝置 reset,接續應就可順利進行下去。
看著結果群魔亂舞算有趣可以玩玩看。

這是莫名分隔線
接下來,上重點了。同步。

  • 思考題
  • 難道同步真的有那麼難嗎?
  • 是的,正如愛因斯坦所說,同步問題,無解!
  • 不過也有人提出同步是物理稟性,可能例如量子糾纏。所以不需要解。
  • 不過,若是加入一個前題條件,則同步問題很簡單就能解決,這。。。。。。,在筆者打完這段落就解決了。。。但可能就打上幾天幾夜吧XXD
  • 須定義,光是各向均性(質)均性,光子不是物質所以只能以性稱,所以連用兩個均性。即,光再怎麼樣被虐待多久都還是光,還是各向定速。YT 有一則很棒的對岸的科普影片可搜來看看(關鍵字小學),光在介質中/例如水中,速度變慢,其詳細論述了速度仍不變,而是因一些物理作用而呈現變慢/我忘得一字不剩XXD
  • 補充註記,後來再想一想申論。鏡像世界是上下前後全同左右相反的(嚴格應該說,上下左右同前後反),所以前面提到無解的原因就是我們不知道光鏡像後性質是否有變異。故今退一步承認一次鏡像是全同,才有有解說。今而若再進一步再退一步說一次鏡像是不同的,但只要鏡像必全同的話(不考慮二次鏡像是非鏡像),即放寬光只存在一次變異,那麼我們是可以通過三次鏡像求出鏡像後的速度的。換言之,後面的處理方法,可進一步推導出,host 可單獨求出 host 至 client 所耗用的時間即便往返的時間是不同的且無需 client 提供任何時間資訊。
  • 光與計算機科學?上述的,筆者只是要讀者類比即是。
  • 真正的傳輸路徑區分如下,
  • [産生傳送的意識念頭 A,即 Send() 那一個 token 開始] -> [內部處理 B(A) 至真正發送開始 B] -> [任何中介傳送 C,例如水,導線等] -> [從真正一接收到的內部處理 D(E)] -> [産生已一接收到的意識 E,即 Recv() 被呼叫的那一刻]
  • 前面提到過的 setTime/D0 的那段落,及前面也提到過若要誤差變異小,那麼就讓誤差的可能值最小化。給一百年,那麼我任何時刻一年十年等都可能 gg,但若只給 3 分鐘,一分兩分最多不過三分 gg,就是這個概念。
  • 因此,setTime 的方法被否決掉了,因其路徑太過邏輯且實際絨長,何不將不可控/不可預期/不可計時的部份最小化,即最後是剛剛所提到的傳輸路徑區分。
  • 因此,甲乙兩方的同步,就只要看甲方的 Send(),及乙方的 Recv(),探求時距即可。不過不過,實務上,並非那麼直觀便可解決。這就是接下來要講的。以此出發,或許各位可先行想想看。
  • 之前提到過,Send() 是主動的/至少從油蛇的觀點視之是如此;Recv() 是被動的,它可以是中斷函式又或是,出了 loop() 才能去巡訪的 callback 函式。換簡言之,Send() 是完全可控的,連續 Send(),意謂著 Send() 之間沒有時距。Recv(),若是後者,那我們能做的,就是一進入 loop(),便立即著手與 Recv() 相關的舉措,目的就是為了將可控的時間浪費化為零,不可控的時間減至最小,使得若有來資料,Recv() 便能以最短的延遲來響應。而若是前者 isr,那麼我們不僅無從施為卻也無關乎我們有做了後者的舉措,並且,其響應速度也必會比後者更快。故 anyway,做後者舉措便是。
  • 接下來,想像一下(迫擊)炮管與水管。這要類比用的。前者一個一個出,單元之間的時距是炮管長;後者連續出,單元之間時距是零。
  • 幸運地,傳輸中介,前面提到的 C,是水管。
  • 很不幸地,B(A),D(E),都是炮管。
  • 請仔細想想此類比如實。
  • 因此,做一次傳送接收,耗時就是 B+C+D。甲方只要告知乙方現在時間是 T 時,那麼乙收到後就將 T 加上 (B+C+D),則甲乙便同步了。
  • 問題在於如何求得 (B+C+D)。直覺地,若甲方連續 Send() 2 次,那麼,乙方 2 次收到的時間差,便是,。。。(B+D);反差地說,若 C 的傳輸時間即便是一百年,請因此仔細想想答案確實就是 (B+D)。
  • 問題是 C 當前還是未知也是沒搞頭;可以是 3 秒,也可以是 100 年,我們求不出來。
  • 易再想到地,如阿基米得的實驗,讓光折返,那麼甲方從 Send() 到 Recv() 的時間差 S1,便可進而求出 C。
  • 即,(前面提到過,devices 在不同個體皆具均等性的前題下)
  • 甲(B+C+D)+乙(B+C’+D)=S1
  • 因此,前面提到,須視光的去程和返程所耗用的時間是相等的。(B+D) 已知,S1 已知,若 C==C’,則 (C+C’)/2 便可得 C。
  • 看到這裏,各位是否更確信我們無從區分 C & C’,同步問題本就是個無解問題了。除非應用上物理禀性。
  • 因此,我們並非是要算 C,而是將 S1/2=D0,再廣播給 devices 便可讓所有人同步了。
  • 因此,唯一個舉措是如上做法求得 D0。setTime 則先給定一個時間值,彼方再陷入等侍通知例如約 1 秒,一收到便立即設定該時間,便可成立吾人可為之之最佳同步。
  • 寫到這裏,同步問題解決了,但程式還停留在上面第二份備份一字未增且,筆者可預期,講得簡單,程式又有好多扣得加了XXD
    希望,手上 LA 有 16 路,每路的 waveform 結果能回饋點成就感XD。若是 us 等級我就爽上天了XD。唉沒意義。將來若有結果再上圖。

20230907 update

上扣,只是備份的扣。第三次備了都還沒有告一段落的跡象XD
簡述一下,
前述的同步已經完成了。
測試結果不盡理想。
就以廣播來說,output 所呈現的 clients 所接收到的同步點,可看得出來,是肉眼難區分的。然而之後再同步來亮燈,卻是明顯不同步。所以問題出現在接收起始之後的程序。只能再加把勁看看了。
程式如同前述操作;其他就略述了。
真如預期加了不少東西,再預期,等到 release,與前一版比起來應是面目全非了吧;平平都是 release 版,功能也沒加上幾個,爸哥也沒修多少。。。目前扣倍使已經累積到五千五百行了。。。是多還少XD。。。真耐人尋味XD。。。

20230908 backup

終於解了,達到期望進度了。
就抓到一隻想法上的 bug,原先已知其可能有問題,但就是想不透,現想通了,可見此版註解與前版差異。
實測分成個別通知及廣播,反而廣播的誤差大,其可能原因出於廣播將造成廣播者與接收者拉開差距為其一/一直懷疑它廣播的作用是循序的,有機會再來查證;其二是個別通知是連續幾種命令一氣喝成的所以最後一條設時命令的延遲反而低(但仍遠大於約定延遲 150us~2500us),而廣播只有單一條設時命令,所以含了初啟動時間。
六個 devices,one host and 5 clients,
所以成果,是看任意兩者間最大差距多少,
個別通知,13ms,廣播,69ms,
並且,如圖,每一分鐘會再加 3ms 的累積誤差,所以如圖示下一次是 17ms。
事實上傳輸延遲尤其又是無線的,變異是頗大的。所以程式邏輯想法上是可行的,恰當的,但因無線而成果不是那麼漂亮。不過話說回來,已實作到如此地步了,針對,
1. 無線傳輸延遲之變異,2. 時序累積誤差,這兩條 issues,應都是可以再深入探究改善的。
舉例來說,延遲及設時都已先決定了也先給 client 了。新加作法為,設時不再是單程空封包,而是同測延遲的乒乓行為且封包內容為 time offset sequence,當某筆 time offset 其延遲是合約定的,那麼下一包便是結束以確保就算變異也能保時。不使用封包放延遲大小是因會超過 1 byte(不過話說回來編成 1 byte,那就只要 2 次乒乓就完事了)。time-offset 必須大於延遲的最大值。
(唉想到這裏,封包放延遲才是較佳做法怎沒想到XD,time-offset 更算是我目前做法的因變異而作的 workaround,但封包放延遲程式是愈加複雜,看我目前只是駐留在一個時間點扣就寫那樣了。。。想改又不想改。。。)(後續若有改,會假定反射傳輸不因彼此或不同時刻而異。提一下誤謬,求延遲時,初啟動和乒乓,最大值也只有 2.5ms[跑任務雖六者間最小差確實有 2.5ms]。那差到 13ms 或更多到底是怎麼來的?另外相對於 host,clients 有領先也有落後。到底這些誤差是怎麼來的?所以照這樣看來延遲差異應不是罪𣁽禍首。又如果是算式或邏輯錯誤,那 5 支 clients 應會有可被觀察到的相似性才是。再這樣講廣播,首次實時任務偏差達 70ms,但下一次的偏差是 70+3ms,3ms 被認定為時脈累積誤差,但反推,若所誤差的 70ms 是一次錯誤結果,那麼下一次應必須從該時間下再錯誤一次即 140ms 才是而不該只有 3ms;再反反推,是不是誤差産生更早於任務前;但數十次的反覆測試,啟動加乒乓行為從未觀到有超過 2.5ms[只有一次一支 11ms],由此也不該歸咎;但翻過來說,clients 間,錯誤誤差應會抵消使得相距很近而非遠大於 2.5ms 才是。當前幸而結果可接受,不然又內傷中了。這也一人寫扣的短板,卡關就是大關了)
至此,成果不漂亮但算自滿了。
應這樣說,若無線傳輸延遲是固定的,那 us 等級應是不困難的,因實作將可控變因都顧及到了。

20230912 backup

不意又把前面提到的封包放延遲的新扣加進去了,此版也埋了 debug code,和使用 gpio trigger,用 gpio 來測時間。debug code 大概率看不出什麼問題也不容易看。不過重點在於新扣及加了新扣後,上面提過的疑問,仍未解,但已有譜了,
簡單講,新扣是最精確的,但建立在光反射速度是恒定的前題下;因此,新扣讓人失望了,仍享受不到新扣的威力。
重點就是,延遲變異,誤人好深。就是它,始作庸者。
上一下圖如下,是新扣,基準已鎖定在 host,因此可看出,clients 都領先 host,表示,所使用的延遲比意欲的大,亦表示所抓出的反射時間比意欲的小,重點就是還不見得是這回事,也會還大。唉,可以理解。此外從圖上看到,最大差距 22ms,clients 間最小差距 722us。
所以結論就是,當前二種方法中,第二種嚴重依賴於反射時間,故使用第一種是最穩定的了。
該是結尾了,
以上全部所論,當前結論是最佳結果了,就這樣使用了。13ms 的最大差距,真的不錯了,收工。
按,ken 哥跳出來巴我頭了!
哈哈哈!
按,
哈哈哈:有看到嗎,前面提到的第一種方法,的 workaround,是不是暏光!
暗,別折磨我了!。。。

20230913 backup

  • 才一天又再次備份了,因為,北風尾了,就是因為那哈哈哈,
  • 氣而不捨地(鍥),把前一天提到的 workaround 實踐出來了。
  • 成果呢,嗯,初步所測的結果非常漂亮,是 20ms,
  • 蝦~毁~沒聽錯吧,沒打錯吧!
  • 是的,20ms;劣於第一種 13ms;優於第二種 22ms;就是非常漂亮的 20ms!
  • 正是因為它透露出了那最隱晦的暏光,待下一份備份完整交待/下一份將作個總整理將三種使用方式都交待清楚。
  • 而現在當然要講一下這第三種,不過,讓我們回顧,清楚一下這三種,
  • 第一種,
  • 會先檢測完畢 send-to-receive time cost(去返/2,後簡稱 SRT)的最大值和最小值,並取中間值供後來設時使用;試想,區間只橫跨 150us to 2500us,故結果再怎麼差,也頂多誤差個 2.5ms。除非後來設時時,正來個暴衝,若然,再修下扣便可輕易達所求。怎料,再怎麼測好幾十次,都是差到 13ms to 70ms 不等。無法理解。只能解釋為真的大暴衝了且也不能一直依賴於等到不暴衝。故比較後來就提出的 workaround(第三種)就是,若當設時時,並檢測 SRT 若大於預期,則在雙方已定義好的下一次或下下次等等的持續設時時間點,若合於預期,則任一方皆能夠計算出多延遲了多久以設時。如此成果將等同第一次便符合預期不暴衝的結果。此第三種後面會再詳述。
  • 第二種,
  • 便是直接設時,並同時檢測去返費時多久,以能夠通知 client 去減掉這個延遲。不過實作上作了個變化,即,假設 reflective send-receive time cost 簡稱 RSRT,是恒定的,當然應該是要恒定的,一收到便立即回覆稱為反射,若不恒定就有怪東西了。該強調的,比起第一種,其使用去返的平均,但若去返的時間相差頗大,那麼結果誤差就大。故第二種單獨求出 RSRT,以進而求得更精確的 SRT。
    事實上如本文一開頭就提過的(如同若光的去是 2c,返是 0,怎辦),除了先求出 RSRT,其他任何方法都無法精確求出 SRT。
    然而結果是 22ms,就開始懷疑人生了。
  • workaround 的方法,經仔細想過,就算協議好了,也只能由 host 才能計算出,無法單由 client 就計算出來。故第三種是 workaround 觀念的變形,且變很大。
  • 第三種,合該讓我們從頭說起,
  • 前幾種同步的方法,我們抓取 host 處於整時(fully-second)時的未來的時間點以作為參考零點,如此可免除 host 端將來取時執行任務時或反之因而轉嫁到 client 端之徒增的基於彼此對應上困擾。而它的特徵就是不連續且特定;以致於,所因而衍生出的那幾種同步法須在該侷限下予以轉圜,不免綁手綁腳。
  • 因此基於前面提到的 workaround 是可行的,不過我們仍需跳脫既有的思維,重新全面思考,所以以下的第三種,可說是集成演化,
  • 類似第一種,我們首先 probing 數十次,以取得極小值,這意謂著將來也有可能出現此極小值。
  • 我們將取此極小值,作為當將來一出現此極值時即做同步化的時間點。
  • 不過這是有風險的,若不再出現便 gg 了,所以轉圜成加上容忍值,如此實測上成功率百百。
  • 前面也提過,可能值區間愈小,誤差愈小,所以此法保證了,設定誤差最大多少,將能取得有誤差上限的漂亮結果。
  • 如此,不僅無畏地輕易跳脫了測光速難題,也將有不遜於該法的成果(這句話成立的前題是有其它維度的誤差存在且頗大時)。
  • 既然至此那麼簡單,確實,接下來困難的來了,
  • 雙方必須記錄每一次傳送接收時的 timestamp(表示多耗時了遜於前幾種),當上面所述滿足時,便能取用。當成立時,
  • host 將 timestamp 轉換成 epoch,連同測得的極小 SRT 值傳送給 client 以做再次的轉換。此 SRT 值實測,通常可在 350us 左右或可更小/170us 有出現過;單看無線品質。SRT 只有 170us 不甜嗎。
  • (當然,若將測光速與此法搭配起來會再改善;不過於當前情境下無意義)
  • 不同以往,補償值無法再視而不見了,然而,雙方該怎麼補,可見扣內說明,有點虐腦;兩三項加數/減數而已,但雙方間同步的對應要有精準的邏輯說明不容易。比一下扣查看新增的部份。
  • 另外明顯的差異是,第三種其取自過去的 timestamp 作為定位點而前兩種則是取自未來的時間點;所以觀點不同,優劣則也各有長短。
  • 因此結論,此第三種方法不同以往,最大的好處便是確保了誤差上限。
  • 也因如此而帶來的自信,由此也迎來了暏光乍現,待下回分曉。

20230916 backup

  • 終於告一段落了,
  • 先說,本版雖然是備份,但已將所實作的 espnow 的應用以範例的形式大部份都套用到了,包含 espnow 進出,集群,發送指令及資料傳輸,ntp 時間同步,亳秒級時間同步,任務執行等,全程大約跑上個 15 分鐘以展示整個範例。細節請看扣內主程式說明。
    因為主題是 codebase,所以此份範例可能不會成為 codebase 最終範例。故此份備份應可視為當前正式的一版本。
  • 再小修了一下,backup 08。
  • 不知各位是否已經有聯想到了,筆者最終才意識到的那一撇暏光,看看,也是因為它,讓筆者擠出了三種方法。也提一下,將方法二與方法三結合起來,將是最佳解。
  • 先前的所有測試當中,最佳的成績是 13ms,也全都大概是在系統啟動後的七分多鐘後才做第一筆 rt-task。做同步是約在第三分鐘。故同步後有四分鐘的空窗期,而若時脈偏差最大時距在 3ms,那,果然,四分鐘,成 12ms 的偏差。始作庸者,一直以來就都是它!!!
  • 換言之,espnow 傳輸,一般狀況下不會太不定不穩定,也又再實際驗證過了,此三種方法都。。。是對的,且是可行可用的。
  • 然而,要在同步後立即執行 rt-task 就目前現有扣架構下有難度,故當前筆者驗證過,此三種方法在盡快執行第一筆 rt-task 都有約 3~5ms 最大偏差的最佳結果。而依筆者的建議,第三種最優,細節請見扣內說明。況且,爭取同步後立即執行無任何意義;該思考,如何解決前面提出的第二條 issue,時脈偏差補償。然而這在某方面是無意義的因為,哪一支 device 才是時脈標準?當然主方面是有意義的,就以 host 為基準,所有 clients 皆用它來校準。
  • 經實測,各 device clock 本身皆有誤差值,所以兩兩間,有 0.65ms,也有 2.9ms 的。
  • 以上大概交待清楚了。
  • 依此/以上,校正並不會太困難但就是很擾惱人;host 同步後再隔例如五分鐘,再同步一次,但 client 端並不以來同步,而是以差值來校正往後每分鐘的修正量,稱它為校正同步。再況且,例如半天,再一次校正同步。故會有五分後及半天後的校正同步乃至於更大的時距也要。所以校正量分為一分作用,及或每小時作用及更多。。。
  • 所以總結,精神層面上筆者是很爽的因為做到了微秒等級的同步,但實際上卻吃不到XXD,才過一分鐘就長出了至少 650us 的偏差,就算這些方法精確度都達 <10us,也。。。只能自嗨了XXD
  • 當前筆者並沒有同步的需求,只是因為這篇 codebase 一開始就有提到同步,所以筆者索性就將它也生出來了吧。因此要再精進有兩點,方法二及三的結合,及校正同步。以後再說了。接下來應是 codebase 的正式改版了。
  • 收工。

20230923 backup

  • 又完成了一新段落了,。。。怎這份扣倍使好像沒完沒了。。。
  • 嗯,的確,沒完沒了有兩種,一種是 bug 解不完,另一種是必要的功能加不完。。。還好至少這次是後者。。。
  • 因為有俱足的進度所以趕緊先備份起來,此次,
  • 為前面提到的時脈修正鋪好路了。。。筆者似乎不見微秒不掉淚,所以又洗了一次頭。。。但還沒開始。。。
  • 有人會有疑問,時間同步,雖是用戶端同步到同一台主機,但怎會是主機主動對其一或所有 clients 作同步呢?確實,筆者實作的方向反了。。。不過問題也是簡單解決;非將扣改成反方向;而是僅多加一條 client 向主機要求同步的指令,便回到前題了。所以這部份完成了;亦謂雙向皆行。
  • 另外這次又漂亮地突破盲點,新增了 Timeafter 函式,潛力股,感覺上有取代 Timeout 的態勢,優點不遜於 Timeout。
  • 比起前一份備份更穩定,所以,至少當前,以本版來 demo 為最佳。
  • 所以,這份扣倍使,一路走來,只有更強,沒有最強!

20231008 backup

  • 這邊務必得引用前一次備份時所有說過的話,所以呢廢話省略了。
  • 再來,
  • 時脈修正,完成!但還未告一段落,接下來的描述,不再加形容詞了,句號。
  • 但真的很累人,所以還是得哀一下。
  • 沒有形容詞,但還是得有些抒發詞不然熬稠了無處宣洩。。。扣倍使已接近 7000 行了,且勢必破。若當中有某段程式碼是 67 那,89 不離 10,大略處處都是 67 了。相反地,若踢不到 67,是 567,那,7000 行的扣倍使,將如何使得。。。
  • 接下來,
  • 1. 更長時的時脈修正。
  • 2. 目前測過 7 支 devs,但每次總會有 2 ~ 3 支不如預期且不固定對象,原因得探求。
  • 3. 在 http 下執行同步。
  • 4. 經過長時間後,有些不再跑實時任務,可能已修正,還須觀察看看。
  • 5. 同步方法二及三的結合。。。一直猶豫要不要做。。。
  • 總的來說,可以問問某些專業的,7 支 40元/支 台幣的做了同步的埋控,經過 18 小時之後彼此間有最大不到 100ms 的時差,等級如何?
  • 若再想到會再補充,但得先休息一段時間了。。。

20231010 backup

  • 承前一次,已修正 2 隻大爸哥,
  • 不定地有某些 devs 不如預期的原因是乘除法或整數溢位,已修正。
  • 有一處時間處理上的邏輯的錯誤,致時脈校正不準確或更差;已修正。
  • 當前沒有其他問題了,只剩新增的功能如前述,待加寫。
  • 目前已測過 8 支 devices,很漂亮。若僅以同步而言,可觀察出前期(當然仍需 clkadj 介入)都可在 100us 以下。而以時脈修正而言,預估,3 天,最大偏移量可在 100ms 以下;而若 error_rate 設為 2(最小值了),也預估將有倍數的長進/偏移量更小。而這些都只是在基礎一階校正及三種初階同步方法(預設使用最佳的第三種方法)的作用下而已。
  • [更新補充],
    1. 上述數據是預估,其實不能這樣算的。當前的成果,僅是使用 6min 為校正時基,所以僅能保證 6 分鐘內有上述一定的精確度,不能外延,即,只使用了 6 分鐘,那麼每 6 分鐘後就會有一定的累積誤差産生。所以當前成績,18 小時 100ms 應該出入不會太大。當前的扣的最好成績是 13 小時差了 45ms。
    換言之,想要有持久性,就需有下一階及下下階等等的時脈校正參與。這代表扣至少更長時的校正是非做不可了。。。正賴以之前完成的 Alarm,或最新的 Timeafter,想要多久後/什麼時刻做,都可輕易完成,所以說,這份扣倍使,處處實用。
    2. 另外,有觀察到,系統時間/其使用 NTP time,經過半天後疑似有明顯落後(2秒)的狀況。其以之前的經驗,要很多天才會差異 1 秒。有可能只是因那讀秒的 polling function,若否,則可能因為暫停 watchdog or micros() 過度訪問所造成/將是硬體層面問題/不該如此,不深究僅註記之。

20231016 backup

每每再一次的更新(備份)都是彌足珍貴,極難極難重來的;即便假使該次更新 bug 重重,也都是唯一的,無可取代的,前一次版本的更上一階,失之,缺之不可!
所以一像個段落,就趕緊備份起來,否則萬一失了,真會是萬刧不復似的。。。
待下次備份一併說明。

20231019 backup

  • 這應該是最後一次備份了,接下來應要出 release 版了,且預計就是包含了兩份專案,前一個 hmsup 四方通訊的範例,及當前針對 espnow 的通訊及同步的範例。
  • 是滴,前面提到的功能全都完成了,除了 sync-method 2&3 的結合沒做外。沒做的最大原因是,個別這三種都是以最閒置的狀態去跑同步回應,因此最大的缺點就是一旦有 lost 某筆,整個會 hang up 掉。要避免,就是一定得插扣進去,影響“最短時間”,很不願意,所以就保持如此。結合,將更放大此缺點且免不了插扣,第二種方法是最佳法就是已插了 3ms 的 delay 了,很是敗筆但又無計可施。也因此第三種無疑是當前最佳解。但強調,第二種才是正解。
  • 在此之前,時間上的控管與角色控管都一直有漏洞。至此,兩者都應已完善。所以 main loop 至此應會很單純化了。
  • clock regulation 階層化,拖很久,因怕很難,但也終真超過預期完成,除了 base stage,繼而衍生的 stage 2,stage 3 一口氣多追尾了兩個,當然,還可以更多。
  • 也新增了原不敢想不願做的,儲存參數,也一併完成。
  • clkadj 3 stages 分別是 8,150,475 分鐘,所以一次完整的 sync/clkadj,就費時 11 小時。儲存就是,只消完整一次,往後,斷電重上電,只消一次同步(0 分鐘),參數自動載入,毌需再 clkadj。儲存的功能,不論對象是誰(hosts),完完全全自動化透明化(Load())。
  • 該提的是 staged,管線化,我比較習慣此稱呼,反於預期,細節見扣內說明。故該不該管線化視應用而定。
  • HTTP,也不用說,就可 http 了,/sync。而用 /s 可查看有無 clkadj 的差異/跑上一天看看。
    此外,就是只要一次的 /sync,只需確保 11 小時內,host hostname 未被改變且隨侍在側/無線得到的地方,那若 3 stages 全啟用,程式自動打理好 s/b/2/3 四次共費時 11 小時的同步。但記得,若要啟用儲存,則限定 stage3 不能啟用。
    如此,這般,全仰賴 Timeafter or Alarm 之助,漂亮吧!實用吧!
    真的這次生出了 Timeafter 之後,Timeout 都快忘了要怎麼使用了。。。不過相對地短板是便不易追踪/除錯,故忌濫用。
  • 結論,同步,極致了,何缺尚可為之?
  • 對了,7 devices,clkadj base 6min,完成後初期 deviation < 30us,初期偏差增漲約 10~20us/minute。主要都是 clients 距離 host,即,clients 間的偏差值通常都很漂亮;初期甚可 < 1us。至於管線化,會差很多很多,故說反於預期,但其應有助於長時距例如 1 天以上。
  • 扣倍使的目的與意涵是,務求熟悉它扣中每一處,使它成為您的左右手,腰際錦囊,只消熟悉這份,便能信手捻來隨心所欲的運用,除非有短板或功能欠缺。舉例來說,
    espnow 有 devices 共 20 支的限制。今既已實現了透過 http 去做同步(當然內層還是透過 espnow),那麼便能突破 20 支的限制,任一支適時向某 device http request 即成。並且,一次 3 stages 的同步(11 小時),如此會不會被某 device 長時間佔用?答案是不會,時間點到了,client 才會僅需再次自動發起 http request 而已;若當下有另一 device 在做同步,頂多等個二十秒吧。是不是,擁有一份,熟悉這一份,那麼一百支,皆能輕易完成同步!
    又若,真用上一百支了,那 host 必爆 RAM(table 存 100 個物件),故熟它,便曉得如何快速優雅地修改以應付需求。
    又若,想在最短的時間內同步一千支,該如何為之。採二(多)元樹狀的傳播。。。是不是很好玩且簡簡單單地就很有成就該一千支的成果。(當然愈後面誤差愈大,又是另一個有趣可以思考的問題了)。
  • 另外,這版備份仍是有啟動 espnow 資料傳輸測試,已知會破壞 receiver 狀態;故須把它註解掉以完整測試同步。下版仍會保留但會做排開。
  • 方才提到的最短時間同步,仍是得改扣。目前扣設定一旦做了同步,就會完整跑完流程所以是無法響應其他人所要求的同步。不過,就算扣有加了改了,仍有不小問題會展現在 mdns/bug 不知是出現在它身上或 router。。。同步對象/或自己本身的 hostname 會變異的機會是頗大的/且意外尚不僅於此,故將是一大隱憂。又再再顯示熟悉此基石,才知道如何順遂加扣改扣。

20231022 backup

  • 又食言了,修正一隻大爸哥,及細修/加零星的扣。值得提的如下,
  • 前面提到 stage 2 & 3 不如預期,原因之一是存在一隻大爸哥使用補償過的時間點去求補償,當使用原始時間點才是。修後若再低於預期乃更前面所述原因。故修後所測數據如下,雖不滿意不過有效果了,約一倍增益,分為 base 作用,及加上 stage 2/3 後的作用。於最後一次同步後約 200 分鐘後作量測,相鄰一分鐘後。
  • base:13.867ms,13.871ms
  • base+stage2+stage3:6.767ms,6.840ms
  • 乃前面短時間內同步多支之述吸引,修了些扣使得,這樣講,我的 hostname 若為 esp-11.local,那可保證必存在 esp-10.local。所以,且不論用什麼方法達最短時間;今同時地多支做同步就可以以頭咬尾的方式 request,即,11 提出同步的對象固定就是 10。不過前提是 10 必須已做過同步。故,當真面臨此需求時,再來提出方法與改扣。故當前已可,11 按 10 同步以後,還會有後續的同步事件,除非 10 已離線,不然必可抓到 10 來同步,原則上已不受 mdns 影響。且不再受舊扣當 10 處於同步階段便無法讓他人同步的限制。
    簡單講,此點完整修掉 20231019 的最後一點,尚留了一滴瑕疪下點述。
  • 扣將會再做一次備份因,mdns-full 雖然自動得到唯一的 hostname,但筆者在開發此同步整整說兩個月時間,因 mdns-full 的運行而浪費超多超多超多時間,為何就不多提,今已想到一法可解此困擾及因 hostname 變異引發的意外(抑制變異)。將接著加/改。不過此法將無可避免又浪費一些 RAM 及新 fundamental cmd。

20231024 backup

  • 早知道,就盡早把 mDns 給處理掉,因至今,已浪費太多時間在等待它的運行上及例如未達預期反覆重啟等等的了。結果一直忽略到今天才幾近完善它,得不償失。所以此備份,真的是備最後一次了,mDns 是真完善了;不過使用界面/下 http request,/mdns,不怎麼友善,想順順地使用它有點繞腦,所以此有改善空間,待應用之全貌更清晰後再來改;而真的,現已完全克服它了;不過一言難盡,省提。
  • http 同步,現已可例如 hmsup-2.local 對 hmsup.local,hmsup-3 對 hmsup-2.local 等等以此類推。且再也不用擔心 hostname 會有變異了,全解決了(當然是全自動,且刷同一份扣既此而已),只消注意誰對誰時,所對之者已同步過即可。。。看來也就醬了。。。也似乎沒進步空間了。。。
  • 再無缺憾。。。
  • 此備份 main loop 有異動以合適於前述的測試。
  • 。。。。哈哈!8000 多行了。。。。埋控。。。的扣倍使。。。。哈哈哈!!!
  • 哈哈哈!!!!!!!這是 Gen1,若 file-db 加進去;與量身訂作的/就是跟時間賽跑那幾篇是精華非整合不可;至 Gen2 時預想是加入既有的 multi-timers and multi-pwms,。。。破萬是必然!
  • 接下來休息了,無聊到發慌時再來做 release 了。

20231028 backup

  • 沒錯,自己都覺得好笑,好了別廢話,
  • mdns 先前都在 sta 做測,所以,這次進一步地完善了 ap and ap+sta,新增了此一些扣;故現全都支援了。
  • 不過就此問題乍現,之前就有提過,關於 mdns,偶爾會來個 wdt-reset,當 query services 時。猜想是 devices 間有 data 上的衝突/不一致所致而不以為然。然而,事實不然,讓我們換個方式講,
  • 會 wdt-reset,並非偶然,而是一定有問題在才會導致,但問題的問題是,該問題存不存在取決於藏得夠不夠深,若是晶片問題/純假設,那花了八輩子可能也找不出問題。對想到了,但也沒那麼糟。
  • 乃因百花齊放後,問題得以爆出來。八千多行,雖不見得 memory 耗用呈線性關係,但總很可能同是遞增函數,所以便聯想到是不是 stack/heap space 爆了。那我有什麼方法可以針對這方面除錯,嗯,所以這次新增扣之一,就是 stack/heap memory 的追蹤。該強調的是,此作追蹤 memory 的粗糙扣,雖不是此方面的除錯利器,合該稱是鈍器,但總是器,真的就是因此而突顯了那麼一滴滴跡象,才得以發現問題所在;真的,才得以。
  • mdns query service 將會快速耗用 20kbytes 以上的 heap memory,且持續蠶食,總共也才 29k。所以,爆不爆是遲早的事;尤其是當一個大系統在運行時將是命懸一絲。不廢話了,此問題未解,因為是 api 那邊的問題,斥或是或許是運用得不正確所致。
  • 當前嘗試關掉它某東西(ok)但 services declaration 似乎也失效了這並不苟同,所以會持續尋求繞路解/其原始碼並不多但自己對 mdns 所知有限也很不有興趣重寫不然,衝動是不小的XXD。
  • 故而,能發現問題是好事;若小系統,跑上個二十天問題才呈現,那真的會讓人厭世的。。。
  • 對了附帶一點,頂級絕妙的設計,推測,String 是使用未登記的 heap 尾端區,因此,當發現 string 怎會不預期消失或截掉或變異,便可知 heap 區用盡;可謂龐大的 strings 不僅沒耗用半點 memory space(flash 內亦有備份),會侵蝕便是反常該修,亦起到了告知作用;將錯就高明!

20231030 backup

  • 真的是結尾了。
  • mdns 應最終還是得面臨源碼修正的需求。
  • 至此,所幸將錯下,有大概率的繞過去了。唯 ap+sta mode,因且稱是佔用掉兩倍的 memory,所以 heap 區所剩無幾/也沒那麼糟,但就是讓整個系統處於最多約 9k 多,一旦跑例如 query services 並存入 String,則必然崩掉。而其他模式或狀態下則是正常,memory 至少至少都在 11k 以上,一些已知的壓測,都沒麼問題,記憶體不會無故減少。
  • 至此,ap, sta, ap+sta, espnow, mdns 全部完善破關了/也沒那麼誇張,就是常用的,都有完成且測試 ok 罷了。我指的是,runtime 地切換模式/設定 ssid-pw/自動取得 hostname 等等諸如此類較進階且真正實用的功能實現。
  • 說真的,我真沒想過,mdns 我最終可以完成到這個地步,。。。才幾週前,只因 mdns,每跑一次程式,就得等上個十幾分鐘才能有測試結果,若列舉不成功(host/client roles),還得重來。現在,已使得 mdns 隨侍在側亦不再帶有一丁點困擾了!
  • 順順的。。。
  • 此備份版的主程式跑環形 http sync 壓測,http7->http6, http6->http5, …, http2->http1, http1->http7。嗯或許會有問題出現/已知/不修不論。(通常有怪不打是因因應用而異)。
  • 接下來等想 release 再說了。

同步結論

  • 1. 誤差:
  • 於 stage3 修正後觀察 2 channels,ChA & ChB(7 devs,取與同步者 A 之最大差異者 B),時距 30 minutes。於此,LA 做為標準。
  • ChA 於此時距內增長了 14ms,即,1800.014 seconds
  • ChB 於此時距內增長了 17ms,即,1800.017 seconds
  • 可觀察出 ChA & ChB 間差了 3ms,不由得我們看個別當下兩點的差異,發覺,
  • T(0) ChA & ChB,B 落後了 1ms,
  • T(30) ChA & ChB,B 落後了 4ms。
  • 我們評算如下,
  • 同步後的時脈修正,我們所用的方法是補償了經過 Tsp 時距後的兩者間偏差 Tdv;例如 B 同步於 A,由 B 來做補償,以 A 為參考點這毌需贅言。此外當前看到的也釋了疑於會不會 A 或 B 時脈本身就會有偏差(Clk(n, n-1)!=Clk(m, m-1),週期性地可能會,不過必會抵消,除非不定增益,上述數據的一致無發現不定增益)。但我們仍會有疑問,為何 1+3 這三次的修正,無法修掉 3ms/30min 這差異。我們先除一下得,3000/(30×60)=1.67us/s 低於五十萬分之一的誤差。。。事實上已經夠好了,但其可觀的修後累積誤差亦是讓人留下遺憾。。。而這誤差也正是計算上的誤差加上不精準的傳輸延遲誤差,還記得嗎,我們正規化後的時距呈例如 3.141592s 的截位誤差。
  • 故,a) 取得精準的傳輸延遲誤差 b) 於取決參考時間點之時及界定傳輸延遲之時,以 assembly 為之 c) 計算之位元數之擴展須大於最小誤差/不過可以軟體方法解決 d) cpu 時脈之提高(目前 6.25ns);將決定同步的精準度,以 5G 來講可從 200ps(e-12)來爭取之為 <1ns。
  • 2. 成果:
  • 前面提過預估是 18hr < 100ms。現在新的數據是,error_rate(base, stage2, stage3)==(2us, 5us, 10us),19hr 為 30ms。比預期還少了超過 3 倍
  • 還記得最初同步成果的數據嗎:7 分鐘 13ms,且是在全然懵懂的腦袋下,一步一步克服層層關卡,才有現在此甜美的果實。
    若是沒有時脈修正(扣裏有埋一個開關 http /s 可觀察),19x60x2.6ms(deviation)-30ms=2.934秒;97.8 倍。花兩個月寫這麼多扣就只為了一個同步,今呈現一百倍的改善,值得了。

20231103 TMPC-ESP8266-G1 v.1.2 release

  • 內含 1 份 codebase 及 3 份 examples
  • example 分別是 EX1,espnow 模式下的 sync time,最多 20 個 devices,建議 6 個,刷同一份扣毌需修改;但若 devices 的個數異於 6 個,則須改此數值。
  • EX2,http 模式下的 sync time,不限 devices 個數,也不限何時加入成員。但很容易 hang up/因為多個 devices 所以同時 espnow communication 機率很大所以會造成資料漏失。也很容易發生分群,因為時間控管上不易;例如 http request failed 就會拖長時間而誤時。我以 7 個測大概十來分鐘就發生了,建議愈少愈穩,刷同一份扣毌需修改。(是可再加個允許旗標。但因此範例僅屬展示)
  • EX3,human motion ir sensing,前一份專案的 release。
  • file db 順道加入 codebase 當中,就不需去前面文章取得。
  • 後續如前所提會加入幾個之前的專案,成為第二代以期完整。

20231105 TMPC-ESP8266-G1 v.1.3 release

  • 改版這期間,曾針對 system-time 的 polling time 作過調整,有改岔,今修正之。human-motions 的部份也進版為 v.1.3

20231111 show off

此二圖是約 38 小時及足 48 小時後的修正後累積偏差,分別是 43ms,68ms,前後的 waveform 相對位置並無明顯差異;最接近的二者 1.3ms。再接下來的 1 至 10 小時之間皆維持在 66ms,1.67ms。故猜測或許修正累偏已收歛住了吧/直害我捨不得結束它們/別忘了,有三階隨時間持續增加的補償/表補償有到位使收歛(使用 ex1/7devs)。這結果算是筆者乃至目前看過最好的一次結果(以前的都會發散掉)。好壞到底是受什麼影響在同步結論已提過。
承前,73 小時後的數據是 96ms,1.6ms;channel 6 有發散掉了,即摘除它則為 78ms。但也有可能再過一段時間又縮/補償回來也說不定。
若無任何修正,其中之一已偏差超過 5 秒/73小時。
之前提過,是否任何軟體行為疑似會影響 cpu clock。比對此篇與前一篇的測果/結果;當前結論是,不會影響。
收工。
這篇主題扣倍使,卻失焦還於同步;但也不失基礎性質;無線/同步。下一篇是回顧也因而稍燃起了重整二巨頭以讓 Gen2 可以問世的念頭;不過二巨頭之前還有必要的專用時序要整理。全再看看吧。

PHP Code Snippets Powered By : XYZScripts.com