KEMBAR78
ATmega328P: Temperature Monitoring and Logging. | PDF | Microcontroller | Embedded System
0% found this document useful (0 votes)
41 views26 pages

ATmega328P: Temperature Monitoring and Logging.

The document outlines a project focused on designing a temperature monitoring and logging system using the ATmega328P microcontroller, LM35 temperature sensor, DS3232 RTC, and an I2C LCD display. The system logs temperature variations exceeding 4ºC within an hour into the ATmega328P's EEPROM and displays real-time data on the LCD. The report details the methodology, components, firmware development, and testing processes involved in the project.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views26 pages

ATmega328P: Temperature Monitoring and Logging.

The document outlines a project focused on designing a temperature monitoring and logging system using the ATmega328P microcontroller, LM35 temperature sensor, DS3232 RTC, and an I2C LCD display. The system logs temperature variations exceeding 4ºC within an hour into the ATmega328P's EEPROM and displays real-time data on the LCD. The report details the methodology, components, firmware development, and testing processes involved in the project.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

Subject EBS117V

PROJECT
Student surname Mngomezulu
Student number 220383130
Practical number Project Phase 2

GA 5 competence achieved
YES NO
SB Mngomezulu

Student number 220383130

EBS117V Project Phase 2

Temperature Monitoring and Logging with


ATmega328P
Introduction

In this report we will look into the design and implementation of temperature
monitoring and logging through an ATmega328P. Temperature and time will be
displayed on a 20x4 LCD that is configured for I2C operation through a PCF8574
I2C port expander. The temperature will be measured through an LM35 module and
the data getting logged internally within the ATmega328P EEPROM memory
whenever a variation of 4ºC is detected within an hour. A DS3232 RTC will be used
to maintain time keeping in this exercise.

Literature Review

Embedded systems play a crucial role in real-time monitoring applications, especially


in industrial and environmental monitoring. The ATmega328P microcontroller, with its
ADC capabilities and EEPROM, is ideal for implementing such a system. The
DS3232 RTC ensures accurate timekeeping, while the LM35 provides reliable
temperature measurements. Previous works have utilized similar architectures but
with different communication protocols, such as SPI and UART. This project focuses
on an I2C-based approach to minimize wiring complexity.

Project Objectives

➢ Development of an embedded system that continuously monitors


temperature.
➢ Accurate timestamping using an RTC module.
➢ Use the LCD to display the real-time temperature and time.
➢ Using the EEPROM to store temperature variations exceeding 4˚C in an hour.
➢ Simulate through Proteus evaluating the results through the LCD and the
EEPROM tables

Methodology

Components
• ATMega328P
• DS3232
• LM35 Module
• I2C LCD with PCF8574 module
The backbone of the project will be the ATmega328P, this microcontroller is a low
power 16MHz 8-bit microcontroller with 32 registers. The ATmega328P has
Bluetooth and WiFi capabilities, ADC conversion, I2C capabilities and an internal
EEPROM. The ATmega328P will be used to control these components as inputs and
outputs.

The LCD has an I2C module integrated with it and this allows the best use of the
microcontroller since only two pins are used for data transfer when using the I2C
protocol to communicate with modules. The two pins can also be used for other
modules as well distinguished by their addresses, hence we were able to wire the
RTC module via the same pins.

For temperature sensing the LM35 uses analog-to-digital conversion (ADC) which is
not too complicated compared to DS18B20 1 Wire Communication. The LM35 has a
high accuracy of ±0.5˚C which makes it ideal for the requirement we are addressing.

The DS3232 has high accuracy compared to other real time counter (RTC) modules.
Compared to the DS1307 for example, the DS3232 has an accuracy of ±2 ppm with
a built-in temperature compensated crystal oscillator while the latter has an accuracy
of ±20 ppm with an external crystal that is prone to drift and the inaccuracy has a
serious impact over long periods of time or as temperature varies. Since we are
measuring temperature the DS3232 is the best option because it is temperature
compensated.

Simulation
Proteus will be used for simulation of the project. For simulation components do not
always come integrated with the modules they need for I2C protocol functionality,
hence they have added to the circuitry. The placement of components must be done
strategically so that it allows one to see the circuit clearly when debugging. Most of
the protection measures which would have been necessary for the real setup are not
essential for simulation circuitry however they will be addressed in this report. It’s
also important to know where the location of your files is because for simulation a
hex file created by Microchip Studio will be used for the simulation.

Firmware Development
The code will be done on Microchip Studio using C-language. By using Microchip
Studio we can talk to the registers of the ATmega328P directly while other software
like Arduino may be buggy and slower.

Given that we are using ATmega328P which is a resource limited microcontroller


using C works efficiently and faster since it has a lower CPU overhead and a smaller
memory footprint. C also can be used to directly control registers of the
microcontroller which is the best approach to using embedded systems effectively.
C++ would have been slower due to its use of abstract layers and standard libraries
for embedded systems are rare hence it would have caused the complexity of
creating those libraries.

Microchip Studio is specifically designed for AVR microcontrollers hence it’s suitable
for direct register control requirements unlike Arduino which is largely reliant on
libraries to execute processes. Microchip Studio has advanced debugging tools like
viewing EEPROM during execution and such features are crucial for development.

Testing and Debugging

The functionality code of a project works better if the requirements are introduced in
stages. The first would be testing if the LCD is configured correctly by displaying a
simple string before adding values read from ADCs. To make sure that the ADC is
responsive you measure the voltage across the reference pin and the ground pin, or
the power pin and it must correspond with the way it is varied or tuned.

To make sure that the EEPROM is logging correctly an USART will be added, and it
will display data as it is logged on the EEPROM and it will be used to read the data
logged in a decimal form instead of the hexadecimal format which the EEPROM
stores the data in.

System Design

Requirement Analysis

This project was designed to meet specific functional and technical requirements
relevant to embedded environmental monitoring systems:

• Accuracy: The system must provide precise temperature readings within a


±1°C margin.
• Logging Efficiency: Only significant temperature shifts (>4°C in an hour)
should trigger data storage, minimizing EEPROM wear.

• User Readability: Display must present time and temperature clearly and
update in near real-time.

• Hardware Simplicity: The system should use a minimal number of


components and leverage I2C where possible to reduce wiring complexity.

• Scalability: The firmware must be modular, allowing the future addition of


wireless modules or external memory.

• Power Considerations: While not simulated in Proteus, the system should


be efficient enough for battery-powered deployment.

• Environmental Range: The current configuration is suitable for 0°C–100°C


environments, with limitations noted for sub-zero applications.

Circuit Simulation and Implementation

The system is made up of the following components:

• ATmega328P which handles data processing and storage. This


microcontroller has an internal EEPROM which will be used to log the
temperature and time.
• LM35 modules will provide analogue values of temperature that will be
digitised through analogue-to-digital conversion.
• DS3232 real time clock (RTC) will keep track of time and to also display it on
the LCD.
• I2C LCD (PCF8574 based 20x4) which will used to display time and
temperature

These components are chosen because of their compatibility and efficiency. The
LCD and the RTC will be configured in a I2C protocol configuration minimising the
connections that will be going to the microcontroller. Therefore, that means the
PCF8574 and the DS3232 will be connected to I2C pins SDA and SCL and the LM35
will be connected to ADC pin of the ATmega328P
Circuit Diagram

Figure 1: The circuit as seen from Proteus.

Firmware Implementation

The sequence at which the firmware will be applied needs to follow a certain order
for some functionalities otherwise the code might not work as intended. The
sequence which we will follow starts with setting the microcontroller itself which is a
stage that involves defining the frequency and setting the pinout. In this case since
we will be only simulating Proteus instead of using a CPU frequency of 16MHz,
which applies for the ATmega328P hardware, we used 1MHz. The address of the
PCF8574 I2C module used to communicate with LCD is also stated as determined

#define F_CPU 1000000UL


#define PCF8574_ADDR 0x4E // (0x27 << 1) for Write Mode
#define DS3232_ADDR 0xD0
#define TEMP_THRESHOLD 4
by the configuration of the address pins of the module. The PCF8574 address above
is basically the first address in the I2C mode, which is 27 in hex and it’s a 7-bit
address and then the least significant is added to determine whether the module will
operate as read or write function, read is 1 and write is 0. Therefore, the address
0x4E is 0x27 shifted one bit to the left and a zero added in the LSB to configure for
writing. It is worth noting that the address configuration in I2C inverts the bits thus
the PCF8574 address pins are technically 000 in binary however the address is
interpreted as 111 in the position of those bits. The DS3232 counter address is also
configure similarly. Another value that will remain constant whenever we apply it is
the temperature threshold value hence, we also define it in preamble section of the
code.

After macro definitions the next step is defining the required libraries for your project
and for those functions that do not have libraries readily available you have to define
the functions on the code, or you can create a library yourself. In the code I opted to
define the functions in the code instead of going for creating my own library.

#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <stdio.h>
// I2C Function Prototypes
void I2C_Init(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Write(uint8_t data);
uint8_t I2C_ReadACK(void);

// LCD Function Prototypes


void LCD_SendCommand(uint8_t cmd);
void LCD_SendData(uint8_t data);
void LCD_Init(void);
void LCD_SendString(const char *str);
void LCD_SetCursor(uint8_t row, uint8_t col);

//LM35 Function Prototypes


void ADC_Init(void);
uint16_t ADC_Read(uint8_t channel);
void DisplayTemperature(float temperature);

//DS3232 Function Prototypes


void DS3232_ReadTime(uint8_t *hour, uint8_t *minute, uint8_t *second);
uint8_t BCD_to_Dec(uint8_t bcd);
void DisplayTime(uint8_t hour, uint8_t minute, uint8_t second);
uint8_t Dec_to_BCD(uint8_t dec);

//EEPROM Function Prototypes


void EEPROM_LogTemperature(uint8_t hour, uint8_t minute, uint8_t temp);
void EEPROM_ReadLog(void);
It is important to declare function prototypes because then you don’t have to follow a
strict sequence when declaring your functions if they are declared earlier in the code
they will be known to the compiler.

void I2C_Init(void) {
// Set SCL and SDA as output
TWBR = 72; // Set I2C clock (100kHz for 16MHz CPU)
}

void I2C_Start(void) {
TWCR = (1 << TWSTA) | (1 << TWEN) | (1 << TWINT); // Start condition
while (!(TWCR & (1 << TWINT))); // Wait for completion
}

void I2C_Stop(void) {
TWCR = (1 << TWSTO) | (1 << TWEN) | (1 << TWINT); // Stop condition
}

void I2C_Write(uint8_t data) {


TWDR = data;
TWCR = (1 << TWEN) | (1 << TWINT); // Start transmission
while (!(TWCR & (1 << TWINT))); // Wait for completion
}

uint8_t I2C_ReadACK(void) {
TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWEA);
while (!(TWCR & (1 << TWINT)));
return TWDR;
}

uint8_t I2C_ReadNACK(void) {
TWCR = (1 << TWEN) | (1 << TWINT);
while (!(TWCR & (1 << TWINT)));
return TWDR;
}}

In order to facilitate communication between the ATmega328P microcontroller and


I2C-based peripherals such as the LCD module and the DS3232 RTC, a set of low-
level I2C functions were implemented. These functions allow the system to initiate
communication, transmit data, and receive responses in compliance with the I2C
protocol.

The I2C_Init() function configures the I2C clock speed by setting the Two-Wire Bit
Rate Register (TWBR). With a CPU clock of 16 MHz, the TWBR value was selected
to achieve a standard 100 kHz I2C communication speed. This ensures compatibility
with typical I2C devices while balancing speed and reliability.

The I2C_Start() function generates a start condition on the I2C bus by setting the
appropriate control bits in the Two-Wire Control Register (TWCR). It waits until the
start condition is transmitted before proceeding, ensuring that the bus is properly
engaged before any communication takes place.

Similarly, the I2C_Stop() function issues a stop condition to terminate


communication with the current slave device. This ensures that the bus is properly
released for other operations or subsequent communication cycles.

Data transmission is handled by the I2C_Write() function. It loads a data byte into
the Two-Wire Data Register (TWDR) and initiates the transfer by manipulating
TWCR. The function waits until transmission is complete before returning,
guaranteeing that each byte is successfully sent before the next action is taken.

For reading operations, two functions are provided: I2C_ReadACK() and


I2C_ReadNACK(). The I2C_ReadACK() function reads a byte from the bus and
sends an acknowledgment (ACK) back to the slave, signalling readiness to receive
more data. In contrast, I2C_ReadNACK() reads a byte without sending an
acknowledgment (NACK), typically used to signal the end of a multi-byte read
sequence. Both functions ensure proper synchronization with the slave device during
read operations.

Together, these functions establish a complete, reliable framework for I2C


communication in the system. They were carefully verified during pre-integration and
post-integration testing phases to ensure compatibility with the LCD and RTC
modules, thereby forming a crucial part of the system’s firmware infrastructure.

The ADC_Init function is for initialising the ADC, it starts by setting the REFS0 bit of
the ADMUX register to 1 which configures the ADC to use the microcontrollers’ V CC
as the reference voltage. Then from the ADCSRA the ADC is enabled and a
prescaler of 128 is set.by setting all ADPS# bits to 1s.

To obtain stable analogue measurements from the LM35DZ sensor, a dedicated


function was implemented to configure and initiate ADC conversions on the
ATmega328P. The function, ADC_Read(uint8_t channel), first selects the
appropriate ADC channel by masking and updating the lower three bits of the
ADMUX register. It then starts the analogue-to-digital conversion by setting the
ADSC bit in ADCSRA. The function enters a blocking loop that waits until the
conversion is complete, indicated when the ADSC bit clears. Finally, the function
returns the converted 10-bit digital value from the ADC data register. This low-level
control approach ensured precise and reliable analogue sampling, critical for
accurate temperature measurements.

void ADC_Init(void) {
ADMUX = (1 << REFS0); // Select AVcc as reference
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
// Enable ADC, prescaler 128
}
uint16_t ADC_Read(uint8_t channel) {
ADMUX = (ADMUX & 0xF8) | channel; // Select ADC channel
ADCSRA |= (1 << ADSC); // Start conversion
while (ADCSRA & (1 << ADSC)); // Wait for conversion to finish
return ADC;
}

The EEPROM_ReadLog() function sequentially reads stored entries from the


EEPROM, starting from address 2. Each logged entry consists of three bytes: the
hour, minute, and temperature reading at the time of logging. Data is formatted into
readable strings and transmitted over the USART interface. To ensure efficiency, the
reading process automatically terminates upon detecting an uninitialized EEPROM
byte (0xFF), indicating the end of valid data. This mechanism allows the device to
safely retrieve all historical records without risking out-of-bounds memory access.

To facilitate continuous data recording, the EEPROM_LogTemperature(uint8_t


hour, uint8_t minute, uint8_t temp) function was implemented. This function reads
the current memory pointer (stored at address 0), logs the new temperature entry
(hour, minute, and temperature) sequentially, and updates the pointer for the next
write operation. This method guarantees that data entries are stored contiguously
and minimizes the risk of memory fragmentation. Care was taken to avoid
overwriting the pointer area (address 0 and 1) by reserving the first two bytes of
EEPROM space.
void EEPROM_LogTemperature(uint8_t hour, uint8_t minute, uint8_t temp) {
uint8_t eeprom_addr = 2;
uint8_t addr = eeprom_read_byte(&eeprom_addr);

eeprom_write_byte((uint8_t*) addr, hour);


eeprom_write_byte((uint8_t*) (addr + 1), minute);
eeprom_write_byte((uint8_t*) (addr + 2), temp);

addr += 3;
eeprom_write_byte(&eeprom_addr, addr);
}

void EEPROM_ReadLog() {
uint8_t addr = 2;
UART_SendString("\nTemperature Log\r\n");

while (addr < 100) { // Limit check


uint8_t hour = eeprom_read_byte((uint8_t*)(uintptr_t) addr);
uint8_t minute = eeprom_read_byte((uint8_t*) (addr + 1));
uint8_t temp = eeprom_read_byte((uint8_t*) (addr + 2));

if (hour == 0xFF) break; // Stop when reaching uninitialized EEPROM

char buffer[32];
sprintf(buffer, "Time: %02d:%02d Temp: %dC\r\n", hour, minute, temp);
UART_SendString(buffer);

addr += 3;
_delay_ms(1);
}
}

void EEPROM_PrintLastLog() {
uint8_t current_addr = eeprom_read_byte((uint8_t*)0); // Log pointer is at
address 0

if (current_addr < 3 || current_addr == 0xFF) return;

uint8_t addr = current_addr - 3; // Last full log starts 3 bytes back

uint8_t hour = eeprom_read_byte((uint8_t*)(uintptr_t)addr);


uint8_t minute = eeprom_read_byte((uint8_t*)(addr + 1));
uint8_t temp = eeprom_read_byte((uint8_t*)(addr + 2));

if (hour == 0xFF || minute == 0xFF || temp == 0xFF) return;

char buffer[32];
sprintf(buffer, "Time: %02d:%02d" " Temp: %d\xB0""C\r\n", hour, minute,
temp);
UART_SendString(buffer);
}

Additionally, the EEPROM_PrintLastLog() function was developed to retrieve and


display only the most recent log entry. By referencing the previous three bytes
relative to the current memory pointer, the function extracts and outputs the last
recorded hour, minute, and temperature. This feature is useful for quick verification
without the need to traverse the entire log history.
These EEPROM management routines collectively ensure reliable storage of critical
data, maintaining consistency between real-time temperature monitoring and logged
historical records. Special considerations such as detecting the end of initialized
memory and managing the EEPROM pointer were incorporated to maintain data
integrity throughout device operation.

The main() function orchestrates the initialization and continuous operation of the
temperature logging system. It begins by invoking the initialization routines for the

int main(void) {

I2C_Init();
LCD_Init();
ADC_Init();
UART_Init();

EEPROM_ReadLog();

DS3232_SetTime(23, 59, 30);

// Display Test Message


LCD_SendCommand(0x01); // Clear screen
_delay_ms(2);
LCD_SetCursor(0,1);
LCD_SendString("Temp Logger Ready");
_delay_ms(1000);
LCD_SendCommand(0x01);
_delay_ms(2);
LCD_SetCursor(1,0);
LCD_SendString("Time: ");
LCD_SetCursor(2,0);
LCD_SendString("Temp: ");

uint8_t hour, minute, second;


float prev_temp = 0;

while (1) {

DS3232_ReadTime(&hour, &minute, &second);

DisplayTime(hour, minute, second);


// Infinite loop (Can add temperature/time logic later)
uint16_t adc_value = ADC_Read(0); // Read ADC0 (LM35)
float temperature = (adc_value * 5.0 / 1024.0) * 100.0;

// Display Temperature
DisplayTemperature(temperature);

if (fabs(temperature - prev_temp) >= TEMP_THRESHOLD) {


EEPROM_LogTemperature(temperature, hour, minute);
prev_temp = temperature;
}

_delay_ms(1000);
}
}
core modules, namely I2C_Init(), LCD_Init(), ADC_Init(), EEPROM_Init(), and
UART_Init(). These setups ensure that communication interfaces, data acquisition
units, and storage modules are properly configured before normal operation begins.

After initialization, EEPROM_ReadLog() is called to retrieve and display any


previously stored temperature data via UART. A single call to DS3232_SetTime() is
included to manually set the real-time clock to a known starting value for testing
purposes. This setting is only necessary during the first deployment or after resetting
the RTC.

Following setup, the LCD is prepared with a welcome message ("Temp Logger
Ready"), giving visual feedback that the system has booted correctly. After a brief
delay, the LCD is cleared again, and static labels ("Time:" and "Temp:") are
positioned to reserve spaces for dynamic updates.

Within the infinite while(1) loop, the program continually reads the current time from
the DS3232 RTC using DS3232_ReadTime(), and measures the analogue signal
from the LM35 temperature sensor via the ADC_Read() function. The ADC result is
then converted into a human-readable temperature value in degrees Celsius.

Real-time display updates are handled by the DisplayTime() and


DisplayTemperature() functions, which refresh the LCD content based on the latest
time and temperature values. To optimize EEPROM usage and minimize redundant
writes, the system only logs temperature values when the difference between the
current reading and the previously stored value exceeds a specified threshold of 4°C
(TEMP_THRESHOLD). When such a change is detected,
EEPROM_LogTemperature() is called to store the timestamp and corresponding
temperature value, followed by EEPROM_PrintLastLog() to confirm the logging
action through UART.

The loop concludes with a 1-second delay (_delay_ms(1000)), setting the update
and monitoring cycle frequency to once per second. This design ensures timely data
acquisition while avoiding excessive resource usage, resulting in a reliable and
efficient embedded logging system.
Limitations & Applicability

Limitations

Limited EEPROM Capacity and Lifespan

The internal EEPROM of the ATmega328P is only of 1KB in size and this limits it to
only 341 entries of hour, minute and temperature readings. When using this system
as a long-term application it will require that older data gets overwritten to
accommodate for new data. The EEPROM also a finite lifespan of 100000
write/erase cycles therefore this is a limited timespan solution.

Inability to Measure Negative Temperatures

The circuit is configured through a direct connection of the LM35 to the ADC and this
configuration does not accommodate for measuring negative temperatures, reading
temperatures requires additional complicated components and firmware
configuration.

EEPROM Write Speed and Task Blocking

EEPROM writes are slow compared to RAM speed and this might cause the logging
process to block other time sensitive tasks if a diligent approach is not applied in the
sequence of implementing the tasks.

Lack of Data Integrity and Wear Management Features

The EEPROM also doesn’t support checksums and error correction which means
when the data gets corrupted there is no way of telling. The other feature which is
not accommodated for by the ATmega238P on the memory logging is the wear-
levelling of the EEPROM which will result in risk of unreliability in the long term.

Simulation Inaccuracy of RTC Timing

The DS3232 RTC tends to count a tad quicker in simulation environment and this is
mainly due to Proteus’ time emulation model limitations. This however is not the case
with an actual DS3232 hardware component which is highly accurate with a
temperature compensated crystal oscillator.
Firmware Does Not Compensate for Hardware Limitations

The coding approach applied is design-focused hence it does not compensate for
hardware limitations that can be addressed through software. There is the issue of
the EEPROM size which typically the viable solution would be to configure it to
overwrite old data once all addresses have been used up however, I will not
implement this as I believe extending the memory size is the best solution. The same
will apply to wear levelling techniques, I will not implement any since I believe
hardware solutions are the best solution and even address the problem for long term
solutions.

Applicability
This embedded system showcases several design principles and integration
strategies that can be applied in other domains:

Use of I2C Communication Protocol:


The decision to use I2C allowed multiple peripherals (RTC and LCD) to
communicate over a shared two-wire bus, reducing wiring complexity and conserving
I/O pins. This approach is highly scalable and applicable to more complex systems
such as environmental monitoring networks, where multiple sensors and modules
need to operate concurrently without expanding hardware complexity.

Modular Component Integration:


The system integrates discrete modules — a temperature sensor (LM35), a real-time
clock (DS3232), and a display unit (PCF8574-based I2C LCD). This modular
approach allows for easy upgrades, replacements, or extensions. For instance,
replacing the LM35 with a humidity sensor or extending the EEPROM functionality to
an external memory chip makes the system adaptable for broader applications like
smart agriculture, cold-chain logistics, or industrial process monitoring.

Threshold-Based Event Logging:


Logging only when a significant temperature change (exceeding 4°C within an hour)
is detected optimizes memory usage and reduces unnecessary writes to EEPROM.
This strategy is applicable in power-sensitive or storage-limited applications, such as
remote weather stations, battery-powered data loggers, or spacecraft
instrumentation, where efficiency is critical.
Real-Time Monitoring with Timestamping:
The combination of time-aware data logging using an RTC enhances the traceability
of events. This is applicable in safety-critical systems like food safety monitoring,
server temperature control, and pharmaceutical storage where logged data must be
accompanied by accurate timestamps for compliance and diagnostics.

Simulation Before Hardware Deployment:


Simulating the system in Proteus before actual implementation ensured design
correctness and reduced the risk of hardware damage. This method supports rapid
prototyping and debugging, making it suitable for academic research, industrial
design testing, and educational purposes where physical hardware may be limited.

Use of Internal EEPROM for Local Storage:


Although limited in size, internal EEPROM provides non-volatile storage without
external components. In other applications where temporary or low-frequency
logging is needed (e.g., event counters, boot logs, or factory configuration settings),
this approach remains cost-effective and reliable.

Embedded C Programming:
The use of C allows for direct hardware control and efficient resource management,
making the approach applicable to bare-metal programming, firmware development
for wearable devices, consumer electronics, and real-time industrial control systems.

Relation between Limitations & Applicability


While the system demonstrates sound integration and reliable functionality within a
simulated environment, its limitations shape — but do not invalidate — its broader
applicability. Below is a reflection on how these limitations relate to and inform the
potential use of this system in various contexts:

Limited EEPROM Size (1KB) and Endurance (~100,000 Writes)


Although internal EEPROM is sufficient for short-term or threshold-based logging, it
constrains the system’s suitability for long-term or high-frequency data logging
without external memory expansion. However, by selectively logging only significant
temperature changes, this limitation is mitigated, making the system practical for
applications like daily environmental monitoring or infrequent event-based logging in
remote or embedded locations.
Lack of EEPROM Error Detection/Correction Mechanisms
EEPROM in ATmega328P lacks built-in checksums or error correction, posing a risk
to data integrity in critical applications. While this limits its standalone reliability in
sensitive systems (e.g., medical devices), it remains applicable in non-critical
environments where occasional data corruption does not compromise safety or
performance — or where software-level validation can be later added.

Inability to Log Negative Temperatures Using Current LM35 Configuration


Since the LM35 sensor is biased to output 0V at 0°C, it cannot record sub-zero
values in this setup. This restricts the system’s use in cold storage, outdoor winter
monitoring, or certain industrial environments. Nonetheless, in regions or
applications where temperatures remain above freezing (greenhouses, indoor labs,
or server rooms), the system remains fully applicable.

RTC Drift Observed in Simulation


The slight acceleration of timekeeping in the simulated DS3232 RTC module is a
simulation-specific issue. On real hardware, the RTC performs accurately due to its
integrated temperature-compensated crystal. This indicates that the system is more
dependable in physical deployment than what the simulation suggests.

EEPROM Does Not Automatically Overwrite Full Memory:


Without firmware support for memory cycling or offloading, the system stops logging
once EEPROM capacity is reached. This limits autonomous, long-duration
deployments. However, in controlled environments where logs are periodically
extracted, or in academic setups, this constraint can be managed manually or
through planned resets.

Simulation Constraints (No EEPROM Visibility or RTC Battery Simulation):


Proteus limitations prevented direct testing of EEPROM contents and battery backup
behavior. This affects validation completeness. Still, the system's core logic remains
testable, and such limitations are non-existent in actual hardware. Therefore, these
constraints are mainly relevant during development and not in real-world use.

Firmware Design Choices (e.g., No EEPROM Overwrite Logic):


The current firmware does not implement memory management such as circular
logging or dynamic address tracking. This simplifies development but reduces
system resilience for prolonged deployment. Despite this, it serves as a strong
foundation for systems where logging needs are limited, or where manual log
management is acceptable.

Use of Static Threshold (4°C) for Logging:


A fixed threshold may not suit all environments — some applications might require
finer granularity. However, this approach is suitable in scenarios where only
significant deviations are of interest (e.g., detecting overheating, rapid cooling
events, or anomaly alerts).

Testing

The development and testing of this embedded temperature monitoring and logging
system followed a modular, layered approach. The tests and implementation will
begin with most basic output functionalities and then integrating progressive
functionalities and components as we move forward.

The initial phase of development is focused on integrating the I2C LCD with the MCU
and testing that its configured right to display basic data in string format. Before
introducing any dynamic values from the ADC readings or counters, it was important
to make sure that I2C module and the LCD are correctly connected. It is important to
know which address to use for your I2C module as it depends on how you have
connected your address pins for the module and if the code does not use the right
address you will fail to reach to it. I have come to notice that the address for Proteus
simulation is 0x27 whereas for the actual hardware when configured similarly its
0x3F. The other challenge that surfaced was the LCD not displaying and turns out
there was a need for a delay during the initialisation of the I2C LCD otherwise some
commands and data would overlap each other before some functions are
implemented. When the timing issues and addresses have been corrected the string
format data was displayed and then the system was ready for displaying real-time
updated data from the ADC and the RTC.

Once the LCD has proven to be functional and operating as expected, the next
logical addition to the system is displaying the clock using the RTC module. The
code can be used to set the time and in reality the DS3232 has to have a battery
keep the clock running even when other components are not operational.
Following successful clock display, attention shifted to reading analogue values from
the LM35DZ sensor through the ADC0 channel. The goal during pre-integration was
to capture the raw ADC value and display it directly on the LCD to verify the
sampling process. Pre-integration testing revealed fluctuating readings that did not
align with the expected voltage from the sensor. Investigation showed that an
incorrectly set ADC prescaler were the causes. Implementing a prescaler of 128
corrected the readings. Once these modifications were integrated, the ADC value
remained consistent and could be updated on the LCD every second without display
artifacts.

Once satisfied with the ADC value display, the next logical step was to convert these
values into meaningful temperature data. The LM35DZ outputs 10 mV per °C, and
the ADC of the ATmega328P with a 5V reference and 10-bit resolution produces a
step size of approximately 4.88 mV. This meant that the raw ADC value needed to be
multiplied by 0.488 to convert it into °C. Pre-integration testing involved writing this
conversion in C and confirming output correctness via USART. The biggest
challenge during this stage was rounding errors due to integer division. To address
this, floating-point arithmetic was used temporarily to validate results, after which a
fixed-point approximation was adopted for efficiency. Post-integration testing showed
accurate real-time temperature values displayed on the LCD, matching those
obtained through simulation and multimeter validation

Once temperature acquisition was reliable, attention turned to EEPROM logging.


The goal was to store temperature values alongside timestamps whenever a change
of 4°C or more occurred within an hour. Pre-integration testing focused on writing
and reading single-byte values to and from the EEPROM, confirming data
persistence across resets. One challenge faced was the management of EEPROM
wear and memory address overflow. This was addressed by implementing a simple
pointer system that rotated through memory addresses and avoided writing
duplicates. After integration, EEPROM logging worked as intended: temperature
changes were successfully captured with their timestamps and retained even after
power loss.

The final integration phase involved using the USART to transmit significant
temperature variations—defined as a 4°C or more change—and to cross-verify that
the EEPROM and LCD were synchronized in real time. Pre-integration USART
testing included displaying basic strings and temperature data on a serial terminal.
Interrupt-driven USART transmission was added to reduce blocking behavior. A key
challenge was ensuring that USART output did not conflict with LCD updates,
particularly when both used data derived from the same ADC readings. This was
resolved by introducing a data buffering scheme and synchronizing display refresh
cycles. Final testing showed that whenever a qualifying temperature change
occurred, both the LCD and EEPROM updated simultaneously, and the USART
accurately reflected this event on the serial monitor.

Results
LCD Display

• The LCD module reliably displayed real-time temperature and clock readings
with an update rate of 1 second.
• No character flickering, ghosting, or communication errors were observed
during simulation.
• Display layout remained stable with dynamic data updates throughout testing.

Temperature Acquisition and Processing

• Temperature readings obtained from the LM35DZ sensor through the ADC0
channel were consistent and stable.
• ADC configurations with a prescaler of 128 effectively reduced noise and
provided smooth readings.
• Temperature conversions from ADC values matched expectations based on
theoretical calculations and virtual voltmeter checks within Proteus.

EEPROM Logging

• The EEPROM correctly logged temperature entries whenever a temperature


change of 4°C or more occurred within an hour.
• Data persisted across simulated resets, confirming correct read/write
operations.
• No address overflows or overwrites were observed during standard test
durations.

Figure 2: EEPROM Memory (values in hexadecimal)

USART Communication

• Serial communication accurately reflected real-time temperature updates and


significant changes as expected.
• No USART data loss or synchronization issues were detected between
transmissions and LCD/EEPROM updates.
Figure 3: Temperature Log Terminal

RTC Performance

• The DS3232 RTC module maintained accurate clock readings throughout the
simulation.
• Minor timing acceleration due to Proteus simulation behavior was observed
but was consistent and did not impact system functionality.

GA5 Compliance Discussion

This project aligns comprehensively with the ECSA GA5 outcomes, as detailed
below:
1. Applicability and Limitations of Method, Skill, or Tool

The methods and tools used throughout this project were carefully assessed for their
applicability and limitations before implementation. Proteus simulation was selected
due to its ability to model microcontroller behaviour closely without needing physical
hardware. The LM35DZ temperature sensor, EEPROM internal memory, and USART
communication were chosen based on their suitability for environmental monitoring
within the constraints of available resources. Limitations such as EEPROM wear,
simulation inaccuracies, ADC noise, and I2C communication delays were identified
and considered during the design and testing stages, as discussed under Limitations
and Applicability.

2. Correct Application of Method, Skill, or Tool

Each method and tool was applied systematically and correctly to achieve the
required result. LCD interfacing was established with verified I2C communication, the
ADC was configured with an appropriate prescaler to stabilize analogue readings,
temperature values were accurately calculated using proper scaling from ADC
readings, and EEPROM writes were conditioned to prevent unnecessary memory
wear. USART communication was integrated in a non-blocking manner to ensure
real-time operation. These correct applications led to a fully functional system, as
documented in Section 8.

3. Testing and Assessment of Results

Testing was conducted both at the subsystem level and at the full system integration
level. Each module was independently verified before integration, and their
combined performance was tested to ensure seamless operation. System outputs
such as LCD displays, EEPROM contents, and USART serial outputs were cross-
verified for consistency and correctness. Furthermore, a comparative analysis was
performed to evaluate system behavior under different update delays (1 second vs.
300ms), reinforcing the assessment of timing trade-offs. All results met the intended
functional requirements of the project.
4. Computer Applications Created, Selected, and Used

Proteus was used extensively to create a virtual simulation environment for the
embedded system, replacing the need for immediate physical prototypes.
Additionally, microcontroller firmware was developed in C, leveraging custom I2C
libraries, EEPROM management functions, ADC configuration, and USART routines.
The disciplined use of these tools enabled successful completion of the project
objectives. The choice of applications and tools directly supported the project goals,
confirming the fulfillment of GA5 expectations.

Overall, the project not only achieved its technical aims but also systematically
adhered to professional engineering practices aligned with ECSA's GA5 competency
outcomes.

Conclusion

The development, simulation, and testing of this embedded temperature logging


system provided an in-depth opportunity to practice and refine critical embedded
systems engineering skills. Starting with foundational tasks like LCD interfacing and
advancing through complex multi-peripheral integration involving ADCs, EEPROM
memory, USART communication, and RTC time synchronization, the project
showcased a disciplined, modular approach to embedded design.

Subsystems were tested incrementally, ensuring that early-stage challenges such as


I2C addressing faults, ADC noise, EEPROM wear, and USART timing conflicts were
systematically identified and resolved. Proteus simulation tools were used
throughout to validate the design, offering a controlled environment for both
functional and stress testing. The ultimate success of the integrated system — with
real-time LCD updates, accurate temperature measurements, intelligent EEPROM
logging based on a 4°C threshold, and synchronized USART outputs — confirmed
the robustness of the design methodology.

In conclusion, this project successfully achieved its technical goals while


demonstrating a responsible and systematic approach to engineering practice. The
methods, skills, and tools applied were carefully assessed for their applicability and
limitations, ensuring they were well-suited for the project’s objectives. Each
technique was applied correctly, leading to a functional and reliable system.
Rigorous testing and assessment confirmed that the results met the desired
specifications and functional requirements. The use of computer applications,
including the Proteus simulation and custom-developed firmware, was both
intentional and appropriate, enhancing the design process. Overall, this project not
only fulfilled the required outcomes but also adhered to professional engineering
standards as outlined in ECSA’s GA5, ensuring a robust foundation for future
developments in embedded systems.

You might also like