edge lab LIVE! starts Tuesday in Munich. Grab a workshop seat and take home the board you build on. Code FRIEND-HACKSTER saves 20%. () Learn more!
Robert Fletcher
Published

Standalone ATmega328P-AUR Environmental Data Logger

Build a compact environmental data logger using the ATmega328P-AUR microcontroller. The project measures temperature, humidity, and ambient

IntermediateWork in progress30
Standalone ATmega328P-AUR Environmental Data Logger

Things used in this project

Hardware components

ATmega328P-AUR
Main microcontroller
×1
16 MHz crystal
External clock
×1
10 kΩ resistor
RESET pull-up
×1
100 nF ceramic capacitor
Power supply decoupling
×3
10 µF electrolytic capacitor
Supply stabilization
×1
22 pF ceramic capacitor
Crystal load capacitors
×2
MCP1700-3302E/TO
3.3 V LDO regulator
×1
DHT22 / AM2302
Temperature and humidity sensor
×1
BH1750FVI
Digital ambient light sensor
×1
SSD1306 128×64 I2C OLED
Local display
×1
MicroSD card module
Data storage
×1
MicroSD card
Storage medium
×1
4.7 kΩ resistor
I2C pull-up resistors
×2
1 kΩ resistor
DHT22 data pull-up
×1
330 Ω resistor
Status LED current limiting
×1
LED
Data logging status
×1
Push button
Manual data logging
×1
3.3 V regulated power source
Main power
×1
ICSP programming header
In-system programming
×1

Software apps and online services

Arduino IDE
Arduino IDE
firmware development
Arduino AVR Boards package
ATmega328P support
Adafruit SSD1306 library
OLED display control
Adafruit GFX library
display graphics
DHT sensor library
temperature and humidity reading
SD library
MicroSD card access
KiCad
KiCad
schematic capture and PCB design
GitHub
project source code and documentation
Serial Monitor
debugging and data inspection

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Digital multimeter
Wire cutters and wire strippers
Breadboard jumper wires
USB-to-serial adapter
TQFP soldering tools
PCB fabrication service

Story

Read more

Code

Code

C/C++
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <DHT.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <BH1750.h>

#define DHTPIN 2
#define DHTTYPE DHT22

#define SD_CS 10
#define STATUS_LED 6
#define BUTTON_PIN 7

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

DHT dht(DHTPIN, DHTTYPE);

BH1750 lightMeter;

Adafruit_SSD1306 display(
  SCREEN_WIDTH,
  SCREEN_HEIGHT,
  &Wire,
  -1
);

unsigned long lastLog = 0;
unsigned long elapsedSeconds = 0;

const unsigned long LOG_INTERVAL = 10000;

void showMessage(const char *message)
{
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println(message);
  display.display();
}

bool writeLog(float temperature,
              float humidity,
              float lux)
{
  File file = SD.open("ENVLOG.CSV", FILE_WRITE);

  if (!file)
  {
    return false;
  }

  file.print(elapsedSeconds);
  file.print(",");
  file.print(temperature, 2);
  file.print(",");
  file.print(humidity, 2);
  file.print(",");
  file.println(lux, 2);

  file.close();

  return true;
}

void displayReadings(float temperature,
                     float humidity,
                     float lux)
{
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);

  display.setCursor(0, 0);
  display.print("Temperature: ");
  display.print(temperature, 1);
  display.println(" C");

  display.setCursor(0, 16);
  display.print("Humidity: ");
  display.print(humidity, 1);
  display.println(" %");

  display.setCursor(0, 32);
  display.print("Light: ");
  display.print(lux, 0);
  display.println(" lux");

  display.setCursor(0, 48);
  display.print("Time: ");
  display.print(elapsedSeconds);
  display.println(" s");

  display.display();
}

void recordMeasurement()
{
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  float lux = lightMeter.readLightLevel();

  if (isnan(temperature) || isnan(humidity))
  {
    showMessage("DHT22 read error");
    return;
  }

  if (lux < 0)
  {
    showMessage("BH1750 read error");
    return;
  }

  displayReadings(temperature, humidity, lux);

  if (writeLog(temperature, humidity, lux))
  {
    digitalWrite(STATUS_LED, HIGH);
    delay(100);
    digitalWrite(STATUS_LED, LOW);
  }
  else
  {
    showMessage("SD write error");
  }
}

void setup()
{
  pinMode(STATUS_LED, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  Serial.begin(9600);

  Wire.begin();

  dht.begin();

  lightMeter.begin();

  if (!display.begin(
        SSD1306_SWITCHCAPVCC,
        0x3C))
  {
    while (1);
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("ATmega328P-AUR");
  display.println("Environmental");
  display.println("Data Logger");
  display.display();

  delay(2000);

  if (!SD.begin(SD_CS))
  {
    showMessage("SD init failed");
  }
  else
  {
    File file = SD.open("ENVLOG.CSV", FILE_WRITE);

    if (file)
    {
      if (file.size() == 0)
      {
        file.println(
          "Time,Temperature_C,Humidity_Percent,Light_Lux"
        );
      }

      file.close();
    }
  }

  recordMeasurement();

  lastLog = millis();
}

void loop()
{
  if (millis() - lastLog >= LOG_INTERVAL)
  {
    lastLog = millis();

    elapsedSeconds += 10;

    recordMeasurement();
  }

  if (digitalRead(BUTTON_PIN) == LOW)
  {
    recordMeasurement();

    delay(300);
  }
}

Credits

Robert Fletcher
20 projects • 1 follower
Senior semiconductor engineer at AVAQ Semiconductor. With extensive experience in electronic components, supply chain solutions & sourcing.

Comments