18830浏览
查看: 18830|回复: 5

[项目] DIY柔软的压力传感器,顺便试试Arduino和Processing的交互

[复制链接]
你有想过给柔软的物体增加压力感应的功能吗?
如果想的话应该要如何实现呢?
第一种办法:使用电阻式压力传感器
例如这款:https://www.dfrobot.com.cn/goods-317.html
缺点:比较贵,感应区域比较小,如果想要实现大面积的压力感应则需要好多个,那么成本就很高了。
第二种办法:使用弯曲传感器
例如这款:https://www.dfrobot.com.cn/goods-338.html
缺点:好贵

如果我想要在一个布娃娃身上实现压力感应功能,使用以上传感器的话那需要多少钱才能实现布娃娃全身的压力感应?
在下在想着这个问题时,我忽然想起来以前的一个视频:
https://v.youku.com/v_show/id_XMzU5Mjg1ODQ0.html?from=s1.8-1-1.2

懂日语的话这种时候就是方便,哈哈。这视频中采用的方法是用红外光照射棉花,然后用多个红外接收管去接收红外光反射的量。棉花在蓬松,无压力状态下内部空隙很多,红外光射入之后会在棉花内部不断反射,消耗,因此回到接收管的光很少,而在受到压缩后,棉花内部空隙减少,会有更多的光被反射回接收管。如果让多个接收管呈一定形状排布,就可以检测到有没有被压,还有被压到哪里,压力大概多大的信息。
还有一个信息源:
Fluffy FuwaFuwa Sensor Technology Opens Exciting New Possibilities

想到这一方法,我自己也DIY了一个。
材料:
洞洞板一块(或者面包板也行)
红外接收二极管(红外接收管)几个(大概3~6个即可,只能是非调制的接收管,两根引脚的那种)如下图

红外接收二极管

红外接收二极管

红外发射LED几个(大概和接收管数量一样多就行,我们不会去控制LED,所以我使用了一小段红外LED灯带)
1kΩ电阻(和接收管数量一样多)
细导线若干
可以接到Arduino板上的插针或接插件
Arduino板一块(什么型号都行,我使用了Arduino Uno R3)
USB线(用于连接Arduino和电脑)
棉花一块,不要太厚,蓬松的最好,尺寸能够覆盖到所有接收管就可以了。
电脑一台(用于显示效果和烧程序)
如果要焊接的话就需要各种焊接工具,这里我就不啰嗦了。

电路图:
以使用4个红外接收管,4个1kΩ电阻,5V红外LED灯带为例。注意红外发射部分和红外接收部分要做在两块分离的板上,不能全都焊在一块板上!
红外接收部分:(下图中有很重要的一点画错了,红外接收管在这里要反过来接!!!如果使用的是上图中的那种红外接收管,那么引脚长的一端是正极,短的一端是负极。下图中应该要把红外接收管的正极接地,负极和电阻连接。)
红外接收.PNG


红外发射部分:(我使用的是红外LED灯带,电路是一样的)
红外发射.PNG

5V电源可以直接使用Arduino板上的5V接口,这东西功耗不大。

在洞洞板或面包板上搭建好电路并与Arduino相连后,将棉花夹在红外发射和红外接收部分(红外发射部分要面向红外接收部分),硬件部分就算完成了。
像这样:
柔软压力传感器.png

你还可以尝试这样配置:
柔软压力传感器2.png

可以用Arduino的analogRead()功能读取A0~3的数值就可以体验一下压力传感器的功能了。你能够看到数值会随棉花被压缩的程度而变化。
如果希望将Arduino采集到的数据用图形来可视化,则可以使用Processing来尝试。Processing的风格和Arduino基本上很相似。
你可以到这里去下载Processing,https://processing.org/download/
我现在使用的版本是Processing 2.2

Arduino程序如下:
  1. #include <stdio.h>
  2. int IRvalue[4] = {0, 0, 0, 0};
  3. void setup() {
  4.   // put your setup code here, to run once:
  5.   Serial.begin(115200);
  6. }
  7. void loop() {
  8.   // put your main code here, to run repeatedly:
  9.   IRvalue[0] = 1024 - analogRead(A0);
  10.   IRvalue[1] = 1024 - analogRead(A1);
  11.   IRvalue[2] = 1024 - analogRead(A2);
  12.   IRvalue[3] = 1024 - analogRead(A3);
  13.   char buf[32];
  14.   sprintf(buf, "QA%dB%dC%dD%dP", IRvalue[0], IRvalue[1], IRvalue[2], IRvalue[3]);
  15.   Serial.println(buf);
  16.   delay(100);
  17. }
  18. [/mw_shl_code]Processing程序如下:
  19. [mw_shl_code=applescript,true]
  20. //-------------------------------------------------------------------------------------------------------------------------------
  21. import processing.serial.*;
  22. int IRvalue[] = new int[4];
  23. Serial myPort;
  24. String buf=""; // String buffer to store serial values
  25. void setup() {
  26.   size(800, 600);
  27.   printArray(Serial.list());
  28.   String portName = Serial.list()[0];
  29.   myPort = new Serial(this, portName, 115200);
  30. }
  31. void draw() {
  32.   background(125);
  33.   fill(255);
  34.   rect(0, 600-(IRvalue[0]/2), 200, (IRvalue[0]/2));
  35.   rect(200, 600-(IRvalue[1]/2), 200, (IRvalue[1]/2));
  36.   rect(400, 600-(IRvalue[2]/2), 200, (IRvalue[2]/2));
  37.   rect(600, 600-(IRvalue[3]/2), 200, (IRvalue[3]/2));
  38.   while (myPort.available ()>0) {
  39.     serialEvent(myPort.read());
  40.   }
  41. }
  42. void serialEvent(int serial) {
  43.   if (serial!=10&&serial!=0) {   //receive
  44.     buf += char(serial);
  45.   } else {//if serial==10
  46.     println(buf);
  47.     //extract the value from the string 'buf'
  48.     //int len1 = buf.length();
  49.     //char input[]=new char[len1];
  50.     char input = buf.charAt(0);
  51.     if (input=='Q')
  52.     {
  53.       int head=1;//start of a number, ":"
  54.       int tail=1;//end of a number, " "
  55.       String temp;
  56.       while (buf.charAt (head)!='A') {
  57.         head++;
  58.       }
  59.       tail=head;
  60.       while (buf.charAt (tail)!='B') {
  61.         tail++;
  62.       }
  63.       IRvalue[0] = int(buf.substring(head+1, tail));
  64.       while (buf.charAt (head)!='B') {
  65.         head++;
  66.       }
  67.       tail=head;
  68.       while (buf.charAt (tail)!='C') {
  69.         tail++;
  70.       }
  71.       IRvalue[1] = int(buf.substring(head+1, tail));
  72.       while (buf.charAt (head)!='C') {
  73.         head++;
  74.       }
  75.       tail=head;
  76.       while (buf.charAt (tail)!='D') {
  77.         tail++;
  78.       }
  79.       IRvalue[2] = int(buf.substring(head+1, tail));
  80.       while (buf.charAt (head)!='D') {
  81.         head++;
  82.       }
  83.       tail=head;
  84.       while (buf.charAt (tail)!='P') {
  85.         tail++;
  86.       }
  87.       IRvalue[3] = int(buf.substring(head+1, tail));
  88.     }
  89.     buf="";//clear receive buffer
  90.   }
  91. }
复制代码
测试视频:
从视频中可以看到电脑屏幕上显示的4个不同高度的长方形是Arduino的4路模拟输入采集到的数值。在我按压不同部位时4路模拟输入的数值会有不同反应。按压右边时右侧的长方形会变高;按压左边时左侧的长方形会变高。这样可以在一定程度上知道哪个部位被按压了,也可以推测被按压得多深。视频中做了3种测试,第一个测试是把红瓦发射和红外接收面对面安装,棉花夹在中间的对射式方案。第二个测试是把红外发射和红外接收靠在一起,两者之间有一定夹角,棉花放在上头的反射式方案。第三个测试是把红外发射和红外接收按对射式的方案嵌入布娃娃躯干里。


粗略的测试后发现的问题:
1.放进娃娃里面的时候最好把接收端和发射端都缝起来固定,不然容易捏着捏着里面的东西都移位了,导致采集到的数据失去规律性。
2.把棉花夹在红外发射和红外接收之间的话棉花不能太厚不然感应不到。
3.测试反射式方案时可能是红外发射和接收的夹角没调好,按压时虽然可以看到有些反应但是规律性较差,需要改进。4.棉花不够均匀时传感器之间的反应差异较大。

除此之外,你也可以试试以下方法:
1.用柔性电路板制作红外发射和接收的电路板
2.使用CD4051这种模拟开关来扩展Arduino的模拟输入,达到更大面积的压力感应
3.可以使用阵列驱动的思想,分别控制红外LED并分别检测红外接收管
4.使用贴片元件缩小体积
5.使用可见光的LED和光敏电阻达到类似效果,能够看到发光的棉花也许会有有趣的用途。
6.使用更小的微控制器
7.使用很小的红外对管
8.用海绵代替棉花
等等。。。

Jane  高级技匠

发表于 2015-8-20 18:54:06

非常棒的想法~
回复

使用道具 举报

Cain  初级技匠

发表于 2015-8-20 19:06:55

赞一个,好想法!
回复

使用道具 举报

丄帝De咗臂  高级技匠

发表于 2015-8-20 19:14:57

只能说太棒了
回复

使用道具 举报

大连林海  初级技神

发表于 2015-8-20 20:07:35

有机会要试试看
回复

使用道具 举报

Phoebe  高级技匠

发表于 2015-8-21 13:07:09

涨知识了,超实用
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2022 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail