精美的温湿度传感器
组件和用品
 | | × | 1 | |
 | Adafruit NeoPixel Ring:WS2812 5050 RGB LED | | × | 1 | |
 | | × | 1 | |
| Adafruit 1.44" 彩色 TFT LCD 显示屏,带 MicroSD 卡突破 - ST7735R | | × | 1 | |
 | | × | 1 | |
 | | × | 1 | |
 | | × | 1 | |
关于这个项目
这个项目背后的故事
了解我们如何构建胡桃木燕尾形外壳并使用易于查找的 Arduino 组件为木工车间构建时尚且实用的湿度和温度监控器。这个 DIY 项目展示了使用 Arduino Uno 和 Adafruit 的一些优秀零件使用胡桃木燕尾榫和初学者电子产品的一些木工。
我们住在德克萨斯州中部,那里春季的湿度和温度会发生剧烈波动,这对某些木工项目来说可能是灾难性的。当湿度发生变化或开始变高时,这个很酷的项目有助于提醒我们,这样我们就可以采取预防措施,例如将我们的木制品移入房屋,或者在高湿度天气期间不进行任何铣削。它看起来也很棒,还有我们可爱的标志!
我们是 Arduino 和电子产品的新手,所以我们在制作这个的过程中不断学习。既然我们知道做出伟大的事情是多么容易,我们很高兴能做出更多的项目。
观看详细的构建视频!
代码
Arduino Work Shop 传感器代码Arduino
#include #include #include #include #include #include #include // 你可以在网上找到一堆 DHTXX 库。它们都有不同级别的功能。//定义引脚#define TFT_CS 10#define TFT_RST 9#define TFT_DC 8#define DHT_PIN 2#define PIXEL_PIN 6#define PIXEL_NUM 24#define SD_PIN 4#define BMP_BUF 20 // 全局变量sint currentColor =9999; //(数字对应图表。见下文。)CRGB LEDs[PIXEL_NUM];Adafruit_ST7735 tft =Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);DHT22 dht(DHT_PIN);int loopDelay =2000; //ms// SETUPvoid setup() { Serial.begin(9600); Serial.println("启动中。"); // 开始 DHT dht.begin(); // 初始化液晶屏 tft.initR(INITR_144GREENTAB); // 初始化 SD 卡 Serial.print("初始化 SD 卡。");如果(!SD.begin(SD_PIN)){ Serial.println(“失败!”);返回; } // 设置屏幕背景为黑色 tft.fillScreen(ST7735_BLACK); // 初始化 LED FastLED.addLeds(leds, PIXEL_NUM); // 让一切在开始循环之前赶上 delay(500);}// LOOPvoid loop() { // 获取传感器数据 dht.readTemperature(); dht.readHumidity(); int f =dht.temperature_F; // 华氏度 int h =dht.humity; // 百分比 // 绘制度数图标 tft.fillCircle(102, 42, 6, ST7735_WHITE); tft.fillCircle(102, 42, 4, ST7735_BLACK); // 在 LCD 屏幕上绘制温度 drawTemperature(f); // 湿度 setHumidityColors(h); //打印数据到串口监视器Serial.print("Temperature:"); Serial.println(f); Serial.print("湿度:"); Serial.print(h); Serial.println("%"); // 延迟延迟(1000); }// 绘制位图 - 这是用于 LCD Screenvoid bmpDraw(char *filename, uint8_t x, uint8_t y) { File bmpFile; int bmpWidth, bmpHeight; // W+H 以像素为单位 uint8_t bmpDepth; // 位深(目前必须是 24) uint32_t bmpImageoffset; // 文件开始图像数据 uint32_t rowSize; // 并非总是 =bmpWidth;可能有填充 uint8_t sdbuffer[3*BMP_BUF]; // 像素缓冲区(每像素 R+G+B) uint8_t buffidx =sizeof(sdbuffer); // 当前位置在 sdbuffer boolean goodBmp =false; // 在有效的标头解析上设置为 true boolean flip =true; // BMP 自下而上存储 int w, h, row, col; uint8_t r, g, b; uint32_t pos =0,startTime =毫秒(); if((x>=tft.width()) || (y>=tft.height())) return;// Serial.println();// Serial.print("Loading Bitmap Image:'"); // Serial.print(filename);// Serial.println('\''); // 打开 SD 卡上请求的文件 if ((bmpFile =SD.open(filename)) ==NULL) { Serial.print("Bitmap file not found!");返回; } // 解析 BMP 头 if(read16(bmpFile) ==0x4D42) { read32(bmpFile); (无效)read32(bmpFile); bmpImageoffset =read32(bmpFile); //Serial.println());读取32(bmp文件); bmpWidth =read32(bmpFile); bmpHeight =read32(bmpFile); if(read16(bmpFile) ==1) { bmpDepth =read16(bmpFile); //Serial.print("位深度:"); if((bmpDepth ==24) &&(read32(bmpFile) ==0)) { goodBmp =true; // BMP 行被填充(如果需要)到 4 字节边界 rowSize =(bmpWidth * 3 + 3) &~3; // 如果 bmpHeight 为负,则图像为自上而下的顺序。 // 这不是经典,而是在野外观察到的。 if(bmpHeight <0) { bmpHeight =-bmpHeight;翻转 =假; } // 要加载的裁剪区域 w =bmpWidth; h =bmpHeight; if((x+w-1)>=tft.width()) w =tft.width() - x; if((y+h-1)>=tft.height()) h =tft.height() - y; // 将 TFT 地址窗口设置为裁剪图像边界 tft.setAddrWindow(x, y, x+w-1, y+h-1); for (row=0; row=sizeof(sdbuffer)) { bmpFile.read(sdbuffer, sizeof(sdbuffer)); buffidx =0; } // 将像素从BMP转为TFT格式,推送显示 b =sdbuffer[buffidx++]; g =sdbuffer[buffidx++]; r =sdbuffer[buffidx++]; tft.pushColor(tft.Color565(r,g,b)); } } } } } bmpFile.close(); if(!goodBmp) Serial.println("BMP 格式无法识别。");}// 这是用于 Bitmap/LCD Screenuint16_t read16(File f) { uint16_t result; ((uint8_t *)&result)[0] =f.read(); // LSB ((uint8_t *)&result)[1] =f.read(); // MSB 返回结果;}// 这是针对 Bitmap/LCD Screenuint32_t read32(File f) { uint32_t result; ((uint8_t *)&result)[0] =f.read(); // LSB ((uint8_t *)&result)[1] =f.read(); ((uint8_t *)&result)[2] =f.read(); ((uint8_t *)&result)[3] =f.read(); // MSB 返回结果;}// 在 LCD 屏幕上绘制温度void drawTemperature(int temp) { // 获取温度中的位数 intdigits =numDigits(temp); // 定义绘制位图的光标位置 int x1_2 =62; int x2_2 =32; int x1_3 =1; int x2_3 =1; int x3_3 =1;整数 y =38;字符数字1[12];字符 digit2[12];字符 digit3[12];字符 digitStr1[24];字符 digitStr2[24];字符 digitStr3[24]; // 获取第一个数字 itoa(temp % 10, digit1,10); //Serial.println(temp % 10); strcpy(digitStr1, ""); strcat(digitStr1, digit1); strcat(digitStr1, ".bmp"); // 获取第二个数字 if(digits ==2){ itoa((temp / 10) % 10, digit2,10); strcpy(digitStr2, ""); strcat(digitStr2, digit2); strcat(digitStr2, ".bmp"); } // 获取第三位数字 if(digits ==3){ itoa((temp / 100) % 10, digit3,10); strcpy(digitStr3, ""); strcat(digitStr3, digit3); strcat(digitStr3, ".bmp"); } if(digits> 2){ bmpDraw(digitStr1,x1_3,y); bmpDraw(digitStr2,x2_3,y); bmpDraw(digitStr3,x3_3,y); } else { bmpDraw(digitStr1,x1_2,y); bmpDraw(digitStr2,x2_2,y); }}// 获取温度的位数以确定屏幕上的位置int numDigits(int number){ int valLen =0;如果(数字> 99)valLen =3;否则 valLen =2; return valLen;}// 设置 LED 颜色void setColors(int r, int g, int b){ for(int i =0; i
定制零件和外壳
示意图
Fritzing 没有大部分实际组件,所以我尽力表现事物的流动。