数码之家

 找回密码
 立即注册
搜索
查看: 2428|回复: 7

[Arduino] 用LED做光敏二极管实验

[复制链接]
发表于 2020-3-22 12:15:59 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 qingkong 于 2020-3-22 12:27 编辑

光敏二极管还得买。。。这个不用单独买,而且更好找,好像也更便宜 :lol:

红色 强光下可以到1.5V左右,各种颜色的最大电压基本上就是他们的导通电压了

只是 因为电流太小,最好静止使用。。。否则 可能数值乱跳。。。。

虽然 前两天我还买了点光敏管,但是感觉这个感光范围比光敏管还要大呢“宽容度”更高一些
芯片用的是lgt8f328p 采样是12位的 (4096),如果是arduino uno 采样就是10位的 (1024)

使用了log10底拟合一下人眼曲线,感觉这个算法比较简单。。。大家还有更简单,更有效的公式么?直接带入测量的电压的话 感觉和人眼的感觉差别有点大(光敏电阻也有这个问题)


IMGP6495.JPG

EXECL用下面的公式算出来的log曲线。。。。(下面的程序还是只用了一部分曲线)

无标题.JPG

  1. /*
  2. ReadAnalogVoltage

  3. lgt8f328p读取电压 Wemos TTGO XI 8F328P-U Board
  4. */
  5. // the setup routine runs once when you press reset:
  6. #include <math.h >

  7. #include "TM1637.h"
  8. #define CLK 10//pins definitions for TM1637 and can be changed to other ports
  9. #define DIO 9
  10. TM1637 tm1637(CLK, DIO);
  11. unsigned char ClockPoint = 1;
  12. int sensorValue = 0;

  13. unsigned char hour = 0;
  14. unsigned char minute = 0;
  15. int8_t TimeDisp[] = { 0x00, 0x00, 0x00, 0x00 };

  16. void TimeUpdate(void) {
  17.         //int sensorValuesa = cbrt(sensorValue) * 100; //取立方根
  18.         int sensorValue1 = constrain(sensorValue - 0.5 * 4096 / 2.56, 850, 2500);

  19.         int sensorValuesa = log10(sensorValue1) * 1000; //以10为底的对数

  20.         int voltage = sensorValue * (2.56 / 4096.0) * 100;
  21.         int BRIGHTS = constrain(sensorValuesa, 2700, 3200);
  22.         int BRIGHT = map(BRIGHTS, 2700, 3200, 0, 7);
  23.         if (ClockPoint) {
  24.                 tm1637.point(POINT_ON);
  25.                 Serial.println(sensorValuesa / 1);
  26.                 tm1637.set(BRIGHT);
  27.                 TimeDisp[0] = sensorValuesa / 100 / 10;
  28.                 TimeDisp[1] = sensorValuesa / 100 % 10;
  29.                 TimeDisp[2] = sensorValuesa % 100 / 10;
  30.                 TimeDisp[3] = sensorValuesa % 100 % 10;
  31.         } else {
  32.                 tm1637.point(POINT_OFF);
  33.                 Serial.println(voltage / 1);
  34.                 tm1637.set(BRIGHT);
  35.                 TimeDisp[0] = voltage / 100 / 10;
  36.                 TimeDisp[1] = voltage / 100 % 10;
  37.                 TimeDisp[2] = voltage % 100 / 10;
  38.                 TimeDisp[3] = voltage % 100 % 10;
  39.         }
  40.         Serial.println(BRIGHT);
  41.         ClockPoint = !ClockPoint;
  42.         //int sensorValuesa = cbrt(sensorValue) * 100;
  43.         //TimeDisp[0,1,2,3] = sensorValuesa /  1;

  44. }

  45. void setup() {
  46.         // initialize serial communication at 9600 bits per second:
  47.         Serial.begin(9600);

  48.         tm1637.init();
  49.         tm1637.set(BRIGHT_TYPICAL); //BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;

  50.         analogReference(INTERNAL2V56); //use internal 1.1v as Avref
  51.         //analogReference(EXTERNAL); //使用外部基准

  52. //analogReference(type)
  53. //描述
  54. //配置用于模拟输入的基准电压(即输入范围的最大值)。选项有:
  55. //DEFAULT:默认5V(Ocrobot控制板为5V)或3.3伏特(Ocrobot控制板为3.3V)为基准电压。
  56. //INTERNAL:在ATmega168和ATmega328上以1.1V为基准电压,以及在ATmega8上以2.56V为基准电压(Ocrobot Mega无此选项)
  57. ////INTERNAL1V1:以1.1V为基准电压(此选项仅针对Ocrobot Mega)
  58. //INTERNAL2V56:以2.56V为基准电压(此选项仅针对Ocrobot Mega)
  59. //EXTERNAL:以AREF引脚(0至5V)的电压作为基准电压。
  60. //参数
  61. //type:使用哪种参考类型(DEFAULT, INTERNAL, INTERNAL1V1, INTERNAL2V56, INTERNAL4V096 或者 EXTERNAL)。
  62. //返回
  63. //无

  64.         uint32_t guid = (GUID3 << 24) | (GUID2 << 16) | (GUID1 << 8) | GUID0; // 给guid赋值唯一ID
  65.         Serial.println(guid); // 串口输出唯一ID
  66.         delay(1000);
  67. }

  68. // the loop routine runs over and over again forever:
  69. void loop() {
  70.         // read the input on analog pin 0:
  71.         sensorValue = analogRead(A0);
  72.         // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  73.         float voltage = sensorValue * (2.56 / 4096.0);
  74.         // print out the value you read:
  75.         Serial.print(sensorValue);
  76.         Serial.print(' ');
  77.         Serial.print(cbrt(sensorValue));
  78.         Serial.print(' ');
  79.         Serial.println(voltage);

  80.         delay(1000);
  81.         TimeUpdate();
  82.         tm1637.display(TimeDisp);
  83. }
复制代码



打赏

参与人数 2家元 +60 收起 理由
家睦 + 50
人艰不拆了 + 10

查看全部打赏

发表于 2020-3-22 15:27:14 | 显示全部楼层
LZ用的什么开发环境?  好象支持python
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-22 15:55:47 | 显示全部楼层
茶壹杯 发表于 2020-3-22 15:27
LZ用的什么开发环境?  好象支持python

arduino 用的 sloeber IDE

这个芯片上不了python,这个是个ATmega328的国产替代,内存是一样大的,运行不了python.....

如果uno可以上micropython 那这个肯定就可以(内存一样,flash大一倍.....):tongue:
回复 支持 反对

使用道具 举报

发表于 2020-3-22 17:26:17 来自手机浏览器 | 显示全部楼层
就想知道曲线拟合,是怎么弄的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-22 19:05:49 来自手机浏览器 | 显示全部楼层
cat_li 发表于 2020-3-22 17:26
就想知道曲线拟合,是怎么弄的

wps 折线图 和板子半毛钱关系没有………

电压值知道 就能推算出所有的采样值 然后画图………
回复 支持 反对

使用道具 举报

发表于 2020-3-22 21:27:54 | 显示全部楼层
现实中不这么用,是因为光敏三极管很便宜,一毛几分钱……虽然普通LED更便宜,但是要用一个几毛钱的运放来搭I-V转换,成本高面积大;而光敏三极管只要加个电阻就行,成本、面积都不消说。

打赏

参与人数 1家元 +20 收起 理由
qingkong + 20 多谢赐教

查看全部打赏

回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2020-3-22 21:45:22 来自手机浏览器 | 显示全部楼层
amo73 发表于 2020-3-22 21:27
现实中不这么用,是因为光敏三极管很便宜,一毛几分钱……虽然普通LED更便宜,但是要用一个几毛钱的运放来 ...

我用的单片机……不需要运放……直接上就行……… 而且只是调节个亮度……

但是刷新频率不能太快…… 太快了它来不及……

这个上单片机连电阻也不用……直接adc读电压就行……

低成本凑合用………而且电视遥控器的学习功能也是类似的吧……拓展下,说不定还能干点别的………
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-22 22:13:48 来自手机浏览器 | 显示全部楼层
当然了 光敏电阻是更专业的选择 但是我连不怎么专业的事情(亮度和观感统一)的都不到……

玩玩这个也凑合了……反正 咋着也是玩啊………:lol:


这个我是led正极直接接a0 负极接地 单片机直接对二极管采样……  彻底杜绝了分压电路的额外电流消耗……

只是esp8266还是没法直接上 电压最低的红色的也可以给出超过1v的电压………  但是发光二极管那点电流 分压了还不知道能不能采到………
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-3-28 22:13 , Processed in 0.358801 second(s), 15 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

快速回复 返回顶部 返回列表