AVR普通IO端口实现非接触式电容触摸感应试验成功
说到电容非接触摸技术相信大家并不陌生......前几天在书城看到匠人的手记.....里面看到这样一个描述用普通IO口加一个电阻实现电容感应的方案...只是大概描述..回来后经过自己分析...由于人体就是导体,通过大地回路形成一个很小的电容.在人体接近感应区域时,人体电容和IO口内部的电容并联,可以通过RC充电方式测量出这个电容,在人体没有接近时,只有IO口内部电容,通过软件处理后可识别是否有人体接近... 由于电容很小,所以电阻要很大才行,现在这里用20M的电阻.......
经过软件仿真.电压5V 电阻20M 测得
电容 = 1P充电时间大约为 20US
电容 = 5P充电时间大约为100US
电容 = 10P 充电时间大约为200US
电容 = 25P 充电时间大约为 1750US
那就费话少说.....直接上图...上源代码.....
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_376353.jpg
(原文件名:电容感应1.jpg)
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_376354.JPG
(原文件名:电容感应2.JPG)
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_376355.JPG
(原文件名:电容感应3.JPG)
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_376356.JPG
(原文件名:电容感应4.JPG)
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_376357.JPG
(原文件名:电容感应5.JPG)
//引用文件***********************************************************
#include<iom8v.h>
#include<macros.h>
//输出定义***********************************************************
#define Led1On PORTD |= (1 << 7) //输出指示
#define Led1Off PORTD &= ~(1 << 7) //关闭指示
//*******************************************************************
//函数名字; Delay1Ms();
//输入参数; 无
//输出参数; 无
//功能描述; 延时1 毫秒
//建造日期; 2008年08月09日
//*******************************************************************
void Delay1Ms(void) //毫秒延时
{
unsigned int i;
for (i = 0; i < 140; i++); //
}
//*******************************************************************
//函数名字; DelayNms(n);
//输入参数; 延时周期参数据
//输出参数; 无
//功能描述; 延时程序
//建造日期; 2008年08月09日
//*******************************************************************
void DelayNms(unsigned int n) //延时周期
{
unsigned int i;
for (i = 0; i < n; i++)
{
Delay1Ms(); //毫秒延时
}
}
//*******************************************************************
//函数名字; PortInit();
//输入参数; 无
//输出参数; 无
//功能描述; 脚位设置
//建造日期;2008年08月09日
//*******************************************************************
void PortInit(void)
{
PORTB = 0xff; //控制输出
DDRB= 0x07;
PORTC = 0x6f; //上拉输入
DDRC= 0x08;
PORTD = 0x00; //控制输出
DDRD= 0xff;
}
//*******************************************************************
//函数名字; DischargeOut();
//输入参数; 无
//输出参数; 无
//功能描述; 电容放电
//建造日期; 2008年08月09日
//*******************************************************************
void DischargeOut(void)
{
PORTC |= (1 << 4); //置高电平
DDRC|= (1 << 4); //开始放电
DelayNms(1); //放电时间
}
//*******************************************************************
//函数名字; SurveyRc();
//输入参数; 无
//输出参数; 无
//功能描述; 测量充电时间
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char SurveyRc(void)
{
unsigned char time = 0; //时间计数
DischargeOut(); //电容放电
DDRC&= ~(1 << 4); //输入设置
PORTC &= ~(1 << 4); //高阻输入
while (PINC & (1 << 4)) //充电计时
{
time++; //计时增加
asm("nop"); //精确10us
if (time > 250) break; //最大限时
}
return time; //返回时间
}
//*******************************************************************
//函数名字; DataAdd(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据总和
//功能描述; 缓冲区所有数据相加
//建造日期; 2008年08月09日
//*******************************************************************
unsigned int DataAdd(unsigned char *buffer, unsigned char size)
{
unsigned int add;
unsigned char i;
add = 0; //数据清零
for (i = 0; i < size; i++)
{
add += buffer; //数据相加
}
return add; //返回总和
}
//*******************************************************************
//函数名字; DataMax(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据最大值
//功能描述; 选出缓冲区最大值
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char DataMax(unsigned char *buffer, unsigned char size)
{
unsigned char max, i;
max = buffer; //假设最大
for (i = 1; i < size; i++)
{
if (max < buffer) max = buffer; //对比最大
}
return max; //最大数据
}
//*******************************************************************
//函数名字; DataMin(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据最小大值
//功能描述; 选出缓冲区最小值
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char DataMin(unsigned char *buffer, unsigned char size)
{
unsigned char min, i;
min = buffer; //假设最小
for (i = 1; i < size; i++)
{
if (min > buffer) min = buffer; //对比最小
}
return min; //最小数据
}
//*******************************************************************
//函数名字; DataEqually(idend, isor);
//输入参数; 被除数,除数
//输出参数; 平均值
//功能描述; 数据平均
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char DataEqually(unsigned int idend, unsigned char isor)
{
return (idend / isor); //数据平均
}
//*******************************************************************
//函数名字; FilterData();
//输入参数; 无
//输出参数; 平均值
//功能描述; 取样平均滤波
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char FilterData(void)
{
unsigned char i, max, min, data;
unsigned int sum;
for (i = 0; i < 10; i++)
{
data = SurveyRc(); //收集数据
}
sum = DataAdd(data, 10); //数据相加
max = DataMax(data, 10); //取最大值
min = DataMin(data, 10); //取最小值
return (DataEqually((sum - max - min), 8)); //取平均值
}
//*******************************************************************
//函数名字; main();
//输入参数; 无
//输出参数; 无
//功能描述; 主程序
//建造日期; 2008年08月09日
//*******************************************************************
void main(void)
{
unsigned char temp = 0; //上电校准
unsigned char time = 0;
PortInit(); //端口设置
temp = FilterData(); //读取误差
while (1)
{
time = FilterData(); //读取时间
if (time > temp)
{
Led1On; //输出指示
}
else
{
Led1Off; //关闭指示
}
}
} 点击此处下载 ourdev_376373.rar(文件大小:257K) (原文件名:电容感应.rar) 单片机AVR M8 使用内部1M RC振荡.
现可以感应到2MM厚的洞洞板,由于没有防止临界状态处理程序.在临界状态LED输出闪烁... 太牛了,不知道可靠性和一致性怎么样 需要考虑感应灵敏度可调才有实际应用价值 一至性好的话,做键盘很有前途的 不错的尝试,我们公司有用到PSOC来做过触摸按键 现在只是试验成功,要想产品上用.还要经过一些防误处理,自动校准处理,灵敏调节处理,临界状态处理.....看看大家在这方面处理的算法有什么好的建议或方法.....请多多指教... 很容易玩坏IO口……而且完全无法抵御蓄意破坏,过脉冲群测试更是做梦都不要想…… 楼上的,如果有新的技术出现都不去尝试一下.怎么去发现它的缺点并改进它,这样技术怎么会有进步呢.
现在AVR原产也正在试验这种新技术,PIC产家也在设想在为单片机加入这一功能.....很有可能有些型号的单片机以后就有这种模块功能....很有可能会取代按键开关.....这东东很有前途....... 标记,以后再仔细看。 是的,也许很多IC厂家正在尝试把这个功能加入MCU,但是人家是建立在给IO口内部电路额外增加足够的保护功能的前提之上的
而你的电路……不得不说,绝对是缺点大于优点,实际产品中如果敢这么用,保证三个月后要求退货的顾客踏破你公司的门槛……
但如果你要在自己的电路上也增加足够的保护功能……我可以确定那东西做出来不会比普通薄膜开关便宜的…… 标记,谢谢 顶! 不错,偶试试~ atmel和quantum合作,电容触控IC已经量产了,有单键,两键...24键,48键等.用得就是AVR 不得不说现在这些现成的东西很多了呢。ATMEL,CYPRESS都有,国内好像也有现成产品了。 liuxj 军哥:
atmel和quantum合作,电容触控IC已经量产了,有单键,两键...24键,48键等.用得就是AVR
应该说是ATMEL把QUANTUM收购了。CYPRESS的CAPSENSE也比较有特色,感兴趣可以玩玩,做开关不错。 学习。 最新改进型电容感应电图:
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_377293.jpg
(原文件名:改进型电容感应.jpg) 最新改进型源源程序代码....加入防误处理....实现按键功能....每按一下,LED输出指示取反一次...
AVR M8 内部1MRC振荡
//引用文件***********************************************************
#include<iom8v.h>
#include<macros.h>
//输出定义***********************************************************
#define Led1On PORTD |= (1 << 7) //输出指示
#define Led1Off PORTD &= ~(1 << 7) //关闭指示
//*******************************************************************
//函数名字; Delay1Ms();
//输入参数; 无
//输出参数; 无
//功能描述; 延时1 毫秒
//建造日期; 2008年08月09日
//*******************************************************************
void Delay1Ms(void) //毫秒延时
{
unsigned int i;
for (i = 0; i < 140; i++); //
}
//*******************************************************************
//函数名字; DelayNms(n);
//输入参数; 延时周期参数据
//输出参数; 无
//功能描述; 延时程序
//建造日期; 2008年08月09日
//*******************************************************************
void DelayNms(unsigned int n) //延时周期
{
unsigned int i;
for (i = 0; i < n; i++)
{
Delay1Ms(); //毫秒延时
}
}
//*******************************************************************
//函数名字; PortInit();
//输入参数; 无
//输出参数; 无
//功能描述; 脚位设置
//建造日期;2008年08月09日
//*******************************************************************
void PortInit(void)
{
PORTB = 0xff; //控制输出
DDRB= 0x07;
PORTC = 0x6f; //上拉输入
DDRC= 0x08;
PORTD = 0x00; //控制输出
DDRD= 0xff;
}
//*******************************************************************
//函数名字; DischargeOut();
//输入参数; 无
//输出参数; 无
//功能描述; 电容放电
//建造日期; 2008年08月09日
//*******************************************************************
void DischargeOut(void)
{
PORTC |= (1 << 4); //置高电平
DDRC|= (1 << 4); //开始放电
DelayNms(1); //放电时间
}
//*******************************************************************
//函数名字; SurveyRc();
//输入参数; 无
//输出参数; 无
//功能描述; 测量充电时间
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char SurveyRc(void)
{
unsigned char time = 0; //时间计数
DischargeOut(); //电容放电
DDRC&= ~(1 << 4); //输入设置
PORTC &= ~(1 << 4); //高阻输入
while (PINC & (1 << 4)) //充电计时
{
time++; //计时增加
asm("nop"); //精确10us
if (time > 250) break; //最大限时
}
return time; //返回时间
}
//*******************************************************************
//函数名字; DataAdd(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据总和
//功能描述; 缓冲区所有数据相加
//建造日期; 2008年08月09日
//*******************************************************************
unsigned int DataAdd(unsigned char *buffer, unsigned char size)
{
unsigned int add;
unsigned char i;
add = 0; //数据清零
for (i = 0; i < size; i++)
{
add += buffer; //数据相加
}
return add; //返回总和
}
//*******************************************************************
//函数名字; DataMax(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据最大值
//功能描述; 选出缓冲区最大值
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char DataMax(unsigned char *buffer, unsigned char size)
{
unsigned char max, i;
max = buffer; //假设最大
for (i = 1; i < size; i++)
{
if (max < buffer) max = buffer; //对比最大
}
return max; //最大数据
}
//*******************************************************************
//函数名字; DataMin(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据最小大值
//功能描述; 选出缓冲区最小值
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char DataMin(unsigned char *buffer, unsigned char size)
{
unsigned char min, i;
min = buffer; //假设最小
for (i = 1; i < size; i++)
{
if (min > buffer) min = buffer; //对比最小
}
return min; //最小数据
}
//*******************************************************************
//函数名字; DataEqually(idend, isor);
//输入参数; 被除数,除数
//输出参数; 平均值
//功能描述; 数据平均
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char DataEqually(unsigned int idend, unsigned char isor)
{
return (idend / isor); //数据平均
}
//*******************************************************************
//函数名字; FilterData();
//输入参数; 无
//输出参数; 平均值
//功能描述; 取样平均滤波
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char FilterData(void)
{
unsigned char i, max, min, data;
unsigned int sum;
for (i = 0; i < 5; i++)
{
data = SurveyRc(); //收集数据
}
sum = DataAdd(data, 5); //数据相加
max = DataMax(data, 5); //取最大值
min = DataMin(data, 5); //取最小值
return (DataEqually((sum - max - min), 3)); //取平均值
}
//*******************************************************************
//函数名字; KeyCheck(adjust);
//输入参数; 校准数据
//输出参数; 有效标置
//功能描述; 检测按键是否有效
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char KeyCheck(unsigned char adjust)
{
if (FilterData() > adjust)
{
Led1On; //
return 1; //有效按键
}
else
{
Led1Off; //
return 0; //无效按键
}
}
//*******************************************************************
//函数名字; KeyState(adjust);
//输入参数; 校准数据
//输出参数; 无
//功能描述; 按键处理
//建造日期; 2008年08月09日
//*******************************************************************
void KeyState(unsigned char adjust)
{
static unsigned char count = 0; //限时记数
static unsigned char valid = 0; //有效标志
static unsigned char reach = 0; //长按标志
if (valid == 1) //是否有效
{
if (KeyCheck(adjust)) //扫描按键
{
if (reach == 0) //长按无效
{
if (++count > 5) //防误处理
{
reach = 1; //长按置位
PORTD ^= (1 << 6); //取反输出
}
}
}
else
{
valid = 0; //有效清零
reach = 0; //长按清零
count = 0; //记数清零
}
}
else if (KeyCheck(adjust)) valid = 1; //有效置位
}
//*******************************************************************
//函数名字; main();
//输入参数; 无
//输出参数; 无
//功能描述; 主程序
//建造日期; 2008年08月09日
//*******************************************************************
void main(void)
{
unsigned char adjust; //上电校准
PortInit(); //端口设置
adjust = FilterData(); //读取误差
while (1)
{
KeyState(adjust); //按键处理
DelayNms(5); //定时扫描
}
}
//*******************************************************************
//函数名字;
//输入参数;
//输出参数;
//功能描述;
//建造日期; 2008年08月09日
//******************************************************************* 点击此处下载 ourdev_377313.rar(文件大小:28K) (原文件名:电容触摸感应.rar) 强,不顶不行。
理论联系实际 还是有价值的 记号 估计这个也是普通单片机实现的吧,有可能是类似em78p156的单片机。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_377453.jpg
tf745 (原文件名:tt.jpg) 4148一样过不了脉冲群……
用P6KE系列还差不多…… 好久没来这逛了,出来透透气 刚刚又对程序进行了优化.....改进电容放电时间.....按键按下.....按键释放....都加入防止处理.....实用性大大增强....
现在就差温度漂移及其它因素导致的漂移.....不知哪位高手有这方面的算法... 顶一下,楼主的触摸距离有多少?以前做过实验,采用1M电阻上拉端口方式,距离1cm左右,干扰比较大,触点和端口不能接太长的线。有时间试试楼主的电路。 做个记号 新鲜,顶下 帮楼主改一下程序注释:
---------------
//*******************************************************************
//函数名字; DischargeOut();
//输入参数; 无
//输出参数; 无
//功能描述; 电容放电
//建造日期; 2008年08月09日
//*******************************************************************
void DischargeOut(void)
{
PORTC |= (1 << 4); //置高电平
DDRC|= (1 << 4); //开始放电 改为:开始充电
DelayNms(1); //放电时间 改为:充电延时
}
//*******************************************************************
//函数名字; SurveyRc();
//输入参数; 无
//输出参数; 无
//功能描述; 测量充电时间
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char SurveyRc(void)
{
unsigned char time = 0; //时间计数
DischargeOut(); //电容放电 改为:对电容充电
DDRC&= ~(1 << 4); //输入设置
PORTC &= ~(1 << 4); //高阻输入 断开内部上拉电阻
while (PINC & (1 << 4)) //充电计时 改为:放电计时,判断PC_4从1到0的时间
{
time++; //计时增加
asm("nop"); //精确10us
if (time > 250) break; //最大限时
}
return time; //返回时间
} 弱弱的问:所谓的人体电容的充电回路是怎样的?
如此高的输入阻抗,EMC恐怕很难过的吧。
有空试试他的抗干扰能力 不錯 不错,学习了 一样做的话,可能用STC好一点,因为STC的I/O脚是自带ESD保护的。 最最新版软件......
对按键按下,释放的时间进行优化,响应时间更快,在试验时没有出现误动作.......在连续2S没有检测到按键,就自动更新校准参数...实现自动跟踪漂移...在宽电压范围内都可正常工作....欢迎大家进行公测试验.....提供改进建议...
下一步要实现灵敏度可调节...
//引用文件***********************************************************
#include<iom8v.h>
#include<macros.h>
//公用变量***********************************************************
unsigned char follow; //跟踪校准
//*******************************************************************
//函数名字; Delay1Ms();
//输入参数; 无
//输出参数; 无
//功能描述; 延时1 毫秒
//建造日期; 2008年08月14日
//*******************************************************************
void Delay1Ms(void) //毫秒延时
{
unsigned int i;
for (i = 0; i < 140; i++); //
}
//*******************************************************************
//函数名字; DelayNms(n);
//输入参数; 延时周期参数据
//输出参数; 无
//功能描述; 延时程序
//建造日期; 2008年08月14日
//*******************************************************************
void DelayNms(unsigned int n) //延时周期
{
unsigned int i;
for (i = 0; i < n; i++)
{
Delay1Ms(); //毫秒延时
}
}
//*******************************************************************
//函数名字; PortInit();
//输入参数; 无
//输出参数; 无
//功能描述; 脚位设置
//建造日期;2008年08月14日
//*******************************************************************
void PortInit(void)
{
PORTB = 0xff; //控制输出
DDRB= 0x07;
PORTC = 0x6f; //上拉输入
DDRC= 0x08;
PORTD = 0x00; //控制输出
DDRD= 0xff;
}
//*******************************************************************
//函数名字; DischargeOut();
//输入参数; 无
//输出参数; 无
//功能描述; 电容放电
//建造日期; 2008年08月14日
//*******************************************************************
void DischargeOut(void)
{
PORTC |= (1 << 4); //置高电平
DDRC|= (1 << 4); //开始放电
asm("nop"); //放电时间
asm("nop"); //精确 5uS
asm("nop");
asm("nop");
asm("nop");
}
//*******************************************************************
//函数名字; SurveyRc();
//输入参数; 无
//输出参数; 无
//功能描述; 测量充电时间
//建造日期; 2008年08月14日
//*******************************************************************
unsigned char SurveyRc(void)
{
unsigned char time = 0; //时间计数
DischargeOut(); //电容放电
DDRC&= ~(1 << 4); //输入设置
PORTC &= ~(1 << 4); //高阻输入
while (PINC & (1 << 4)) //充电计时
{
time++; //计时增加
asm("nop"); //精确10uS
if (time > 250) break; //最大限时
}
return time; //返回时间
}
//*******************************************************************
//函数名字; DataAdd(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据总和
//功能描述; 缓冲区所有数据相加
//建造日期; 2008年08月14日
//*******************************************************************
unsigned int DataAdd(unsigned char *buffer, unsigned char size)
{
unsigned int add;
unsigned char i;
add = 0; //数据清零
for (i = 0; i < size; i++)
{
add += buffer; //数据相加
}
return add; //返回总和
}
//*******************************************************************
//函数名字; DataMax(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据最大值
//功能描述; 选出缓冲区最大值
//建造日期; 2008年08月14日
//*******************************************************************
unsigned char DataMax(unsigned char *buffer, unsigned char size)
{
unsigned char max, i;
max = buffer; //假设最大
for (i = 1; i < size; i++)
{
if (max < buffer) max = buffer; //对比最大
}
return max; //最大数据
}
//*******************************************************************
//函数名字; DataMin(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据最小大值
//功能描述; 选出缓冲区最小值
//建造日期; 2008年08月14日
//*******************************************************************
unsigned char DataMin(unsigned char *buffer, unsigned char size)
{
unsigned char min, i;
min = buffer; //假设最小
for (i = 1; i < size; i++)
{
if (min > buffer) min = buffer; //对比最小
}
return min; //最小数据
}
//*******************************************************************
//函数名字; DataEqually(idend, isor);
//输入参数; 被除数,除数
//输出参数; 平均值
//功能描述; 数据平均
//建造日期; 2008年08月14日
//*******************************************************************
unsigned char DataEqually(unsigned int idend, unsigned char isor)
{
return (idend / isor); //数据平均
}
//*******************************************************************
//函数名字; FilterData();
//输入参数; 无
//输出参数; 平均值
//功能描述; 取样平均滤波
//建造日期; 2008年08月14日
//*******************************************************************
unsigned char FilterData(void)
{
unsigned char i, max, min, data;
unsigned int sum;
for (i = 0; i < 5; i++)
{
data = SurveyRc(); //收集数据
}
sum = DataAdd(data, 5); //数据相加
max = DataMax(data, 5); //取最大值
min = DataMin(data, 5); //取最小值
return (DataEqually((sum - max - min), 3)); //取平均值
}
//*******************************************************************
//函数名字; KeyState();
//输入参数; 无
//输出参数; 无
//功能描述; 按键处理
//建造日期; 2008年08月14日
//*******************************************************************
void KeyState(void)
{
static unsigned char release = 0; //释放记数
static unsigned char count = 0; //按下记数
static unsigned char valid = 0; //有效标志
static unsigned char reach = 0; //长按标志
static unsigned inttrail = 0; //跟踪记数
if (valid == 1) //是否有效
{
if (FilterData() > follow) //按键按下
{
release = 0; //释放清零
if (reach == 0) //长按无效
{
if (++count > 2) //防误处理
{
reach = 1; //长按置位
PORTD ^= (1 << 7); //取反输出
}
}
}
else if (++release > 2) //释放记数
{
valid = 0; //有效清零
reach = 0; //长按清零
count = 0; //记数清零
}
}
else
{
if (FilterData() > follow)
{
trail = 0; //数据清零
valid = 1; //有效置位
}
else
{
if (++trail > 400) //漂移跟踪
{
follow = FilterData(); //更新误差
PORTD ^= (1 <<6); //跟踪指示
trail = 0; //数据清零
}
}
}
}
//*******************************************************************
//函数名字; main();
//输入参数; 无
//输出参数; 无
//功能描述; 主程序
//建造日期; 2008年08月14日
//*******************************************************************
void main(void)
{
PortInit(); //端口设置
follow = FilterData(); //读取误差
while (1)
{
KeyState(); //按键处理
DelayNms(5); //定时扫描
}
}
//*******************************************************************
//函数名字;
//输入参数;
//输出参数;
//功能描述;
//建造日期; 2008年08月14日
//******************************************************************* C8051F系列的某一款 内置了触摸按键接口的 可以查一下 阿莫....应该给裤子了吧........呵呵..... 楼主是人才,应该给条内裤穿 cy也有的 用过 不错 该程序成功移值到PIC16F84A 上成功运行.....效果更佳.....
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=1400964&bbs_page_no=1&bbs_id=1028
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_378513.jpg
(原文件名:电容触摸感应.jpg)
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_378514.JPG
(原文件名:电容触摸感应1.JPG)
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_378515.JPG
(原文件名:电容触摸感应2.JPG)
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_378516.JPG
(原文件名:电容触摸感应3.JPG) 记号 楼主的代码注释还是错误的,看来楼主还是没有完全弄明白它的原理,采用上拉是检测结电容+人体电容的充电时间,采用下拉是检测结电容+人体电容的放电时间,这样的代码要是给“酷”那就是对初学者的误导。 ti的430也有类似的演示板 原理是检测上拉结电容和人体电容......要是理论分析不对,又怎么做得来出呢........
IO输出高电平,短路电容.....这不是放电吗......那又是什么.......
PORTC |= (1 << 4); //置高电平
DDRC|= (1 << 4); //开始放电
IO高阻输入...电容充电...程短路现象...这时检测高电平....并记录充电时间.....
DDRC&= ~(1 << 4); //输入设置
PORTC &= ~(1 << 4); //高阻输入
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_378633.JPG
(原文件名:仿真模型1.JPG)
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_378634.JPG
(原文件名:仿真模型2.JPG) 感应距离可以到多厚?
比如,5毫米的玻璃板可以吗? 哈哈,关于充电还是放电的问题,其实是一样的,LZ的电容参考点是VCC,而44楼的参考点是GND,还是我问的问题,充电或放电的回路是什么呢?
如果没有回路,怎么充呢?比如象44楼那样说的话,假使GND是接大地的,那么就有了充电回路。LZ的意思是人体是等同接到VCC上的,于是有了充电回路,那么LZ的电路中到底是哪个接的大地呢?如果没用接,而是高度绝缘的,那么就是通过空气的,如果空气够大的湿度的话也可以理解。如果用开关电源供电是一个说法,用变压器又是一个,用初次级隔离骨架作的变压器又是一个。 刚才试了一下,2MM PCB + 5MM 亚克历有机玻璃,可以感应得到...只是灵敏度低了一点点...可以通过加大焊盘的面积来提高灵敏度.... 【48楼】 xiaobendan 仲跻东
够细心...对于回路问题.....
1,开关电源供电
我在刚开始试验时用的是开关电源供电,电路通过在线下载编程器,经过USB 连到电脑....刚开始试的时候..灵敏度比较高...当断开下载线时..灵敏度下降...LED不停闪动.....按键失效....经过分析..是电脑的开关电源通过一个小电容联到了地线....此时不是感应不到人体,只是回路发生了变化..灵敏度变弱了..经过调整软件,加入自动跟踪漂移自动校准后...此问题现以解决...
2,对于次级隔离骨架作的变压器
昨晚我用可调电源进行了试验....该电源用的是次级隔离骨架作的变压器,进行了测试...可以正常工作.....
对于这个问题今晚我再用 1:1 的公频变压器试验....看看有什么结果... 所以我说..欢迎大家进行公测试验.....提供改进建议... 至少是一种思路,虽然离实用还有距离,也很支持楼主 看了楼主的仿真电路我也明白为什么楼主能做出来了,完全是歪打正着,居然把代替人体的电容接到VCC上。
请参考人体等效模型:ourdev_379314.pdf(文件大小:86K) (原文件名:armok01123934.pdf) ivws
用电池供电能正常工作吗? 楼主这个电路应该会受到比较严重的噪声干扰,因为单片机IO做输入后输入阻抗很高,噪声会造成很大的影响
cypress的csr技术也有类似的毛病 54楼的更狠啊,哈哈!不过我的三星NV10的按键是感应的,但是好像是接触上才能感应到的,而且他的外壳是金属的,使用时又是用手拿着的,所以可能是简单的电路作的。
楼主是否测量过这个输入脚上的信号到底是什么样子的? 好。 昨晚上有 1:1 隔离变压器测试....用AVR 方案的可以用...不过漂移较大....有时自激..
用PIC方案的比较稳定...这几天要提高程序自适应算法...加强自动跟踪漂移... lz很有钻研精神,佩服。。。 看来真的用电池做的话是不行的,不过没用必要这样。因为有些家电就是要用变压器的,反正是非接触的,即使是直连到220上的也没有问题。不过还是要考虑用户的鞋子比较好,鞋底比较厚,还有地板的问题。 所以说没有振荡源的电容非接触摸是不可靠的
其实用2个三极管就可以搞定电容非接触摸,即使用电池供电也一样稳定可靠 piaoguo AVR-BIN 电子油条,你能给个电路看看吗? 不錯 Mark Mark 好贴,MARK!!! 不错,学习一下 好贴 MARK! 记号 好 学习学习,谢谢分享 之前有朋友成功试过,只加两个电阻就可以很稳定做到。并量产。能在凌阳。51中实现 记号 mark 之前听过PIC技术工程师的讲座,PIC单片机也是这样的原理 mark thanks mark 我也测试过了,确实可行,灵敏度都可以,就是抗干扰不行 是啊, 原理是可行的, 但这个方案, 抗干扰不行, 要提高抗干扰, 得换个方案. 不过, 楼主做了很有益的尝试, 能公布试验结果, 鼓励一下 mark 81楼说一下另外的方案吧 期待有更好的方案 用电池还能感应不? 有动手实践才有说话权,支持LZ,支持动手钻研 mark 标注,等到空点再细看! mark mark mark mark 做的不错!顶! 记号 mark mark mark~~~ mark