目标是实现从1mW以下到几瓦射频功率的测量。
原理图很简单,6个300欧电阻并联成50欧假负载,二极管检波、分压后由MCP3421进行AD转换,STM32F030控制OLED屏显示。供电用一节5号电池,BL8530升压到3.3V。
主要的麻烦在于检波二极管。2015年试过一次,用2SC1622、2N5551之类高反压三极管的BC结检波,结果发现输入频率50MHz时测得结果严重偏小,输入144M、430M时就完全测不到了,换成1N60则一切正常。可见结电容稍微大一点都不行。但是1N60的耐压只有40V,这样用单只1N60时能测到的最大功率为 \frac{(40\rm V / 2\sqrt{2})^2}{50\Omega}=4\rm W , 两只串联时也只有16W,还是稍嫌小了点儿。如果有耐压上百伏的锗二极管就能测到几十瓦的功率了。
调试过程略麻烦。MCP3421测得的是22k分压电阻上的电压, 乘以(492/22)后可得二极管检波后的峰值电压, 再加上二极管压降Vf即得输入电压峰值.
问题是小信号输入时二极管完全是非线性的, 因此需要对若干已知输入电压Vin, 算出二极管压降VD和电流I.
根据二极管模型 I\approx I_Se^{V_D/nV_T} , 可得 V_D\approx nV_T{\rm ln}\frac{I}{I_S}=nV_T{\rm ln}I-nV_T{\rm ln}I_S , 其中n, Vt, Is都是常数. 之后就简单了, 用若干组实测数据, 拟合出Vd和I的关系式为V_D=0.0294{\rm ln}I + 0.5005, R^2=0.9941 . 从R平方值来看拟合得还可以.
下表左边两列是根据输入电压计算的功率和dBm值, 右边两列是用ADC转换结果换算的功率和dBm值. 精度似乎不错, 除了第一组数据以外, 最多只差0.1dBm, -10dBm的下限已经远超预期了.
如果需要准确测量更小的输入功率呢? 可以把检波二极管换成更灵敏的1SS86(反向耐压只有可怜的3V), 或者直接上对数放大器AD8307/AD8310之类.
最后还有个坑: 一开始MCU选了STM32F030F4, 结果大概是因为浮点运算比较多, 最后编译完居然有30k多, STM32F030F4的16k Flash根本不够用. 保险起见, 换成了64k Flash的STM32F030C8.
二维码显示模块
做了个小模块, 可以把字符串从PC传到模块上存储, 并以二维码显示出来.
原理图如下, MCU用了48脚的stm32f103, 配1.44寸128x128的TFT屏, 存储么, 24C512和W25Q16各上一片. 其实只要24C512就足够了...
USB接口用了HID协议, 从stm32的官方USB例程改改就行, 好处是PC端不需要装驱动了. 程序太长就不贴上来了.
默认例程收发都是以8字节为单位, 这里先改成64字节, 但是64字节的数据包还是不够长, 所以需要做简单的分包处理. 思路也简单, 把第一字节的最高位和次高位作为首包和尾包的标志位, 接收时如果发现是首包, 就把接收指针指向接收缓冲区的起始位置; 然后把后面的63字节依次从USB端点复制到接收缓冲区, 之后接收指针增加63. 如果发现是尾包, 就设一个"接收完成"的标志变量为真.
主程序这边, 得到完整的数据后再调用libqrencode库, 把字符串转换成二维码显示出来, 最后设置"接收完成"的标志变量为假.
PC端程序用python实现, 因为有pywinusb库, 所以很简单, 贴上来:
import pywinusb.hid as hid
import time
# 从设备接收数据
def sample_handler(data):
data …
写了个取剩余可用堆内存的函数
原理就是二分查找, 不断malloc, 找到一个malloc(n)成功, malloc(n+1)失败的位置
如果堆空间不连续, 返回的应该是最大连续空间.
程序如下, get_free_mem()中调用__get_free_mem()时指定上下界.
static size_t __get_free_mem(size_t start, size_t end)
{
unsigned char *p;
size_t size = (start + end) / 2;
if(start == end - 1)
return start - 1;
p = malloc(size);
if(p != NULL) { // malloc succeeded
free(p);
return __get_free_mem(size …
卡片手电加强版
之前做过一个卡片手电,链接:卡片手电,感觉亮度不太够;但是如果加大亮度,电池续航时间又嫌太短。所以有必要做成高低两档亮度。
原理图如下:
这次改用升压恒流的方式。升压IC不一定要用MP1540,只要是能从单锂电升压到13~14V的boost IC都可以。LED用了四只0.5W的5730,取样电阻R308串联在LED回路中,因此低亮度档的电流为1.25V/39R=32mA,相应的功率大约是0.4W。当需要高亮度时按下SW302,此时Q301导通,R305、R306与R308并联,总电阻为8.58R,此时的电流是146mA,总功率约1.9W。电池正负极连接J302、J303,MicroUSB口通过U301对电池充电。LTC4054比较贵,可以用国产的TP4054等型号完美代替。ps. D301负极对地漏了个滤波电容,10u的贴片电容就可以。
升压恒流方式的优点是输出电流较小,因此取样电阻的功耗也较小;但当LED有一只断路时,boost输出电压会持续升高直到击穿,因此需要增加一只16V的稳压二极管D303,把输出电压限制在VFB+16V的位置。有些专门的LED升压驱动IC,比如MP3202,已经内置了保护电路。
实物如下 …
read more可级联的USB-UARTx2转换器
各种DIY实验时经常需要不止一个串口,有时需要三四个;再加上下载器之类,PC提供的USB口多半不够,所以还得来个USB HUB。这堆东西肯定会把桌面弄得很乱。如果把USB HUB和USB转UART做到一起,不就简洁多了? 于是动手,原理图和实物如下:
USB HUB IC选用GL850G,可以转出四个下级USB口。其中两个USB口接沁恒的CH340E,转为TTL串口;一个USB口用母座引出,可以用来接下载器之类。如果两个串口还不够,可以两套串一起用,这样就有四个串口了。
CH340E是沁恒新出的小体积USB-UART转换器,实测波特率可以到2Mbps;但是不怎么好焊,感觉引脚不太沾锡,与同样MSOP-10封装的XTR111、AD9833相比差远了。大概沁恒的封装工艺还需要加强。
ps. 刚看到沁恒又出了SOP8封装的CH330N,有空试试。
read moreCH341T GPIO实验
沁恒的CH341A是个多功能的USB总线转发器. 淘宝搜CH341A会搜出一大堆用它做的EEPROM/FLASH编程器, 而它的实际功能还要强大得多, 可以从USB提供异步串口、打印口、EPP/MEM并口、I2C、SPI等接口. 此外CH341A在EPP/MEM并口状态下还可以用沁恒提供的API直接操作引脚, 除了8位并口的8个脚以外, 若干状态引脚也能操作, 总共可以得到16个左右的GPIO. (其中有个别引脚只能输入或者只能输出. )
这东西的主要缺点就是封装是SOP28宽体, 体积实在大了点. 它的两个小兄弟, CH341T和CH341H都是SSOP20封装, 苗条了很多, 前者只提供异步串口和I2C, 后者只提供SPI.
CH341A配置不同功能是靠SDA的不同接法实现的, SDA/SCL悬空时连接PC会识别成异步串口, SDA拉低会识别成转EPP/MEM并口和I2C/SPI串口, SDA和SCL短接会识别成USB打印机. CH341T也提供了SDA和SCL引脚, 如果SDA接地, 能不能也把它的若干状态引脚当GPIO用呢?
做了块小板, 实际测试, 果然可以! PC直接把它识别成了CH341A.
接下来要实测哪些引脚可以使用. 这里要吐槽一下沁恒的API, 只提供了ch341dll.h, ch341dll.dll和ch341dll.lib; 试了各种办法想把ch341dll.lib转成mingw环境下的.a或者.o, 均失败. 没想到直接gcc …
read more做了个PSK31 Beacon
psk31 是业余无线电爱好者常用的通讯方式. psk31 的原理就不介绍了, 见链接: 哈罗 CQ 火腿社区 - HAM 软件、HAM 网站 - PSK31 簡介 BV3FG - Powered by phpwind
psk31 的调制如何具体实现呢? HAM 们常用的方式是用 digipan 等软件把要发送的消息调制到几百 Hz 的音频信号上, 再利用发射机的 SSB 模式把这个音频信号发射出去, 这里 SSB 实际上起了上变频的作用.
也可以把整个调制过程都放在 MCU 里进行, 直接从 MCU 的 DAC 输出调制好的音频信号.
ka7oei 则提供了一个偏硬件的直接调制方案, 见下图:
左下的振荡器振荡在所需频率的 4 倍上, 由计数器 74HC4017 接成四分频, 从 …
read more带电压电流指示的USB充电器
以前做过一个带输出电流指示的USB充电器, 电流指示用的是10段式LED光条, 用着挺好, 就是感觉10段式光条显示电流还是太粗略了. 最近玩了几个OLED屏, 感觉显示效果不错, 于是做了个直接显示电压电流数值的USB充电器.
原理图如下, Buck IC用的是AOZ1050, 同步整流降压, 号称效率95%, 不过最大输出电流只有2A. 输入电压范围是4.5到16V, 当然输出5V时输入电压得高于5V才行, 我用的是12V. (需要更大电流的话, 可以考虑TPS54331/MP1584/MP2303之类, 可以到3A; AOSMD的AOZ1014或AOZ1094可以到5A, 他家还有更大电流的产品, 不过不知道好不好买.) 0.05欧电阻R1和运放U5, PMOS Q1组成高端电流检测, R1两端电压放大22倍后进单片机的ADC通道0, 输出电压则直接分一半进ADC通道1. 单片机用了20脚的STM32F030F4P6, 16K/4K的FLASH/RAM已经足够了. 显示屏用了一片0.91寸128x32分辨率的OLED. LDO U3为单片机和OLED屏供电, 注意它的输入电压, 常用的XC6206之类只允许5V输入, 12V进去肯定是要冒烟的.
实物照片:
注意, 电流好象超了? 其实是测得不准, 测量发现运放两输入端电压差几十mV, 看样子是自激了. 果然这个高端电流检测的原型电路不能直接抄来就用, 得在PMOS栅极加电阻 …
read more试着用ATmega169做了个钟
之前试过M328在Powerdown模式/WDT中断唤醒时工作电流不到1uA. AVR 8位单片机里带LCD控制器的不多, 查了一下似乎就只有64脚的M169/329/649和100脚的M3290/M6490这几种. 前段时间搞了几个m169和4位8字的笔段式LCD, 于是考虑做个钟, 用CR2032供电, 看看它的低功耗性能如何.
WDT中断的时钟源是RC振荡器, 定时精度太差了, 做钟肯定是不行的; 幸好M169也支持T2定时器的异步模式, 可以用32.768KHz的晶振作为时钟源, 由T2中断唤醒. 以及M169的省电模式下LCD控制器仍然保持运行, 感觉都是很贴心的设计. 缺点就是... 体积太大了, 64脚还是0.8的间距, 封装面积是14*14=196mm2, 还不如用别的MCU配一片HT1621呢. ps. 这东西有9*9和7*7的两种QFN封装, 但是没见到哪有卖的.
原理图很简单, 就不贴了. 实物照片:
实测工作电流大概20uA, CR2032的标称容量有200mAh多点, 算下来能工作一年多. 希望明年这会儿它还能走.
read moreUSB-485隔离转换器
调试各种设备经常用到RS-485总线, 但是现在的PC连232也基本没有了, 只剩USB能用, 因此需要搞个USB-485的转换器. 做法也简单, 先用CP2102/PL2303/CH340/FT232之类IC把USB转成TTL电平的串口信号, 再从TTL转成485. (顺便点评一下: PL2303太差劲, FT232国内盗版太多, 用原厂驱动会烧, CP2102好用但是只有QFN封装不好焊, 国产的CH340最好用.)
这里有个问题, 485收发器都需要提供收/发方向信号(也有自动切换方向的, 比如MAX13487, 但是要用的时候总是买不到), 由MCU直接控制很容易, 但从USB转出来的串口信号没法判断方向. 网上的通行做法是把485的DI脚直接接地, 串口TXD信号用晶体管反相后驱动485的DE/RE脚. 这样在接收状态时, TXD空闲为高电平, 反相后把485的DE/RE拉低, 于是485方向为接收, 没问题; 发送0时TXD为低电平, 反相后485的DE/RE脚拉高, DI脚接地, 于是485输出0, 也没问题. 发送1时TXD和空闲时一样是高电平, 485的DE/RE拉低, 方向为接收, 此时485的A/B脚是高阻状态, 靠A的上拉和B的下拉电阻输出1. 这样确实能通讯, 短距离工作也一切正常, 但是总觉得不太可靠.
偶然发现国产芯片 …
read more