做了個PSK31 Beacon

psk31是業餘無線電愛好者常用的通訊方式. psk31的原理就不介紹了, 見鏈接:

哈羅CQ火腿社區 - HAM軟體、HAM網站 - PSK31 簡介BV3FG - Powered by phpwind

psk31的調製如何具體實現呢? HAM們常用的方式是用digipan等軟體把要發送的消息調製到幾百Hz的音頻信號上, 再利用發射機的SSB模式把這個音頻信號發射出去, 這裡SSB實際上起了上變頻的作用.

也可以把整個調製過程都放在MCU里進行, 直接從MCU的DAC輸出調製好的音頻信號.

ka7oei則提供了一個偏硬體的直接調製方案, 見下圖:

左下的振蕩器振蕩在所需頻率的4倍上, 由計數器74HC4017接成四分頻, 從0和2兩腳輸出一對相位相反的載波信號. MCU的PB2通過74HC00選擇相位. PA3輸出的PWM信號經低通濾波後, 再經U2, Q4調節Q3的漏極電壓, 實現在輸出0時將輸出信號幅度逐漸降到零的瞬間切換相位. 這個方案很簡潔, 我決定就拿這個圖稍微改動一下. MCU么, 用最簡單的ATTiny13就好了.

首先得在PC上軟體模擬一下. 程序很簡單, 找個psk31的碼錶, 一般是類似這樣:

const uint16_t VARICODE_TABLE[] = {n 0x8000, /* ASCII = 1 */n 0xFF80, /* ASCII = ! 111111111 */n 0xAF80, /* ASCII = " 101011111 */n 0xFA80, /* ASCII = # 111110101 */n...n 0xA000, /* ASCII = t 101 */n 0xDC00, /* ASCII = u 110111 */n 0xF600, /* ASCII = v 1111011 */n 0xD600, /* ASCII = w 1101011 */n 0xDF00, /* ASCII = x 11011111 */n 0xBA00, /* ASCII = y 1011101 */n 0xEA80, /* ASCII = z 111010101 */n};n

存儲格式是從高位到低位, 後面補零. 注意這個碼錶是從空格開始, 到小寫z就結束了, 也就是ASCII碼從32到122這91個字元, 這樣能省下不少寶貴的flash空間. 畢竟ATTiny13的flash空間只有可憐的1024位元組, 如果把完整的碼錶放進來, 一下子512位元組就沒有了.

發送一個字元的函數可以寫成這樣:

void psk31_tx(char c)n{n uint16_t varc;n for(varc = VARICODE_TABLE[c - ]; varc; varc <<= 1) {n if(varc & 0x8000)n printf("1");n elsen printf("0");n }n printf("00");n}n

然後隨便找個字元串, 比如Hello, world.

char msg[] = "Hello, world.";nchar *p = msg;nwhile(*p) {n psk31_tx(*p);n p++;n}n

編譯運行, 就能看到效果了.

在MCU上實現時要稍微複雜一點. 發送1好辦, 保持滿幅輸出不變, 挨過32ms時間就完事. 發送0就複雜一些, 需要按餘弦函數把輸出幅度逐漸減小為零, 切換相位, 再把幅度逐漸增加到最大. 把printf("1")和printf("0")分別換成這兩個操作就行. 但是這樣就破壞了可移植性. 解決辦法就是函數指針, 把psk31_tx函數寫成這樣:

void psk31_tx(char c, void (*tx0)(void), void (*tx1)(void))n{n unsigned short varc;n for(varc = varicode_table[(c - )]; varc; varc <<= 1) {n if(varc & 0x8000)n (*tx1)();n elsen (*tx0)();n }n (*tx0)();n (*tx0)();n}n

把發送1和0的操作寫成兩個回調函數傳給psk31_tx(), 這樣就完美了.

之後設計電路, 如圖:

振蕩這裡用一隻74AHC1G00加上14.318M的晶振就行了, 通過調節KV1471的偏壓來微調頻率. 四分頻用了更常用的74HC74, 兩級二分頻, 從第二級的Q和/Q腳輸出一對相位相反的載波信號. 切換相位用一隻模擬開關74LVC1G3157來實現. 其餘部分基本保持ka7oei的設計不變.

成品照片:

末級電源電壓這裡只用到5V, 實測連續發送1時在50歐假負載上可以得到40mW / +16dBm的功率. 如果把末級供電電壓提到12V, 同時把MMBT2222和2N7002換成封裝大一點的管子, 估計能做到1W上下, 再大就得加後級了.

ATTiny13的一大缺點是不能接晶振, 於是把它的RC時鐘設到4.8M, 通過OSCCAL寄存器微調到4.096M左右, 然後8分頻作為定時器0的時鐘源, 定時器0輸出PWM的同時也提供了4.096M / 8 / 256 = 2kHz的時基信號. 餘弦波形表用了64個點, 從而得到2k / 64 = 31.25Hz. 輸出1時只要什麼都不做, 等定時器0中斷64次就行了.

ATTiny13的另一大缺點... 就是RAM只有可憐的64位元組. 實測發現即使發送"Hello, world."也一樣爆棧, 只好不用回調機制, 同時把"Hello, world."也放到flash, 才總算是發送成功.

用IC-R71E接收, Digipan和MultiPSK解調的效果圖如下:

Digipan

MultiPSK

感覺Multipsk的解調效果要好一些, 可能是Digipan那邊有些參數沒設置好.

在這個Beacon的基礎上可以玩出很多花樣來, 看你怎麼發揮了.


推薦閱讀:

下半年所有的節日你都是派對焦點——印第安頭飾製作教程
學點兒DIY | 純手工給老婆大人做個電子錶,這狗糧很有技術含量!

TAG:业余电台 | 无线电 | DIY |