Don't wanna be here? Send us removal request.
Text
用LM2596搭建数控稳压电源
常用的LM2596芯片可以方便地搭成各种降压式开关稳压电源,但要用单片机来控制它的输出电压就稍微有点麻烦了——主要的思路有两种,一种是使用传统的电位器控制方式,用单片机控制数字电位器来代替模拟电位器;另一种则是利用单片机的PWM或DAC输出一个控制电压,引入到LM2596的反馈环路中。这次试验的是后一种思路。
如图,设输出电压为Vout,控制电压为Vctrl,LM2596的反馈端电压为Vfb,根据运放的基本性质可得:
Vctrl * R3/(R3+R8) + Vfb * R8/(R3+R8) = Vout * R9 / (R2+R9)
按上图的参数,可以写为Vctrl * 10/11 + Vfb * 1/11 = Vout * 1/4
对于LM2596-ADJ,其Vfb = 1.23V,于是有Vout = 4/11 * (10 * Vctrl + 1.23 )
于是,当Vctrl = 0V时,输出电压为1.23V;当Vctrl = 3V时,输出电压为11.3V左右。实际上由于LM358运放输入共模电压的限制,当供电电压为12V时,本电路最高输出电压为10V左右。在R2和R9的分压端引出一路信号到单片机的ADC来测量输出电压。
怎么测量输出电流呢?在输出地端串联小电阻检测电流虽然较简单,但是造成输入、输出不共地,许多情况下反倒更麻烦,因此这里选择了由R4、R1、R6、U3和Q1等元件构成的高端电流检测电路。如图,R4上的压降被U3放大15倍后,得到一个对地的电压,单片机测出此电压,除以15,再除以R4的阻值50毫欧即可得到输出电流。用12V 15W灯泡作为负载,实测工作状况如下:
PWM dutyVctrl/VVout/VIout/A14.6%0.743.10.4524.4%1.224.90.5634.2%1.706.60.6543.9%2.178.40.7453.7%2.6110.20.82
后记:用同样原理实现了APW7120+2SK3919*2的可调同步整流降压电路,实测最大稳定输出电流达到11A。
0 notes
Text
萤火虫瓶子 & LCD串行驱动接口
本来是发在新浪blog的,结果莫名其妙被关了,只好重写一遍……
前者是用AVR的io口模拟PWM,驱动8个LED闪亮。视频:http://v.youku.com/v_show/id_XNTI4Nzc4MDYw.html
分别试验了用PCF8574、74HC164和用一片ATmega48实现用串口驱动1602液晶屏。
PCF8574的方案很简单,4个IO按4线法连接LCD高4位,2个IO连接EN端和RS端。LCD RW直接接地,用一只7660产生负压。需要占用i2c口,显示速度慢、性价比也低,总之不推荐。
用ATmega48扩展的话,可以8线连接,接口用i2c、spi、uart都可以,用一个PWM口产生负压可以节省一只7660,是最灵活的方式,不过用uart时需要双方都有晶振。
用74HC164要多占用两个IO,不过用一些小技巧可以实现只占用两个GPIO:如图,用电阻和二极管形成一个与门,在串行写入数据时将最高位置1,写完8bit后再拉高DATA端,此时与门输出高电平,EN动作。之后要拉低DATA,连续八个CLK以清空164输出端,避免影响下一轮。实测写LCD快速、稳定,成本也是三种方式里最低的。
0 notes
Text
DiyNote: AVR SD播放器
得从大约两年前说起,那会儿amobbs的马潮老师出了个题目:8*8的LED屏,中间四个常亮,最外圈亮一个转圈跑。这东西没啥难度吧?我正好有块点阵屏闲着,就焊了一块板,从开始写程序计算,39分钟解决了。
讨论过程中一师弟(好象是TwoPerson?)大概出口不慎,把这位马潮老师惹怒了——于是他又出了个题,原文如下:
"如果不服,可以再次比试。你在北大找5个学生,组成一个小组。
用m16加一片lm324,设计一个读取sd卡上wave文件,并播放的wave播放器,看谁做的好。
给你们一���月的时间,下个学期开学我到北大找你,比试实物效果。 "
首先声明一下,本人纯粹是外行,本科化学,研究生改物理了,以上纯属业余爱好。马老师这题目在我这个外行看来,也就是一个人两三天到一周左右的工作量,至于五个人搞一个月么?不过后来事情一多也就把这回事忘了。
前段时间突然记起来了,于是动手开干。电路图太简单就不画了。觉得没必要上m16,于是用了一片m8,硬件SPI接SD卡,8位PWM输出,用一片TL061搭成低通滤波,后面一只8050缓冲接喇叭。从学习SD协议、实现FAT开始,焊接、写程序到调试全算上,用了两个晚上、周六全天加周日半天,基本完事。当然8位PWM的音质有点惨不忍睹……
程序如下,太乱了,懒得整理了……
----------------------init.c-------------------------
//初始化部分,是用zx提供的appbuilder生成的,好象是从iar里扒出来的?
//基本没啥有用的,直接跳过好了
#include
#include
void port_init(void) {
PORTB = 0x0;
DDRB = 0xff;
PORTC = 0xff; //m103 output only
DDRC = 0xff;
PORTD = 0xff;
DDRD = 0xff;
}
void timer1_init(void) {
TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0x00;
OCR1AH = 0x00;
OCR1AL = 0xFF;
OCR1BH = 0x00;
OCR1BL = 0xFF;
ICR1H = 0x00;
ICR1L = 0xFF;
TCCR1A = 0xC1;
TCCR1B = 0x09; //start Timer
}
//SPI initialize
// clock rate: 132300hz
void spi_init(void) {
DDRB &= ~(1<<4); // MISO as input
SPCR = 0x53; //setup SPI
SPSR = 0x00; //setup SPI
}
//UART0 initialize
// desired baud rate: 2400
// actual: baud rate:2400 (0.0%)
void uart0_init(void) {
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = (1<
/* UBRRL = 54; //set baud rate lo 19200
UBRRH = 0x0; //set baud rate hi */
UBRRL = 207;
UBRRH = 0;
UCSRB = 0x08;
}
//call this routine to initialize all peripherals
void init_devices(void) {
//stop errant interrupts until set up
cli(); //disable all interrupts
port_init();
timer1_init();
spi_init();
uart0_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 1<
sei(); //re-enable interrupts
//all peripherals are now initialized
}
-----------------------uart_spi_sd.c------------------------
//所有uart、spi的底层操作放这里,sd的一些基本操作也一起
#include
#include
#define SET_SPI_CS do { PORTB |= _BV(2); } while(0)
#define CLR_SPI_CS do { PORTB &= ~_BV(2); } while(0)
uint8_t sd_command( uint8_t cmd, uint32_t arg, uint8_t crc );
void uart_tx( uint8_t data ) {
while (!(UCSRA & _BV(UDRE) ));
UDR = data;
}
void uart_puts( char *str ) {
while(*str) {
uart_tx(*str);
str++;
}
}
void uart_write( char *buf, uint16_t n ) {
while( n ) {
uart_tx( *buf );
buf++;
n--;
}
}
uint8_t spi_writebyte( uint8_t data ) {
SPDR = data;
while( !(SPSR & (1<
return SPDR;
}
#define spi_readbyte() spi_writebyte(0xff)
//找了个现成的抄来了,有点傻,不过还算好用
uint8_t sd_idle_state(void) {
uint8_t i, retry, r1;
CLR_SPI_CS;
_delay_ms(1);
for( i=0; i<20; i++ )
spi_writebyte(0xff);
retry = 0;
do {
r1 = sd_command( 0, 0, 0x95 );
retry++;
} while( r1 != 1 && retry < 100);
if( retry >= 100 )
return 1;
retry = 0;
do {
r1 = sd_command( 1, 0, 0x95 );
} while( r1 && retry < 100 );
if( retry >= 100 )
return 2;
r1 = sd_command( 59, 0, 0x95 );
r1 = sd_command( 16, 512, 0x95 );
_delay_ms(1);
SPCR &= ~(0x3);
SET_SPI_CS;
return 0;
}
uint8_t sd_command( uint8_t cmd, uint32_t arg, uint8_t crc ) {
uint8_t r1, retry = 0;
SET_SPI_CS;
spi_writebyte( 0xff );
spi_writebyte( 0xff );
spi_writebyte( 0xff );
CLR_SPI_CS;
spi_writebyte( cmd | 0x40 );
spi_writebyte( 0xff & (arg >> 24) );
spi_writebyte( 0xff & (arg >> 16) );
spi_writebyte( 0xff & (arg >> 8) );
spi_writebyte( 0xff & arg );
spi_writebyte( crc );
do {
r1 = spi_writebyte(0xff);
retry++;
} while( r1==0xff && retry < 100 );
return r1;
}
uint8_t sd_read_sector( uint32_t addr, uint8_t *p ) {
uint8_t r1=0;
uint16_t i;
addr <<= 9;
r1 = sd_command( 17, addr, 0x95 ); //读出RESPONSE
// { char buf[32]; sprintf( buf, "r1=%d", r1 ); uart_puts(buf); }
while ( spi_writebyte(0xff)!= 0xfe); //直到读取到了数据的开始头0XFE,才继续
for(i=0; i<512; i++)
{
*p = spi_readbyte();
p++;
}
spi_readbyte();
spi_readbyte();
SET_SPI_CS;
return(r1);
}
-------------------------main.c------------------
#include
#include
#include
#include
#include
#include
//#include
#include
#include "init.h"
#include "uart_spi_sd.h"
static struct {
uint16_t addr_boot;
uint16_t addr_fat;
uint16_t addr_rootdir;
uint16_t addr_cluster;
uint8_t sectors_per_cluster;
uint16_t num_reserved_sectors;
uint16_t sectors_per_fat;
} g_sd; //自己凑和实现了个fat,下次不这样了,还是找现成的petit之类东西吧
volatile static uint8_t g_sector[512]; //还好m8有1k sram,可以挥霍,m48就没法这么用了
volatile static uint8_t g_buf1[32], g_buf2[32]; //双缓冲,不太好用,下次还是老实写个fifo吧
volatile static uint8_t g_currbuf = 1, g_updatebuf = 0;
struct fileinfo {
uint16_t first_cluster;
uint32_t filesize;
};
void abortmsg( char *msg, uint8_t data );
void get_sd_info(void ) {
uint8_t r1;
r1 = sd_idle_state();
if ( r1 != 0 )
abortmsg( "idle failed", r1 );
memset( (void *)g_sector, '\0', 512 );
r1 = sd_read_sector( 0, (void *)g_sector); //取MBR
if( g_sector[510] != 0x55 || g_sector[511] != 0xaa )
abortmsg( "read mbr failed", 0 );
memcpy( &g_sd.addr_boot, (void *)&g_sector[454], 2 ); //取引导区
r1 = sd_read_sector( g_sd.addr_boot, (void *)g_sector );
if( g_sector[510] != 0x55 || g_sector[511] != 0xaa )
abortmsg( "read boot g_sector failed", 0 );
memcpy( &g_sd.sectors_per_cluster, (void *)&g_sector[0xd], 1 ); //SD卡的基本数据
memcpy( &g_sd.num_reserved_sectors, (void *)&g_sector[0xe], 2 );
memcpy( &g_sd.sectors_per_fat, (void *)&g_sector[0x16], 2 );
g_sd.addr_fat = g_sd.addr_boot + g_sd.num_reserved_sectors; //文件分配表
g_sd.addr_rootdir = g_sd.addr_boot + g_sd.num_reserved_sectors + 2*g_sd.sectors_per_fat; //根目录
g_sd.addr_cluster = g_sd.addr_rootdir + 32 - 2 * g_sd.sectors_per_cluster;
}
int8_t get_file_info( char *fname, struct fileinfo *p ) {
int16_t i, j;
uint8_t r1, type, status, *tt;
char *t, filename[12], *extname;
//笨��法拆解文件名
strcpy( filename, fname );
t = filename + strlen(filename) - 1;
while(*t != '.' && t>filename )
t--;
if ( t == filename )
extname = NULL;
else {
*t = '\0';
extname = t+1;
}
status = 0;
for ( j = 0; j < 32; j++ ) {
r1 = sd_read_sector( g_sd.addr_rootdir + j, (void *)g_sector);
for( i = 0; i < 16; i++ ) {
type = g_sector[i*32];
if( type == 0 || type == 0xe5 || type == '.' ) // empty, deleted, currdir, parentdir
continue;
if( g_sector[i*32+0xb] & 0x10 ) // is subdir
continue;
//不是上面几种,说明是正常文件
tt = &g_sector[i*32+8-1];
while( *tt == ' ' ) {
*tt = '\0';
tt--;
}
tt = &g_sector[i*32+11-1];
while( *tt == ' ' ) {
*tt = '\0';
tt--;
}
if( strncasecmp( filename, (char *)(&g_sector[i*32]), 8 ) == 0
&& strncasecmp( extname, (char *)(&g_sector[i*32+8]), 3 ) == 0 ) {
//目标文件的首簇号和字节数
p->first_cluster = *(uint16_t *)(&g_sector[i*32+0x1a] );
p->filesize = *(uint32_t *)(&g_sector[i*32+0x1c] );
status = 1;
break;
}
if( status == 1 )
break;
}
}
return status;
}
//在timer1中断里把缓冲区数据送PWM输出
ISR( TIMER1_OVF_vect ) {
static uint8_t t = 0, n = 0;
TCNT1H = 0xff;
TCNT1L = 0x1;
t++;
if(t%2)
return;
if( g_currbuf == 1 )
OCR1A = g_buf1[n%32];// >> 8) & 0xff) | ( (g_buf1[n&0xf] << 8) & 0xff00);
else
OCR1A = g_buf2[n%32];// >> 8) & 0xff) | ( (g_buf2[n&0xf] << 8) & 0xff00);
n++;
if( n%32 == 31 ) {
g_currbuf = 3 - g_currbuf;
g_updatebuf = 1;
}
}
//喂缓冲区,双缓冲不好玩,下次还是改用fifo实现
void feed_data( uint8_t *pdata, uint16_t size ) {
uint8_t n;
do {
n = 32;
if ( size < n )
n = size;
while( g_updatebuf == 0 );
if( g_currbuf == 2 ) {
memcpy( (void *)g_buf1, pdata, n );
}
else {
memcpy( (void *)g_buf2, pdata, n );
}
g_updatebuf = 0;
size -= n;
pdata += n;
} while( size > 0 );
}
//先实现了个显示文本文件内容的函数,然后把输出文本的部分改成喂缓冲区了
void view_file( char *filename ) {
struct fileinfo finfo;
uint16_t n_clusters, next_cluster;
uint8_t i, ret;
ret = get_file_info( filename, &finfo );
if( ret == 0 )
abortmsg( "Open file error!", 0 );
n_clusters = finfo.filesize / ( g_sd.sectors_per_cluster * 512 ) + 1 ;
char buf[32];
//sprintf( buf, "n_clusters:%d\r\nfirstcluster:%d\r\n", n_clusters, finfo.first_cluster );
uart_puts(buf);
next_cluster = finfo.first_cluster;
do {
// read a cluster
for( i = 0; i < g_sd.sectors_per_cluster; i++ ) {
sd_read_sector( g_sd.addr_cluster + ((uint32_t)next_cluster) * g_sd.sectors_per_cluster + i, (void *)g_sector );
if( finfo.filesize > 512 ) {
// uart_write( (char *)g_sector, 512 );
feed_data( (void *)g_sector, 512 );
finfo.filesize -= 512;
}
else {
// uart_write( (char *)g_sector, finfo.filesize );
feed_data( (void *)g_sector, finfo.filesize );
break;
}
}
// get addr of next cluster
sd_read_sector( g_sd.addr_fat + next_cluster / (512/2), (void *)g_sector );
next_cluster = *( (uint16_t *)(&g_sector[ ( next_cluster % (512/2) ) * 2 ]) );
n_clusters --;
} while( n_clusters > 0 );
}
void abortmsg( char *msg, uint8_t data ) {
char buf[32];
//sprintf( buf, "%s\t%d\n", msg, data );
uart_puts( buf );
while(1);
}
//取剩余可用内存块,傻了点,不过能用
uint16_t get_avail_mem(void) {
uint8_t *p;
uint16_t i;
for( i = 1; i < 65534; i++ ) {
p = malloc(i);
if( !p ) //分配失败,说明可用内存就剩这么多了……
break;
free(p);
}
return i-1;
}
int main(void) {
static char buf[32];
struct fileinfo finfo;
init_devices();
_delay_ms(50);
PORTB &= _BV(2);
_delay_ms(50);
get_sd_info();
{
//一开始用16.9344M的晶振,发现不好用,16.9344M/44.1k=384,正好一个半PWM周期……手里没有11.2896M的晶振,只好用8M内部RC慢慢调整到接近11.2896M。用r-2r方式的话就不存在这个问题,直接上24M或27M晶振然后把PWM频率调整到接近44.1kHz就行。
uint8_t old_osccal, i;
old_osccal = OSCCAL;
// 242是用示波器试出来的,得慢慢调快,以免抽筋
for( i = old_osccal; i <= 242; i++ ) {
OSCCAL = i;
_delay_ms(5);
}
// 得重新设定uart分频比例,不然串口输出全变乱码了
UBRRL = 37;
UBRRH = 1;
}
/*
{ abortmsg( "OSCCAL:", OSCCAL ); }
while(1);
*/
//先取文件首簇号和文件大小看看
memset( &finfo, 0, sizeof(finfo) );
get_file_info( "se_m_26.wav", &finfo );
//sprintf( buf, "%u\t%lu\r\n", finfo.first_cluster, finfo.filesize );
uart_puts(buf );
//播放
uart_puts("-------------start-------------");
sei();
view_file( "face1.wav" );
// cli();
uart_puts("--------------end--------------");
//sprintf( buf, "available mem:%d\r\n\r\n", get_avail_mem() );
uart_puts( buf );
while(1);
return 0;
}
下一步的目标是改用r-2r ladder来实现16位输出。马老师的意见是用两个8位pwm按1:255分压来组成16位,不知道哪个方案更蛋疼一些?r-2r就是占用io多了点,m8一共23个io,SD卡用4个,reset一个,txd一个,凑和够了。哪天想起来了再按这个方案试试~~
0 notes
Text
总结一下一年多以来的制作
上次更新是2011年2月,快两年了。东西做了不少的,只是一直没写上来。
各种实验性质的就不提了,挑几个好玩的吧~
桌面温湿度计
ATmega48 + DS18B20 + DHT11的经典配置,简单试验了一下能工作。不过DHT11精度太差了点,跟专门的湿度计读数能相差1/3,没法用啊。。
三用手电
ATtiny26,用INT0切换控制一个白光LED、一个紫外LED和一个红色激光LED。手电/验钞笔/激光笔三合一,如图~
(图1)(图2)(图3) pictured
直流电子管电源
用一节锂电池当电源,LM2577接成flyback,输出再通过IRFR420接成线性稳压,输出60V。另一路通过1117输出1.4V。两路相互隔离。
盖革计数器
也用一只锂电供电,用两只74HC00,一只接成多谐振荡器,缓冲后推动两只Si2302,通过变压器升压到400V以上给盖革计数管供电。另一只74HC00接成单稳态电路,盖革计数管输出的脉冲整形、延时后推动LED和蜂鸣器。朋友的朋友去日本时,这东西派了一回用场。
毫欧表/高斯计/温度计
本质都一样,都是四线法测电阻,电流引线上串个精密电阻,取它两端压降作为基准电压,也就是所谓的比例式配置。当毫欧表和高斯计用时,测试电流用100mA,基准电阻取24欧;当温度计用的话,测试电流取1mA,基准电阻用2700欧。数模转换用AD7705,国产的TM7705也挺好用,测出来结果和AD7705基本一致。
(图)
车载USB充电器
以前买过一个十几块钱的点烟口充电器,用了一年左右吧,坏了。拆开一看发现做工相当差,就是34063推PMOS的结构,号称输出2.1A……于是决定自己做一个。用两套2596降压到5V,各接一个双层USB座,合起来能提供6A的电流,这回怎么也够了。再用热熔胶全部封上。
厨房定时器
很简单,倒计时15秒,时间到了就嘀嘀嘀。按一下按钮延长一分钟,最多十分钟。样子有点象定时炸弹。。。
I2CLCD
1602LCD按四线配置,用一只PCF8574驱动,这样做简单实验时只要四线就能驱动液晶屏了。再用一只7660提供负压,这样3.3V和5V都能工作了。在AVR和STM8上给它写了驱动。不过I2C还是嫌有点慢,以后再做UART和SPI方式的吧。UART可以少一条线,但是两边都得有晶振。
LED测试器
做了个简单的恒流源,专门检测LED用。用开关切换5mA和40mA两档,普通小LED和大功率LED都能测了。
磷酸铁锂充电器
用运放和两只BJT简单实现了恒流充电+恒压补充,用ATmega48对电压采样后驱动10段LED发��条作为电量指示。试了几次,还算好用。
移动电源
电池用两节2000mAh的锂聚合物并联,充电用TP4056,升压用LM2577。 用LED+BJT+PMOS实现了UVLO,不过不太准,大概放到3V多一点关断输出。输出电压按3.5V计算时,LM2577理论上输出电流是3.5V*2.1A/5V = 1.5A;实际使用时发现同时带两个手机充电时发热挺严重,充一个还行。以后用LM3478或MAX1771做个功率大点的,至少2A吧。
PCL86功放
做了个PCL86的外围小板,简单验证了一下能响,以后再慢慢优化吧。
AVRDDS
参考这两个老外的设计:http://www.myplace.nu/avr/minidds/index.htm http://codeandlife.com/2012/03/13/fast-dds-with-atmega88/ 。
做了一点改进,用四位DIP开关选择16个频点,结果莫名其妙地总是不正常,后来发现是asmloop的参数里有浮点计算,老外的程序里参数都是常量,于是浮点的问题由编译器解决了;我在���数里用了变量的结果是把浮点库编译进来了,于是ATmega48可怜的512字节RAM不够用了。改了改程序,解决了。
然后试了一下AM调制:DDS的输出经过LC滤波、2SC945缓冲放大后接天线,电脑的音频输出经过运放缓冲给2SC945供电。初步试验的结果只能说能工作了,收音机离几厘米远能收到,再远就不行了。以后还得改进。
0 notes
Text
年前的三个制作
1. CM102音箱
CM102是台湾C-Media公司的USB声卡芯片。跟著名的PCM270x相比,好处就是:便宜、有DIP封装,当然效果没法比了。电路图如下:
结果是有很大的不规则的噪声... 开始以为是VBUS直供TDA2822的原因,于是让VBUS过了1117-3.3再供TDA2822,结果仍然噪声很大;全换成用电池供电,仍然噪声很大;干脆断开TDA2822,把耳机接到CM102的输出上,噪声没了。看样子是买到山寨2822了,下次用TEA2025重做吧,或者直接改用LM4890。
ps. C-Media的网站怎么可以这么2呢。。手里CM102的datasheet旧了,而且几个图都巨模糊,想找个新的看看,上CM官网一找,倒是有,但是不支持google浏览器;换ie,发现让注册用户;注册了用户,下载了datasheet一看,几个图还是模糊的。这家的东西似乎卖得还不错,比如当年的CMI8738。
2. 继续进行NE555 boost和flyback实验
之前试过用NE555推MTD3055,5V升6.3V的实验,效果很好,输出1A以上电流,效率在80%到90%之间。这次的电路图基本相同,打算升压到125V左右,再经过后面的线性稳压,得到90V左右的稳定电压。结果不太理想,5V输入时闭环只能升到85V左右,12V输入时可以达到130V,效率50%~60%。加大负载则效率迅速跌到30%。从5V逐渐降低输入电压,降到3.3V时仍能工作,但带负载时(3W节能灯)不能从3.3V启动工作。把振荡频率从25kHz提高到50kHz,效率提高到接近70%,但没有根本的改善。再就是变压器的吱吱声实在是太烦人了。
下次的实验目标:
1) 改用低Rds(on)的IRF640S代替IRFR420,仍用boost方式,看能不能稳定实现5V升到110V左右。boost没有噪音的优势还是很明显的。
2) 继续绕变压器,实现升压到400V,同时也试试用74HC04、晶体管自激之类实现升压的可能性。
3. 流水灯
ourdev的马潮老师出了个题目:8x8的LED屏,中间四个常亮,最外圈亮一个灯转圈跑。说实话没啥难度,一伙人讨论得煞有介事。似乎马潮那边的学生衰了点,作为专业搞电子的学生,俩小时搞不出来的都有。我正好闲着就焊了块板,从开始写程序开始,39分钟搞定。
中间一北大的师弟把马潮老师惹毛了,于是这老师又出了个题,当joke看吧:
"如果不服,可以再次比试。你在北大找5个学生,组成一个小组。 用m16加一片lm324,设计一个读取sd卡上wave文件,并播放的wave播放器,看谁做的好。 给你们一个月的时间,下个学期开学我到北大找你,比试实物效果。 "
在我这个外行看来也就是一个人几天或者一两天的工作量,至于让五个北大学生搞一个月么。。。 从北大找五个最衰的还有可能
0 notes
Text
惊魂一幕
去年给我的白光换了花线,因为花线不怕烫。
本来应该另找一个插头接上的,当时图省事,直接把原来的插头连一小段线剪下来,跟花线拧上,用胶布包了完事。大概插拔次数多了,胶布松了,今天再次插往墙上插座的一瞬间,火花一闪,家里灯全黑了……
合了闸一看,只剩下半截插头留在插座上,几个手指全黑了。
0 notes
Text
又试了一下用NE555做boost
电路如图
555搭成多谐振荡器推动MOSFET,用C1815当作比较器,输入5V,输出6.3V左右,试着点了几个电子管的灯丝。
结果如下:
输出电压(V)标称电流(A)输出电流(A)输入电流(A) 效率空载6.76 6U1 6.200.300.320.4686%6N26.190.340.330.4885%6F26.170.450.430.6187%6P16.150.500.500.7384%6N16.120.600.610.8984%6P156.050.760.751.1182%6F36.020.900.921.4079%
素质相当高了,比34063强不少。以前用34063点6N3的灯丝,也是从5V升6.3V,效率只有60%多的样子。
0 notes
Text
USB18B20
用ATMEGA8+DS18B20做了个USB接口的温度计,插上电脑就能显示室内温度 :)
体积和一般的U盘差不多大, 那个黑色的和三极管一样的东西就是DS18B20了~
0 notes
Text
高斯计
搞了一个Lakeshore的六位半霍尔探头,用LM385基准源+TL061+S8050搭了个简易100mA恒流源。
本来打算用tiny26的差分ADC采样,结果发现这个伪差分只能正不能负,而且20X增益在输入几个毫伏时不工作, 只好上AD623放大然后进单端ADC了。
量程3T, 分辨率大概几十G吧
0 notes
Text
验钞笔
拆了一支圆珠笔,粗细正好能装下一节7号锂电,利用原来的弹簧当触点。
笔尖的位置装了一个紫外LED, 串27欧电阻限流。
0 notes
Text
今天的试验成果
1. 改造AM中周
FCZ的许多无线电制作资料上都用了他们自制的线圈,这些线圈估计是很难买到的。幸好查到了它们的绕制数据:
型号频率(MHz)谐振电容(pF)电感(μH)空载Q值4~6脚匝数3~1脚匝数3~2脚匝数FCZ3.53.52209.47072010FCZ771204.6805147FCZ1414701.85754126FCZ2121401.45953105FCZ2828301.190384FCZ5050150.68100263
其中谐振电容接在1和3脚之间, 2是抽头。4和6是次级。
从图上看,结构和中周是一样的,正好手里还有几个AM中周,于是决定先改一个7MHz的试试。
手里只有82p和330p的电容,这样如果用82p的电容谐振在7MHz左右的话,电感量应该是6uH,相应的匝数是16T左右。
改好用LC表测了一下,差不多是6uH。
前段时间买了MC1648,接上改好的线圈,配82p电容,接上频率计。磁芯全部旋进时是6.7MHz左右,全部旋出是7.6MHz左右,差不多。
其他规格的估计也可以照样改绕,不过AM中周的磁芯可能不合适了,可以找FM中周和电视中周试试。
2. MC1648+1SV149 VCO
以前搭过Colpitts和Hartley式的VCO,但是频率覆盖总是只有2倍,可能的原因是1SV149只能部分接入LC槽路,接入多了反馈就少。MC1648是负阻振荡器,在这一点上不受限制。
把82p电容换成1SV149,再试,还是只能从2.7MHz调到5.1MHz。
检查了一下各点的电压情况,原来是MC1648的槽路有+1.5V左右的偏压,这样在5V供电时1SV149只有3.5V的电压区间可以利用了,反向电压1V以下不算的话,只有2.5V了,频率覆盖不够也算正常。
于是接上辅助电源,可以从2.7MHz调到11.9MHz了,但是1SV149的反向电压才6.5V。反向电压1V时的频率是3.3MHz左右,频率覆盖有3倍多,还是不能算满意。
检查了一下电路没有问题,看来是频率计到上限了。于是把线圈的磁芯全部旋进,这样可以从2.0MHz调到9.6MHz,反向电压1V时的频率是2.7MHz,差不多也还是3.5倍的频率覆盖,估计勉强能做到从455kHz到1600kHz了。
3. 车载充电器
用LM2596T的标准电路搭了一个。因为听说有人的比亚迪F3的点烟器座里面居然把正负极接反了,充电器一插上就冒烟,于是保险起见在2596的前面加了个桥。
整流二极管用B540C,电感是在20mm磁环上绕了5T,用LC表测了一下有40多uH,够用了。
负载电阻用5.1欧 1/2瓦电阻。这个电阻功率明显不够,于是用长线把它接出来放进水盆里,应该安全了。
一个负载电阻时,输出电压5.00V,电流0.98A,输入电压12.0V,电流0.55A。
两个电阻时输出5.00V 1.96A,输入电流达到了1.12A。测了一下2596输入端的电压居然只有10V多一点了,看来桥还是挺影响效率的,以后得换个肖特基桥。
按说2596的最大输出电流能达到3A,但是不知道为什么,三个电阻时电路就保护了,试了几次都一样。幸好2A也够用了。
0 notes
Text
买车21天总结
行程:670公里 油耗:一开始加了100元的油也就是15升,跑了50公里,平均每公里30升 第二次加了200元/30升,220公里,平均每公里13.6升 第三次加了330元/50升,350公里,平均每公里14.3升 油耗反而增加的原因估计是,第一次的油用完以后没注意提示,发现要加油的时候,估计油箱快见底了。第二次就很老实地看到“燃油不足”的提示就去加油了。 第四次也加了50升,到现在跑了50多公里吧,提示还能开460公里。希望这次能降到13个以内吧。 中间某一天晚上,左后轮莫名其妙地扎了个螺钉,请路过的出租车师傅换了备胎。4S店说如果破得厉害,买新胎要近千元,而且轮胎玻璃算耗材,不包括在保险里,被吓了一跳。好在第二天在路边小店花50元补好了。
0 notes
Text
34063扩流实验的一些结果
34063我们知道,它做buck的效率是相当低的,手册上给出的83.7%的效率是在输入25V、输出5V的条件下测到的,以前我自己实验的结果是,输入12V、输出6V左右时效率只有60%多,比线性稳压高不了多少。因为是用达林顿管接成OC或OE开关,没法直接驱动外接MOSFET。
fdisk手里的一个路由器板,3.3V供电是从5V buck降压得到的,而且居然是用的34063。5V降到3.3V如果用的是LDO,那么效率就是66%,可见这里效率一定远比66%高;于是和fdisk、sunzx一起把这部分电路抄了下来。基本原理如图:34063内部开关管导通时,Q1关断,PFET栅极通过二极管D1被拉低导通;34063内部开关管关断时,Q1导通,PFET栅极拉高关断。从而实现了利用外置MOSFET扩流。sunzx紧接着找到一个类似原理的boost升压电路,换成了PNP管和NFET。
图1 34063外扩MOS管buck和boost电路
照这两个电路接了一下,buck电路使用2SC945和MTD2955,结果是输入5V 0.24A, 输出3.2V 0.29A, 效率大约77%;boost电路使用2SA733和MTD3055,12V升29V效率只有52%了,输入电压5V时则不能工作;换用导通电压很低的IRLML2502,还是不能工作,从示波器上看栅极波形,根本不能关断。两个电路的结果都不理想。
大概分析了一下:主要的问题应该在MTD2955和3055这两个管子上。在VGS=10V时,两者的RDS(on)分别是0.23Ω和0.18Ω,相比之下,fdisk路由器板上使用的MMSF7P03,RDS(on)只有35mΩ。这个buck电路改用低导通电阻的管子应该会好些。至于boost电路,在输入电压较低时,34063内部开关管和二极管D4上的压降使得MTD3055还不能完全导通;换用IRLML2502之后,它的导通电压低了,但是不能饱和导通的Q4使得IRLML2502没法关断。因此这个boost电路在输入电压较低(3.3V到5V)时不能用,而输入电压再高些的时候则有性能高得多的UC3843可用,看来它的实用价值不大了。
下一步考虑换个低导通电阻的MOSFET比如AO4419,再试一下buck电路的性能,应该还是有潜力的。
0 notes
Text
土绕线机
本来是个PWM调电机转速的板子, 做多了几块, 于是改造成用M48的INT0口数圈数了, 在电机接轴器上粘了一块磁铁, 用A3144检测 电机是300转的减速电机 按一下转100圈, 另一个键是10圈 用来绕变压器很方便 ~
0 notes
Text
频率计
电路如图
输入信号经K246共源缓冲,直耦到C1959放大, 74HC04整形后通过另一只作为���门的C1959,由74HC393和Mega8的T1计数器一起计数。理论能测到224=16.777216MHz。
用CD4060接4M晶振搭了个信号源,测试结果如图:
-----------------------------------------------------------------------------------------------------------
0 notes