發表文章

目前顯示的是 11月, 2025的文章

文章總列表

ANT+找樂子(2),解析心跳感應器和封包

圖片
整活啦 ANT+ Device Profile,Heart Rate Monitor 規格 ,心跳傳輸的速度約4Hz。 上一篇範例程式 速度怎麼搞都很慢,問Grok AI,或是Chatgpt答案都很怪,這種冷門知識還是得靠自己。這篇要講心跳表的定義,以及怎麼用openant讀出數值 心跳表的規格 RF頻率 = 2457Mhz(下表的57代表2400Mhz + 57Mhz) 心跳表用哪個頻率是規定好的 訊息發送間隔是32768/8070=4.06Hz,大多ANT+感應器操作在4Hz附近 Device Type是0x78,Transmission Type=1 為什麼Message Period不設定成8192(4Hz) 為了避免無線電波碰撞。ANT+讓每個裝置頻率略有不同,就算發生碰撞也是短時間,稍後還是會錯開。這個是很有智慧的設計! 直接操作Channel 不囉唆,直接上code node = Node(), set network key ANT+的公開鑰匙,幾乎99%的ANT+裝置都用這把鑰匙 ANTPLUS_NETWORK_KEY = [0xB9, 0xA5, 0x21, 0xFB, 0xBD, 0x72, 0xC3, 0x45] new_channel,開啟host(電腦)和裝置的通道,這個通道是雙向的 幾乎所有範例都是雙向,直接抄 set_period(8070) 根據上表,心跳表的週期是8070照著設定 ch.set_id(54345, 120, 241) # GARMIN WATCH ch.set_id(49528, 120, 1) # Magene 上述的code,連接Garmin Watch或是Magene心跳帶都可以 ch.open() node.start() 開始和ANT+裝置溝通 finally:     node.stop() 如果按CTRL+C,有機會能正確結束程式。不然在MAC經常要插拔Dongle才能恢復 解析ANT+封包 來自規格書的照片先來一張, 中文資料 byte0[bit7]叫Toggle bit,ANT+經常會重送資料以免接收端漏收,招數很土,但是有用 因為會重送,所以當封包內容改變,toggle-bit會變化;這樣接收端就能判斷是資料有變 byte0[bit6:0]叫page,這裡是一個編號,代表後面b...

ANT+找樂子(1),建構開發環境

圖片
緣起 Garmin單車碼表是高階貨色,行業的領頭羊。搭配ANT+感應器,心跳表,單車踏頻,功率計,然後就被鎖在Garmin宇宙了。寫年度考績表實在壓力太大了,我決定深入看看ANT+協定,找樂子 找樂子工具 我用這些東西找樂子,他們不難找 Macbook AIR M2 ANT+ Dongle,下圖左邊的收訊很爛,右邊的好多了,不過都可以用 ANT+ Dongle再說個兩句 右邊的Dongle插入電腦顯示以下資訊,USB廠商識別碼0xFCF(4047),加拿大Dynastream公司在2003年發布ANT規格,2006變成GARMIN子公司 設定開發環境具體步驟 寫下來,下次重灌電腦可以用 取得libusb,和USB Dongle打交道 Windows也許有安裝包可以下載 MAC靠 homebrew 裝,我有點抗拒怕把系統弄亂。反正就找樂子,裝吧 連進他的網站,命令直接複製貼上 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 操作brew brew update // 更新brew工具 brew install libusb // 安裝libusb brew install joe // 安裝我慣用的editor, joe (這一步可跳過) brew list // 列出所有安裝的包裹 設定 openant 開發環境,已經有人包好方便的Python套件,找樂子,裝吧 建立獨立antdev開發環境,和系統Python隔開 python3 -m venv antdev 啟用開發環境 & 升級pip cd antdev source bin/activate pip install --upgrade pip 安裝openant開發包 pip install openant 掃描ANT+裝置 打開手錶的心跳廣播,戴上心跳表,或是讓任何ANT+裝置醒過來 輸入命令尋找ANT+裝置 openant scan 下圖找到裝置 - ID=54345 - Device_type=120 - Transmission_type=241 解析ID 稍微聊一下上面找到的ID,基本上ANT+裝置 完整ID 是32bit,由三個...

單車內搭衣指南

圖片
緣起 我一直想知道單車內搭衣,到底有沒有用。我前後測試非常多件,寫一下comment 96單車內搭衣 迪卡儂399內搭衣 ATLAS秋冬內搭衣 SHIMANO內搭衣 Q36.5 base layer0/ base layer1 新竹風城單車出清CABALLERO內衣 淘寶EVR內搭衣 內搭衣主要有四種材質,他們幾乎不會壞,這裡有 常見布料 介紹 聚酯纖維(可以上色) 聚丙烯(只有白色,繩子,超疏水) 尼龍(亮亮的,滑順,但是容易起毛) 彈性纖維(萊卡,Spandex) 內搭衣穿一整天 穿迪卡儂399當睡衣,衣服太透氣了,根本不聚熱,睡覺冷得要死;隔天套上T-Shirt/襯衫上班,辦公室有空調,一整天感覺冷冷的,這衣服不能替代棉質內衣 車衣+內搭衣,在戶外騎車 我騎觀霧來回大概10H,夏天單穿車衣,流汗流到衣服黏在身上 多一層內搭衣,保證車衣不黏皮膚;網狀材質的衣服不會黏在身上,不管是聚酯纖維,聚丙烯,尼龍,導汗效果都很好。只要拉下拉鍊,風加減能穿到身體,不會被濕車衣全部擋住 外騎我一定穿一件,只要沒有 熱到沒風 ,基本上都有好處 室內騎車的實驗 踩訓練台穿車衣加內搭衣,超白癡的實驗,多一層一定更熱啊!在室內穿內搭衣比較涼,也能避免汗亂噴,踩台我穿內搭衣 內搭衣+車衣(熱到受不了) 車衣(流汗衣服黏在身上) 內搭衣(電風扇能吹到身上) 內搭衣PK 我買了那麼多件,應該有資格說個兩句 聚酯纖維容易染色,所以顏色繽紛的貨色,大多是聚酯纖維 迪卡儂有 399 (聚酯纖維80%)和 749 (聚丙烯40%+尼龍40%)兩種內搭衣,我問grok AI差異,他說聚丙烯布料排汗效能最頂,只是難以染色,幾乎都是白色。也許我該去買一件749實驗看看 ATLAS秋冬款 是100%聚丙烯,非常透氣,比較厚 SHIMANO VERTEX內搭衣 是85%聚丙烯,蝦皮買從印尼雅加達寄來。和ATLAS接近 96單車內搭衣 比較薄,應該是聚酯纖維,穿起來比迪卡儂399涼 Q36.5 base layer 0 ,數字最小,應對最熱的天氣,非常薄,穿起來非常涼 Q36.5 base layer 1 ,比layer 0稍微厚一點,材料多一點 中國EVR內搭衣,網布比較大顆,保證隔開衣服和皮膚 CABALLERO網站停在2017,應該沒營業了。以尼龍為主力(90%),加上萊卡(10%)。標價1280出清20...

軟體架構,流程類軟體指南

圖片
緣起 在軟體裡,有些地方是流程(flow),目的是把別人叫起來。至於對方做什麼,其實我們不在意。這種軟體寫起來有些注意事項 開機流程範例 一般會有個進入點,對每個模組初始化,長得像下面這樣 // init.c extern void mod_a_init(u32 evt); extern void mod_b_init(u32 evt); typedef void (*func_fp)(u32); void init_flow() {     func_fp tbl[] = {         mod_a_init,         mod_b_init,     };     func_exec(tbl, sizeof(tbl)/sizeof(func_fp), EVT_BOOT); } 流程的比喻:貨輪 海運的貨櫃是標準化的服務,以貨櫃作為運送的單位。上述流程要求大家參數一致,讓流程呼叫 void (*fp)(u32); Function prototype 的用途 呼叫函數的約定(Calling Convention)定義在ABI(Application Binary Interface)裡。因為每次都會忘記,寫下這些詞彙當筆記 以範例的函數,第一個參數放r0,再用rcall指令跳進去。編譯器知道函數原型,比如幾個參數,各自的型別,才能正確呼叫 為什麼直接寫prototype,而不是吃對方的header file 不要吃模組的header,例如mod_a_intf.h,原因如下 軟體分層的邏輯,一般是上層應用吃底層的介面,沒有反著走的。init.c顯然是底層服務(例如長榮貨輪),他只要知道呼叫哪個函數,以及對方的參數正確(合乎貨櫃規格),不用全套知識(mod_a_intf.h) 防禦性設計,我們希望init.c固若金湯。如下面範例,mod_a_intf.h故意把SOME_OPTION轉ANOTHER_OPTION;假如init.c得看到SOME_OPTION,吃下去會出事 #if defined(SOME_OPTION)     #undef SOME_OPTION     #defi...