tag 标签: ws2812

相关博文
  • 热度 6
    2023-12-31 00:37
    1432 次阅读|
    2 个评论
    项目背景:甲醛在生活也比较常见:新装修的公寓,不知名的家居,新装修的房子以及吸烟的密闭环境,你没有听错,吸烟过程有大量甲醛,甲醛严重超标。故需要DIY甲醛数显检测,检测时间短,反应快:进口甲醛传感器一致性很好,精度高,sensirion甲醛传感器SFA30,Arduino程序代码:Arduino UNO 驱动OLED实时显示甲醛传感器相关参数:甲醛浓度、温度、湿度,ws2812试试通过颜色确定当前环境中甲醛浓度等级 甲醛相关资料可参考抖音老爸评测中吸烟仓中甲醛浓度,或参考中国知网:吸烟烟雾中的甲醛、室内香烟、电子烟释放甲醛和VOCs的散发特征及健康风险分析等文章 sensirion甲醛传感器SFA30,甲醛传感器一般采用电化学原理,利用甲醛与催化剂作用产生微弱电压信号,经过运放处理后将微弱信号放大然后根据建立模型(湿度、温度补偿)得到甲醛浓度,本教程使用的是sensirion的SFA30甲醛传感器 甲醛传感器原理: 传感器模型框架图: 项目实现:基于Arduino平台搭建甲醛传感器实时显示、指示、读取数据的检测仪,真实检查环境中的甲醛浓度,专业甲醛检测仪动辄上万元,对于普通家庭很难承担,sensirion甲醛传感器SFA30基于电化学原理,通过半透膜筛选甲醛分子,真真切切检测环境中甲醛浓度。 项目原理图: PCB图: 3D渲染图: 实物图: 视频介绍: 代码附件: #include #include #define SENSOR_SERIAL_INTERFACE Serial SensirionUartSfa3x sfa3x; #include #ifdef __AVR__ #include #endif #define PIN 11 Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800); #include "font.h" int16_t hcho; int16_t relativeHumidity; int16_t temperature; int SFA30_date=0; uint16_t error; int scl=A5;//定义OLEDSCL为A1引脚 int sda=A4;//定义OLEDSCL为A0引脚 int res=10;//定义OLE DRES为10引脚(IIC通信可不用设置) #define OLED_SCLK_Clr() digitalWrite(scl,LOW)//SCL #define OLED_SCLK_Set() digitalWrite(scl,HIGH) #define OLED_SDIN_Clr() digitalWrite(sda,LOW)//SDA #define OLED_SDIN_Set() digitalWrite(sda,HIGH) #define OLED_RST_Clr() digitalWrite(res,LOW)//RES 注:此引脚是为了配合SPI驱动模块改成I2C驱动模块使用的(改装的话必须接),如果买的是I2C模块,请忽略此引脚。 #define OLED_RST_Set() digitalWrite(res,HIGH) #define OLED_CMD 0 //写命令 #define OLED_DATA 1 //写数据 uint8_t OLED_GRAM ;//将要显示的缓存内容 void setup() { pinMode(2, OUTPUT);pinMode(3, OUTPUT);//SFA30传感器供电引脚使能 digitalWrite(3, HIGH);digitalWrite(2, LOW);//SFA30传感器供电输出 pinMode(A3, OUTPUT);pinMode(A2, OUTPUT); //OLED供电引脚使能 digitalWrite(A3,LOW); digitalWrite(A2,HIGH);//OLED供电输出 OLED_Init();//OLED初始化 OLED_ColorTurn(0);//0正常显示 1反色显示 OLED_DisplayTurn(0);//0正常显示 1翻转180度显示 SENSOR_SERIAL_INTERFACE.begin(115200); while (!SENSOR_SERIAL_INTERFACE) {delay(100);} sfa3x.begin(SENSOR_SERIAL_INTERFACE); sfa3x.deviceReset();//SFA30传感器复位 sfa3x.startContinuousMeasurement();//SFA30传感器开始测试 //WS2812驱动 #if defined (__AVR_ATtiny85__) if (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif // End of trinket special code strip.begin(); strip.setBrightness(50); strip.show(); // Initialize all pixels to 'off' //WS2812驱动 } void loop() { while(1) { sfa3x.readMeasuredValuesOutputFormat2(hcho, relativeHumidity,temperature);//获取SFA30传感器数据 //OLED_Clear(); OLED_ShowString(0,0,"T:",16);OLED_ShowNum(40,0,temperature/200,2,16); OLED_ShowString(56,0,".",16);OLED_ShowNum(64,0,temperature%200,2,16);OLED_DrawCircle(82,4,1);OLED_ShowString(86,0,"C",16); OLED_ShowString(0,16,"H:",16);OLED_ShowNum(40,16,relativeHumidity/100,2,16); OLED_ShowString(56,16,".",16);OLED_ShowNum(64,16,relativeHumidity%100,2,16); OLED_ShowString(82,16,"%",16); OLED_ShowString(0,32,"HCHO:",16);OLED_ShowNum(40,32,hcho/5,3,16);OLED_ShowString(66,32,"ppb",16); OLED_ShowString(0,48,"date:",16);OLED_ShowNum(40,48,SFA30_date,3,16); OLED_Refresh(); delay(50);SFA30_date++; if(hcho<307) {colorWipe(strip.Color(0, 255, 0), 50); }// Green else if(hcho<615) {colorWipe(strip.Color(0, 0, 255), 50); }// Green else if(hcho<615) {colorWipe(strip.Color(255, 0, 0), 50); }// Red } } //反显函数 void OLED_ColorTurn(uint8_t i) { if(!i) OLED_WR_Byte(0xA6,OLED_CMD);//正常显示 else OLED_WR_Byte(0xA7,OLED_CMD);//反色显示 } //屏幕旋转180度 void OLED_DisplayTurn(uint8_t i) { if(i==0) { OLED_WR_Byte(0xC8,OLED_CMD);//正常显示 OLED_WR_Byte(0xA1,OLED_CMD); } else { OLED_WR_Byte(0xC0,OLED_CMD);//反转显示 OLED_WR_Byte(0xA0,OLED_CMD); } } //起始信号 void I2C_Start(void) { OLED_SDIN_Set(); OLED_SCLK_Set(); OLED_SDIN_Clr(); OLED_SCLK_Clr(); } //结束信号 void I2C_Stop(void) { OLED_SCLK_Set(); OLED_SDIN_Clr(); OLED_SDIN_Set(); } //等待信号响应 void I2C_WaitAck(void) //测数据信号的电平 { OLED_SCLK_Set(); OLED_SCLK_Clr(); } //写入一个字节 void Send_Byte(uint8_t dat) { uint8_t i; for(i=0;i<8;i++) { OLED_SCLK_Clr();//将时钟信号设置为低电平 if(dat&0x80)//将dat的8位从最高位依次写入 { OLED_SDIN_Set(); } else { OLED_SDIN_Clr(); } OLED_SCLK_Set();//将时钟信号设置为高电平 OLED_SCLK_Clr();//将时钟信号设置为低电平 dat<<=1; } } //发送一个字节 //向SSD1306写入一个字节。 //mode:数据/命令标志 0,表示命令;1,表示数据; void OLED_WR_Byte(uint8_t dat,uint8_t mode) { I2C_Start(); Send_Byte(0x78); I2C_WaitAck(); if(mode){Send_Byte(0x40);} else{Send_Byte(0x00);} I2C_WaitAck(); Send_Byte(dat); I2C_WaitAck(); I2C_Stop(); } //更新显存到OLED void OLED_Refresh(void) { uint8_t i,n; for(i=0;i<8;i++) { OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址 OLED_WR_Byte(0x00,OLED_CMD); //设置低列起始地址 OLED_WR_Byte(0x10,OLED_CMD); //设置高列起始地址 for(n=0;n<128;n++) OLED_WR_Byte(OLED_GRAM ,OLED_DATA); } } //清屏函数 void OLED_Clear(void) { uint8_t i,n; for(i=0;i<8;i++) { for(n=0;n<128;n++) { OLED_GRAM =0;//清除所有数据 } } OLED_Refresh();//更新显示 } //画点 //x:0~127 //y:0~63 void OLED_DrawPoint(uint8_t x,uint8_t y) { uint8_t i,m,n; i=y/8; m=y%8; n=1<
  • 热度 21
    2015-4-25 17:38
    1396 次阅读|
    0 个评论
    Well, I am all aquiver with excitement. When I returned from my trip to the UK last week (to celebrate what would have been my dear old dad's 100th birthday) I found a package waiting for me in my office.   The outside of the package informed me that its sender was my chum Duane Benson, so I was reasonably confident that this was going to contain the PCB he'd created to implement the spectrum analyzer shield for my BADASS Display . And, indeed, when I opened the box, the first thing I saw was a small plastic bag containing a couple of these PCBs along with the associated headers.     Actually, the main package was significantly larger than this board. I remember thinking at the time that Duane was being a tad enthusiastic on the packaging front. In fact, I was just about to throw the box away when I realized it contained something else. When I looked closer, I discovered a 60-element NeoPixel ring (this is actually formed from four 15-element NeoPixel segments) from AdaFruit.     Now, I've been using NeoPixels in a lot of my recent projects, and I'd been lusting after one of these rings for a while, so I was jolly excited to finally have one in my sweaty hands. I was just starting to ponder some of the things I could do with this little beauty when I realized that it was accompanied by a custom-designed circuit board.     Well, what would you do? There wasn't any note accompanying the ring, but there was a micro-USB socket on the board almost begging for power to be applied, so I immediately did so, and the ring lit up looking much like the image above.   It didn’t take too long to realize that this was a clock. The pink pixels indicate the hours, the yellow pixel indicates the current hour, the green pixel indicates the current minute, and the blue pixel (a bit hard to see here) indicates the current second.   Sometime later, when I finally got around to checking my email, I found a message from Duane saying: "The spectrum analyzer board should be there when you get back. Also, you'll need these instructions for a little something extra I put in the box." This link took me to the LeoNeo Clock Kit page on Duane's SteelPuppet.com website where I discovered this video , detailed build instructions, and the source code for the sketch (program) running the clock.   In addition to the MCU (which looks like an Arduino Leonardo to the Arduino IDE), there is a real-time clock (RTC) chip, an ambient light sensor, and two control buttons. You can use the buttons to vary the overall brightness of the NeoPixels and to set the time. Whatever brightness you set as the base level, the system will use as a starting point to brighten or dim the display based on the ambient light.   Now, I want to go on record here as saying that Duane has done a masterful job. His circuit board is a joy to behold (not the least that he solders all of the surface-mount components by hand), and the board-ring combo looks absolutely amazing in real life. On the other hand... displaying the hours, minutes, and seconds on the same ring can be a tad confusing to the observer. Also, I always feel that the more tri-colored pixels you have, the better life is (this is a simple rule-of-thumb, but it's served me well over the years).   The bottom line is that I started to ponder making one of these little beauties of my own. Unlike Duane with his custom board, I'll start out using an Arduino Uno or Arduino Mega for my prototype (I may move on to a custom board later). I also started to think about augmenting the 60-pixel ring with a 24-pixel ring and a 12-pixel ring as illustrated below.     In the case of the real-time clock, I'm going to use a ChronoDot Module from Adafruit, because I've already deployed these in my Vetinari Clock and my Inamorata Prognostication Engine projects; they are easy to use and work really well.   I'm still noodling about all of this, but my current thoughts are to place the NeoPixel rings behind a circle of translucent white glass, which will be embedded in an equilateral triangle of black/ebonized wood. The triangle's corners will be rounded off, and the whole thing will have an ultra-simplistic look and feel as illustrated below.     Of course, this ultra-simplistic look will be deceiving. For example, it will be possible to place the triangle using any of its faces as the base, and the clock's display will automatically respond to accommodate this. I could achieve this using two or three simple Tilt Ball Switches , but I'm rather tempted to performing some experiments with a Triple Axis Gyro , or perhaps even an all-in-one 9-DOF Sensor (where "DOF" stands for "degrees of freedom"). In the case of this latter unit, a 3-axis accelerometer can tell you which direction is down towards the Earth (by measuring gravity) or how fast the board is accelerating in 3D space; a 3-axis magnetometer can sense where the strongest magnetic force is coming from (generally used to detect magnetic north); and a 3-axis gyroscope can be used to measure spin and twist. By combining all of this data, the clock will have a really good idea as to what is happening around it (yes, I said "will" because while writing this I've decided that my masterpiece deserves nothing less than a 9-DOF sensor). I'm also planning on adding a sound effects card that can play and mix multiple audio streams. A few of us have been looking into designing and building our own card. However, Duane just pointed me towards a very interesting card called the WAV Trigger from SparkFun that appears to offer most of the capabilities I need.   In addition to playing various sounds to indicate the passing of the hours, minutes, and seconds, I'm also planning on having the clock respond to being tapped or moved, saying things like "Oi! Have you washed your hands?" and "Hey! Don’t be so rough!" and "Oooh... that feels nice."   The really cool thing is that I showed Duane's clock to my chum Ivan who sits in the next bay. Ivan and I are both somewhat competitive, so he's decided to build one of these clocks also, and then we're going to compete with each other to try to out-do the other with the sophistication of our effects. We've both ordered our 60-, 24-, and 12-pixel rings and ChronoDot real-time clocks. (Ivan doesn’t yet know that I've ordered a WAV Trigger card -- you have to keep a little something in reserve LOL.)   I'll be posting update blogs and videos in the weeks to come. I'll also be making all of my design files and program source code files available for anyone else who wants to build one of these. Actually, it would be great if you decided to build one yourself, because then you could join in the competition with Ivan and myself to see who can come up with the best effects. In the meantime, I'd be very interested to hear your thoughts on all of this.