CJMCU-GUVA-S12SD紫外线传感器

作者

颜哲锟

摘要

CJMCU-GUVA-S12SD紫外线传感器是2015年刚出来的。但淘宝卖家只提供了简化版的英文数据手册和写在txt文档里的几行代码,Baidu、Google上只有英文版资料和一些淘宝商家在百度云上托管的几行代码,并没有人把玩过的经历共享出来,甚至在Github上无法搜索到任何有关CJMCU-GUVA-S12SD的资料。
所以我把我的爬坑经历共享出来,希望大家都能看懂。

CJMCU-GUVA-S12SD紫外线传感器

8月初淘来一个紫外线传感器,感觉应该很有意思,型号是CJMCU-GUVA-S12SD,谁知这传感器淘宝卖家只提供了简化版的英文数据手册和写在txt文档里的几行代码,Baidu、Google上只有英文版资料和一些淘宝商家在百度云上托管的几行代码,并没有人把玩过的经历共享出来,甚至在Github上无法搜索到任何有关CJMCU-GUVA-S12SD的资料。好吧,某宝一瞧,居然是2015年刚出来的传感器。虽然已经出了半年,但比起那些常见的sensor岁数可小了不知多少,哈哈哈~

入坑

接上VCC和GND,再接好SIG。之前翻淘宝的时候印象有点深,写的是这个sensor用的TTL通信,我没有任何思考直接把SIG接到了RX。

数值转换表

勉勉强强啃完英文数据手册,发现经过数据处理可以得到传感器光电流的输出电压,同时输出电压值和紫外线等级基本呈线性关系(如上图)。同时,在txt文件中的几行代码里边发现了一个转换:代码转换,认为这个数据是光电流的输出电压与紫外线等级的转换值。

UVindex

烧录程序,数据读出来,优化一下代码,再对着光电流的输出电压与紫外线强度转换表(如上表)写几行代码让arduino在串口监视器中显示电压的同时,也转换出UV等级。

通过人工对比读出来的数据与紫外线等级的转换表发现,在室内的紫外线等级一直是11级,那么这数据肯定是错的咯。我加入了取平均值的filter函数,依旧是错误数据。

我又重新仔细读了一遍数据手册和代码,发现这明明用的是A0口,sensor传回来的是模拟值,然而淘宝商家说明里写了TTL电平。好吧,这是个坑~

其实,我接RX的时候还一直在奇怪,为什么一根信号线不是单总线通信协议?为什么没有时钟却能用高低电平读出数据?果断更改引脚,读取数据正常。

  • 所以,某宝以及个别说明是有误的,CJMCU-GUVA-S12SD用的是单总线通信协议!

重要的话说三遍,CJMCU-GUVA-S12SD是单总线通信!是单总线通信!是单总线通信!

对于4980这个数据我想说一下我个人的观点:考虑到每个sensor制作的时候会有误差,所以这个具体值在每个CJMCU-GUVA-S12SD是不一样的,厂家提供的4980应该是基于统计学的转换值,如果要想要得到一个精确的光电流输出电压需要用工业级紫外线校准仪校准一下,否则会有点不精确,另外还可以把我的取平均值filter算法替换为限幅滤波法(又称程序判断滤波法)。

数据手册

网上可以找到比某宝店家提供的详细好几倍的英文数据手册,在此一并附上:百度文库版豆丁版。呃…虽然是英文版~

底层原理图

底层原理图

最终布线

布线

我单独测试的时候用的是arduino UNO,然后再把CJMCU-GUVA-S12SD接入我要用的nodMCU,布线图中我就用UNO代替了,其实都是大同小异啦!

最终代码

int sensorValue;//传感器输出的数据包
long sum = 0;//由于测试中发现数据会溢出,就用了long,long目前还未溢出过
int vout = 0;//由于通信中输出的是整一串数据包,所以需要翻译,vout是处理好的数据,也就是CJMCU-GUVA-S12SD传感器光电流的输出电压
int uv = 0;//紫外线等级

void setup(){
Serial.begin(9600);//CJMCU-GUVA-S12SD的波特率为9600
}

void loop()
{    
  sensorValue = 0;
  sum = 0;
  for(int i = 0 ; i < 1024 ; i++ )//这里我用的是最简单的filter算法
  {  
      sensorValue = analogRead(A0);
      sum = sensorValue + sum;
      delay(2);
  }
  vout = sum >> 10;//开始数据处理
  vout = vout * 4980.0 / 1024;
  Serial.print("The Photocurrent value : ");
  Serial.print(vout);
  Serial.println("mV");
  if(vout < 50){  //查表,把得到的光电流值转换成紫外线等级
    uv = 0;
  }
  else if(vout < 227){
    uv = 1;
  }
  else if(vout < 318){
    uv = 2;
  }
  else if(vout < 408){
    uv = 3;
  }
  else if(vout < 503){
    uv = 4;
  }
  else if(vout < 606){
    uv = 5;
  }
  else if(vout < 696){
    uv = 6;
  }
  else if(vout < 795){
    uv = 7;
  }
  else if(vout < 881){
    uv = 8;
  }
  else if(vout < 976){
    uv = 9;
  }
  else if(vout < 1079){
    uv = 10;
  }
  else{
    uv = 11;
  }
  delay(20);
  Serial.print("UV Index = ");
  Serial.println(uv);
  }

希望有需要的都可以看懂==不懂可以评论也可以向 wycwykds@163.com 砸邮件~~

2016.8.2写于千岛湖

PS:
原文链接:http://blog.csdn.net/dustintime/article/details/52387798

已授权UbiBots系列博客转载

  • 4
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
以下是将GUVA-S12SD紫外线传感器通过PCF8591转换成毫伏电压的51程序,供您参考: ```c #include <reg51.h> #define uchar unsigned char #define uint unsigned int #define PCF8591_ADDR 0x90 // PCF8591地址 #define GUVA_S12SD_ADDR 0x00 // GUVA-S12SD地址 sbit SCL = P2^1; // I2C总线SCL引脚 sbit SDA = P2^0; // I2C总线SDA引脚 // I2C总线起始信号 void I2C_Start() { SDA = 1; SCL = 1; SDA = 0; SCL = 0; } // I2C总线停止信号 void I2C_Stop() { SDA = 0; SCL = 1; SDA = 1; } // I2C总线等待应答信号 bit I2C_WaitAck() { bit ack; SDA = 1; SCL = 1; ack = SDA; SCL = 0; return ack; } // I2C总线发送应答信号 void I2C_Ack() { SDA = 0; SCL = 1; SCL = 0; } // I2C总线发送非应答信号 void I2C_NAck() { SDA = 1; SCL = 1; SCL = 0; } // I2C总线发送一个字节 void I2C_WriteByte(uchar dat) { uchar i; for(i=0;i<8;i++) { SDA = dat & 0x80; SCL = 1; SCL = 0; dat <<= 1; } } // I2C总线接收一个字节 uchar I2C_ReadByte() { uchar i, dat = 0; SDA = 1; for(i=0;i<8;i++) { dat <<= 1; SCL = 1; dat |= SDA; SCL = 0; } return dat; } // 从PCF8591读取GUVA-S12SD的电压值 uint ReadGUVA_S12SD() { uint vol; I2C_Start(); I2C_WriteByte(PCF8591_ADDR); if(!I2C_WaitAck()) { I2C_Stop(); return 0; } I2C_WriteByte(GUVA_S12SD_ADDR); if(!I2C_WaitAck()) { I2C_Stop(); return 0; } I2C_Start(); I2C_WriteByte(PCF8591_ADDR | 0x01); if(!I2C_WaitAck()) { I2C_Stop(); return 0; } vol = I2C_ReadByte(); I2C_Ack(); I2C_Stop(); return vol * 5000 / 255; // 将ADC值转换成电压值,单位为毫伏 } void main() { uint vol; while(1) { vol = ReadGUVA_S12SD(); // 读取GUVA-S12SD的电压值 // 将电压值转换成待显示的数值(例如:1.23V -> 123) // 将待显示的数值发送到数码管显示模块进行显示 } } ``` 注意:以上程序仅供参考,具体实现还需根据您的具体硬件环境和实际需求进行调整和修改。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值