#include <Adafruit_NeoPixel.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_GFX.h>
#include <FastLED.h>
#include <SPI.h>
#include <SD.h>
#include <cactus_io_DHT22.h> // There's a bunch of DHTXX libraries you can find online. They all have varying levels of features.
// Define Pins
#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
// Global Variables
int currentColor = 9999; //(Numbers correspond to chart. See below.)
CRGB leds[PIXEL_NUM];
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
DHT22 dht(DHT_PIN);
int loopDelay = 2000; //ms
// SETUP
void setup() {
Serial.begin(9600);
Serial.println("Starting up.");
// Begin DHT
dht.begin();
// Initialize LCD Screen
tft.initR(INITR_144GREENTAB);
// Initialize SD Card
Serial.print("Initializing SD card.");
if (!SD.begin(SD_PIN)) {
Serial.println("Failed!");
return;
}
// Set Screen Background to Black
tft.fillScreen(ST7735_BLACK);
// Initialize LEDs
FastLED.addLeds<NEOPIXEL, PIXEL_PIN>(leds, PIXEL_NUM);
// Let everything catch up before starting loop
delay(500);
}
// LOOP
void loop() {
// Get Sensor Data
dht.readTemperature();
dht.readHumidity();
int f = dht.temperature_F; // Degrees in Fahrenheit
int h = dht.humidity; // Percentage
// Draw Degrees Icon
tft.fillCircle(102, 42, 6, ST7735_WHITE);
tft.fillCircle(102, 42, 4, ST7735_BLACK);
// Draw Temperature on LCD Screen
drawTemperature(f);
// Humidity
setHumidityColors(h);
//Print Data to Serial Monitor
Serial.print("Temperature: ");
Serial.println(f);
Serial.print("Humidity: ");
Serial.print(h);
Serial.println("%");
// Delay
delay(1000);
}
// Draw Bitmap - This is for the LCD Screen
void bmpDraw(char *filename, uint8_t x, uint8_t y) {
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3*BMP_BUF]; // pixel buffer (R+G+B per pixel)
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
boolean goodBmp = false; // Set to true on valid header parse
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col;
uint8_t r, g, b;
uint32_t pos = 0, startTime = millis();
if((x >= tft.width()) || (y >= tft.height())) return;
// Serial.println();
// Serial.print("Loading Bitmap Image: '");
// Serial.print(filename);
// Serial.println('\'');
// Open requested file on SD card
if ((bmpFile = SD.open(filename)) == NULL) {
Serial.print("Bitmap file not found!");
return;
}
// Parse BMP header
if(read16(bmpFile) == 0x4D42) {
read32(bmpFile);
(void)read32(bmpFile);
bmpImageoffset = read32(bmpFile);
//Serial.println());
read32(bmpFile);
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
if(read16(bmpFile) == 1) {
bmpDepth = read16(bmpFile);
//Serial.print("Bit Depth: ");
if((bmpDepth == 24) && (read32(bmpFile) == 0)) {
goodBmp = true;
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * 3 + 3) & ~3;
// If bmpHeight is negative, image is in top-down order.
// This is not canon but has been observed in the wild.
if(bmpHeight < 0) {
bmpHeight = -bmpHeight;
flip = false;
}
// Crop area to be loaded
w = bmpWidth;
h = bmpHeight;
if((x+w-1) >= tft.width()) w = tft.width() - x;
if((y+h-1) >= tft.height()) h = tft.height() - y;
// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x+w-1, y+h-1);
for (row=0; row<h; row++) { // For each scanline...
if(flip) {
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
} else {
pos = bmpImageoffset + row * rowSize;
}
if(bmpFile.position() != pos) {
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer);
}
for (col=0; col<w; col++) {
if (buffidx >= sizeof(sdbuffer)) {
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0;
}
// Convert pixel from BMP to TFT format, push to display
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
tft.pushColor(tft.Color565(r,g,b));
}
}
}
}
}
bmpFile.close();
if(!goodBmp) Serial.println("BMP format not recognized.");
}
// This is for the Bitmap/LCD Screen
uint16_t read16(File f) {
uint16_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read(); // MSB
return result;
}
// This is for the Bitmap/LCD Screen
uint32_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
return result;
}
// Draw Temperature on LCD Screen
void drawTemperature(int temp) {
// Get Number of Digits in the Temperature
int digits = numDigits(temp);
// Define Cursor Positions to Draw Bitmaps
int x1_2 = 62;
int x2_2 = 32;
int x1_3 = 1;
int x2_3 = 1;
int x3_3 = 1;
int y = 38;
char digit1[12];
char digit2[12];
char digit3[12];
char digitStr1[24];
char digitStr2[24];
char digitStr3[24];
// Get First Digit
itoa(temp % 10, digit1,10);
//Serial.println(temp % 10);
strcpy(digitStr1, "");
strcat(digitStr1, digit1);
strcat(digitStr1, ".bmp");
// Get Second Digit
if(digits == 2){
itoa((temp / 10) % 10, digit2,10);
strcpy(digitStr2, "");
strcat(digitStr2, digit2);
strcat(digitStr2, ".bmp");
}
// Get Third Digit
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);
}
}
// Get number of digits in temperature to determine placement on screen
int numDigits(int number){
int valLen = 0;
if(number > 99)
valLen = 3;
else
valLen = 2;
return valLen;
}
// Set LED Colors
void setColors(int r, int g, int b){
for(int i = 0; i < PIXEL_NUM; i++){
leds[i].setRGB( r, g, b);
leds[i].fadeLightBy(125);
FastLED.show();
delay(100);
}
}
// Determine which colors to use based on Humidity level
void setHumidityColors(int humidity){
// Humidity Color Chart - This is just something we came up with.
// Red - 0-17%
// Orange - 18-34%
// Yellow - 35-51%
// Green - 52-68%
// Blue - 69-85%
// Purple - 86-100%
// Define Colors
int cRed[3] = {255,0,0};
int cOrange[3] = {255,90,0};
int cYellow[3] = {255,255,0};
int cGreen[3] = {0,255,0};
int cBlue[3] = {0,175,255};
int cPurple[3] = {255,0,255};
int range = map(humidity, 0, 100, 0, 6);
switch (range) {
case 0: // Red
if(currentColor == 0){
break;
}
else {
setColors(cRed[0], cRed[1], cRed[2]);
currentColor = 0;
}
break;
case 1: // Orange
if(currentColor == 1){
break;
}
else {
setColors(cOrange[0], cOrange[1], cOrange[2]);
currentColor = 1;
}
break;
case 2: // Yellow
if(currentColor == 2){
break;
}
else {
setColors(cYellow[0], cYellow[1], cYellow[2]);
currentColor = 2;
}
break;
case 3: // Green
if(currentColor == 3){
break;
}
else {
setColors(cGreen[0], cGreen[1], cGreen[2]);
currentColor = 3;
}
break;
case 4: // Blue
if(currentColor == 4){
break;
}
else {
setColors(cBlue[0], cBlue[1], cBlue[2]);
currentColor = 4;
}
break;
case 5: // Purple
if(currentColor == 5){
break;
}
else {
setColors(cPurple[0], cPurple[1], cPurple[2]);
currentColor = 5;
}
break;
}
}
Comments