0% found this document useful (0 votes)
22 views83 pages

Spring 23

ZcZczc

Uploaded by

ayonpc590
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views83 pages

Spring 23

ZcZczc

Uploaded by

ayonpc590
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 83

SPRING 23

Answer to question no 2

2a) ### Differences between Microprocessor and Microcontroller

1. *Definition*:

- *Microprocessor*: It is the central unit of a computer system, mainly responsible for performing
computational tasks. It lacks peripheral support and requires external components (like memory and
I/O) to function.

- *Microcontroller*: It is a compact integrated circuit designed for specific control applications. It


combines a processor with internal memory (RAM, ROM) and peripherals, making it a complete, self-
contained system.

2. *Components*:

- *Microprocessor*: Requires external components like RAM, ROM, and I/O devices for functioning.

- *Microcontroller*: Contains CPU, memory, and peripherals (I/O, timers, etc.) in a single chip.

3. *Applications*:

- *Microprocessor*: Used in systems where extensive computation and multitasking are needed, like
computers.

- *Microcontroller*: Ideal for embedded systems with specific tasks, like automotive controls, home
appliances, and remote controls.

4. *Power Consumption*:

- *Microprocessor*: Generally higher as it’s designed for high-performance tasks.

- *Microcontroller*: Lower, optimized for applications needing power efficiency.

5. *Cost*:

- *Microprocessor*: Typically more expensive due to the need for additional components.

- *Microcontroller*: Generally cost-effective as it integrates multiple components in one chip.

---
### Memory Layout Diagrams for ATmega328P

The ATmega328P Microcontroller has several distinct memory blocks:

1. *Program Memory (Flash Memory)*: This is non-volatile memory used to store the program code.

2. *Data Memory (SRAM)*: Volatile memory used for variables and temporary data storage.

3. *EEPROM*: Non-volatile memory used to store data that must be retained even after power-off.

These memory blocks are mapped within the microcontroller’s address space, allowing efficient access
by the CPU and peripherals.

---

### Prime and Alternate Functions of PORTB, PORTC, and PORTD on ATmega328P

1. *PORTB*:

- *Prime Functions*: General-purpose I/O pins (PB0 to PB7).

- *Alternate Functions*:

- PB0 to PB5: Can be used as MOSI, MISO, SCK, SS for SPI communication.

- PB6, PB7: Used as crystal oscillator pins XTAL1 and XTAL2 for clock input.

2. *PORTC*:

- *Prime Functions*: General-purpose I/O pins (PC0 to PC6).

- *Alternate Functions*:

- PC0 to PC5: Used for ADC inputs (ADC0 to ADC5) in analog-to-digital conversion.

- PC6: RESET pin, also used for resetting the microcontroller.

3. *PORTD*:
- *Prime Functions*: General-purpose I/O pins (PD0 to PD7).

- *Alternate Functions*:

- PD0, PD1: UART communication (RXD, TXD).

- PD2, PD3: External interrupt pins (INT0, INT1).

- PD5, PD6: Used for PWM output (OC0B, OC0A).

- PD7: PWM output (OC2).

2(b) The ATmega328P microcontroller integrates various hardware modules designed for embedded
control applications. These include:

1. *CPU (Central Processing Unit)* - The core processing unit.

2. *Flash Memory* - 32 KB of program memory.

3. *SRAM (Static RAM)* - 2 KB of data memory for temporary storage.

4. *EEPROM (Electrically Erasable Programmable Read-Only Memory)* - 1 KB for non-volatile data


storage.

5. *I/O Ports (PORTB, PORTC, PORTD)* - Configurable general-purpose input/output pins.

6. *Timers/Counters*:

- Timer/Counter0: 8-bit timer with PWM capability.

- Timer/Counter1: 16-bit timer with PWM capability.

- Timer/Counter2: 8-bit timer with PWM capability.

7. *ADC (Analog-to-Digital Converter)* - 10-bit ADC with 6 input channels on PORTC for converting
analog signals.

8. *USART (Universal Synchronous/Asynchronous Receiver Transmitter)* - Serial communication


module.

9. *SPI (Serial Peripheral Interface)* - Synchronous serial communication.

10. *I²C (Two-Wire Interface)* - Also called TWI, for communication with other devices.

11. *Watchdog Timer* - Used to reset the system in case of a malfunction.

12. *Analog Comparator* - Compares two analog voltages and outputs a digital signal.

13. *Interrupt System* - Provides internal and external interrupt handling.

14. *Clock Oscillator* - Supports internal and external oscillators for the system clock.
These modules make the ATmega328P versatile for various control and automation applications.

2(c) To convert the given C++ code into assembly code for the ATmega328P, let's first understand the
code and then break it down into the corresponding assembly instructions.

### C++ Code:

cpp

byte y1 = 0x65;

byte y2 = 0x73;

byte y = y1 | y2;

In this C++ code:

- y1 is assigned the value 0x65 (which is 01100101 in binary).

- y2 is assigned the value 0x73 (which is 01110011 in binary).

- The bitwise OR operation | is performed between y1 and y2, and the result is stored in y.

---

### ATmega328P Assembly Code:

The ATmega328P assembly code for this would use registers for y1, y2, and the result y. We will use
general-purpose registers (r16, r17, and r18 for example).

asm

; Load immediate values into registers

ldi r16, 0x65 ; Load y1 (0x65) into register r16

ldi r17, 0x73 ; Load y2 (0x73) into register r17


; Perform bitwise OR operation

or r16, r17 ; Perform r16 = r16 | r17

; Store the result in y (using r16)

mov r18, r16 ; Move the result into register r18 (which will represent y)

### Explanation:

1. **ldi r16, 0x65**: Load the value 0x65 (binary: 01100101) into register r16.

2. **ldi r17, 0x73**: Load the value 0x73 (binary: 01110011) into register r17.

3. **or r16, r17**: Perform a bitwise OR between the values in registers r16 and r17, and store the
result back in r16. The result of 01100101 | 01110011 will be 01110111 (which is 0x77).

4. **mov r18, r16**: Move the result of the OR operation from r16 to r18, which is the register
representing y.

The final result of y will be 0x77 after the bitwise OR operation.

Answer to question no 3

Here's a breakdown and explanation of each code, line by line, for each question:

---

Question 3(a)

Objective: Toggle an LED state every time a button is pressed or released.

Code Explanation:
const int buttonPin = 4; // Pin connected to SW1

const int ledPin = 5; // Pin connected to LED

int ledState = LOW; // Current state of the LED (initially off)

int buttonState; // Current state of the button

int lastButtonState = LOW; // Previous state of the button (initially off)

void setup() {

pinMode(buttonPin, INPUT); // Set buttonPin (SW1) as an input

pinMode(ledPin, OUTPUT); // Set ledPin as an output

void loop() {

buttonState = digitalRead(buttonPin); // Read the current button state

if (buttonState != lastButtonState) { // Check if button state has changed

if (buttonState == HIGH) { // If button is pressed (HIGH state)

ledState = !ledState; // Toggle the LED state

digitalWrite(ledPin, ledState); // Set the LED to the new state

delay(50); // Short delay to debounce button

lastButtonState = buttonState; // Update lastButtonState to current

Explanation of Key Parts:

1. Variables Setup:
buttonPin and ledPin store the pin numbers for the button (SW1) and LED.

ledState holds the current state of the LED (LOW = off, HIGH = on).

buttonState and lastButtonState track the current and previous states of the button.

2. setup() Function:

pinMode(buttonPin, INPUT); sets the button pin as an input.

pinMode(ledPin, OUTPUT); sets the LED pin as an output.

3. loop() Function:

buttonState = digitalRead(buttonPin); reads the current state of the button.

if (buttonState != lastButtonState) checks if the button state has changed (pressed or released).

if (buttonState == HIGH) checks if the button is pressed. When pressed, it toggles the LED state using
ledState = !ledState; (inverts the state) and writes the new state to the LED pin.

delay(50); is a debounce delay to prevent the button from being detected multiple times due to
mechanical bouncing.

lastButtonState = buttonState; updates the previous state for the next loop.
---

Question 3(b)

Objective: Receive the string "1234" from Serial Monitor, convert it to an integer, and display it.

Code Explanation:

char inputString[5]; // Array to hold input string, 5 to include null terminator

int index = 0; // Index for filling inputString

void setup() {

Serial.begin(9600); // Initialize serial communication at 9600 baud rate

void loop() {

if (Serial.available()) { // Check if data is available to read

char receivedChar = Serial.read(); // Read a character from Serial Monitor

if (receivedChar == '\n') { // Check if the character is newline

inputString[index] = '\0'; // Null-terminate the string

int number = atoi(inputString); // Convert the string to an integer

Serial.print("Received number: ");

Serial.println(number); // Display the number


index = 0; // Reset index for next input

else {

inputString[index++] = receivedChar; // Store received character in array

Explanation of Key Parts:

1. Variables Setup:

inputString[5] is a character array to store the incoming string (e.g., "1234").

index keeps track of the position in the array where the next character will be stored.

2. setup() Function:

Serial.begin(9600); initializes serial communication with a baud rate of 9600, allowing the Arduino to
communicate with the Serial Monitor.

3. loop() Function:

if (Serial.available()) checks if there is data available from the Serial Monitor.


Serial.read() reads one character from the Serial Monitor and stores it in receivedChar.

if (receivedChar == '\n') checks if the character is a newline ('\n'). If so, it means the user finished typing
a line.

inputString[index] = '\0'; adds a null terminator to the end of the array, converting it into a proper string.

int number = atoi(inputString); converts the string (e.g., "1234") to an integer using the atoi function.

Serial.print() and Serial.println() display the converted number.

index = 0; resets the index for the next string input.

If receivedChar is not '\n', it adds the character to inputString and increments index for the next
character.

---

Question 3(c)

Objective: Read voltage from an analog pin (A3) and display it on the Serial Monitor.

Code Explanation:
const int analogPin = A3; // Pin connected to A3

float voltage = 0.0; // Variable to store the measured voltage

void setup() {

Serial.begin(9600); // Initialize serial communication at 9600 baud rate

void loop() {

int sensorValue = analogRead(analogPin); // Read analog value from A3

voltage = sensorValue * (5.0 / 1023.0); // Convert to voltage

Serial.print("Voltage at A3: ");

Serial.print(voltage);

Serial.println(" V"); // Display voltage

delay(1000); // Update every second

Explanation of Key Parts:

1. Variables Setup:

analogPin is set to A3, where the voltage is read.

voltage will store the calculated voltage value based on the analog reading.

2. setup() Function:

Serial.begin(9600); initializes serial communication with a baud rate of 9600.


3. loop() Function:

analogRead(analogPin); reads the analog value from pin A3. This value is between 0 and 1023,
representing a range from 0V to 5V.

voltage = sensorValue * (5.0 / 1023.0); converts the raw sensor value to voltage using the formula:

5.0 represents the maximum voltage.

Dividing by 1023.0 scales the raw sensor value to the voltage range.

Serial.print() and Serial.println() display the voltage reading on the Serial Monitor.

delay(1000); adds a 1-second delay to update the reading every second.

---

These explanations cover all three sketches in detail. Let me know if there’s any part you would like
further clarification on!

Answer to question no 4

Here's a solution and explanation for each part of Question 4:


---

Question 4(a)

Objective: Calculate the speed of the robot car using an encoder disc.

Explanation:

1. Components in Use:

A 25-slot encoder disc is attached between an IR transmitter and receiver. The IR sensor can detect each
slot as it passes, generating a signal every time a slot moves past it.

Each signal generated represents a fraction of one full rotation of the wheel.

2. Speed Calculation:

The wheel radius is 5 cm, so the circumference of the wheel .

cm.

Since there are 25 slots, each slot passing through the IR sensor corresponds to a movement of:

cm.
The microcontroller can calculate the speed by counting the number of slots detected in a given time
frame and multiplying by the distance per slot.

3. Code to Compute Speed:

We will set up an interrupt service routine (ISR) for the INT1 pin, which triggers every time the IR sensor
detects a slot.

The code calculates speed based on the number of interrupts over a given time period.

Arduino Sketch:

const int encoderPin = 2; // Pin connected to INT1 (digital pin 2 on most Arduino boards)

volatile int slotCount = 0; // Variable to count slots detected

const float distancePerSlot = 1.25664; // Distance moved per slot (in cm)

unsigned long prevTime = 0; // Time of the last calculation

void setup() {

pinMode(encoderPin, INPUT); // Set encoder pin as input

attachInterrupt(digitalPinToInterrupt(encoderPin), countSlot, RISING); // Trigger ISR on rising edge

Serial.begin(9600); // Initialize serial communication

}
void loop() {

unsigned long currentTime = millis(); // Get current time

if (currentTime - prevTime >= 1000) { // Calculate every 1 second

noInterrupts(); // Disable interrupts to safely access slotCount

int count = slotCount;

slotCount = 0; // Reset slot count for the next period

interrupts(); // Re-enable interrupts

float speed = count * distancePerSlot; // Calculate speed in cm/s

Serial.print("Speed: ");

Serial.print(speed);

Serial.println(" cm/s");

prevTime = currentTime; // Update time for the next calculation

void countSlot() {

slotCount++; // Increment slot count whenever the interrupt occurs

Explanation of the Code:

encoderPin is the pin connected to the IR receiver, set up to trigger an interrupt.

distancePerSlot stores the distance traveled per slot.

In loop(), the speed is calculated every second (1000 ms) by multiplying slotCount with distancePerSlot.
countSlot() is an ISR that increments slotCount each time a slot is detected by the encoder.

---

Question 4(b)

Objective: Define T-drive, D-drive, and C-drive journeys of a Taxi Meter.

For this part, you'd typically illustrate different phases of a taxi meter's journey as line diagrams. Each
drive type can represent a phase or type of operation in a taxi meter:

1. T-drive (Trip Drive):

This could represent the start of a journey when the taxi meter begins to charge.

In a line diagram, it would show an initial steady state, transitioning to active charging state upon
starting the trip.

2. D-drive (Distance Drive):

Represents distance-based charging where fare increases based on the distance traveled.

In the line diagram, you would see a step-wise increase in fare as distance increases.
3. C-drive (Cruise Drive):

Represents time-based fare increment, often used when the taxi is stationary but waiting.

In the line diagram, the fare would increase over time while the distance remains constant.

Note: The actual line diagrams would illustrate these modes visually as timelines or fare increment
trends.

---

Question 4(c)

Objective: Implement LED blinking using a class-based approach, where ioDir(), onLED(), and offLED()
control the LED's behavior.

Code Explanation:

To achieve this, we’ll define a class with methods ioDir() to set the LED direction, onLED() to turn it on,
and offLED() to turn it off. This approach encapsulates the LED control within a class structure.

Arduino Sketch:

#define LED 13 // LED connected to digital pin 13


class LEDControl {

public:

void ioDir() {

pinMode(LED, OUTPUT); // Set LED pin as output

void onLED() {

digitalWrite(LED, HIGH); // Turn LED on

void offLED() {

digitalWrite(LED, LOW); // Turn LED off

};

LEDControl led; // Create an instance of LEDControl

void setup() {

led.ioDir(); // Set LED direction as output

void loop() {

led.onLED(); // Turn LED on

delay(1000); // Wait for 1 second

led.offLED(); // Turn LED off

delay(1000); // Wait for 1 second

Explanation of the Code:


1. Define Class LEDControl:

The LEDControl class contains three methods:

ioDir() sets the LED pin direction as output.

onLED() turns the LED on by writing HIGH to the pin.

offLED() turns the LED off by writing LOW to the pin.

2. Create an Instance:

LEDControl led; creates an instance of the LEDControl class.

3. In setup():

led.ioDir(); calls the ioDir() method to set the LED pin as an output.

4. In loop():

led.onLED(); turns the LED on.


delay(1000); waits for 1 second.

led.offLED(); turns the LED off.

delay(1000); waits for another 1 second.

This approach encapsulates LED control in a class structure, making the code modular and reusable.

Answer to question no 5

Certainly! Let's go through each question with the code and explanations.

---

Question 5

5a) Concurrent Blinking and Addition Display

This question requires blinking two LEDs at 1-second intervals and displaying the result of 0x23 + 0x19
on the serial monitor.

const int LED1 = 4; // Pin for LED1

const int LED2 = 5; // Pin for LED2

unsigned long previousMillis = 0;

const long interval = 1000; // 1 second interval


void setup() {

pinMode(LED1, OUTPUT);

pinMode(LED2, OUTPUT);

Serial.begin(9600); // Initialize serial for displaying results

void loop() {

unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

// Toggle LED states

digitalWrite(LED1, !digitalRead(LED1));

digitalWrite(LED2, !digitalRead(LED2));

// Display result of 0x23 + 0x19

int result = 0x23 + 0x19;

Serial.print("Result of 0x23 + 0x19 = ");

Serial.println(result, HEX); // Display in hexadecimal format

Explanation:

millis() helps in creating a non-blocking delay for the LEDs.

The result of 0x23 + 0x19 is displayed as 0x3C in hexadecimal.


---

5b) Save/Retrieve 1-byte Data in Flash Memory

To store data in flash memory on the ATmega328P, we use PROGMEM in Arduino.

#include <avr/pgmspace.h>

const uint8_t data[] PROGMEM = {0x42}; // Arbitrary data to save

void setup() {

Serial.begin(9600);

// Retrieve data from flash memory

uint8_t retrievedData = pgm_read_byte(&data[0]);

Serial.print("Retrieved Data: ");

Serial.println(retrievedData, HEX);

void loop() {

// Empty loop

Explanation:

PROGMEM is used to store data in flash memory.


pgm_read_byte() reads data from flash memory.

---

5c) Asynchronous Frame Diagram for ASCII Character 'A'

For ASCII character 'A' (binary 01000001), here’s an example of code sending the data over serial.

void setup() {

Serial.begin(9600);

char character = 'A';

Serial.print("Sending character: ");

Serial.println(character);

void loop() {

// Empty loop

Explanation:

Character 'A' (0x41) will be sent with start bit (0), 7 data bits, parity bit (optional), and stop bit (1). No
drawing needed in code, but this represents asynchronous communication.

---
Answer to question no 6

6a) Display Voltage Using I2C Protocol

Here’s a basic structure for two Arduino devices, one as Master and one as Slave, for reading voltage
and communicating over I2C. This requires the Wire library.

// Master Code (Nano-1)

#include <Wire.h>

#define SLAVE_ADDRESS 8

#define ANALOG_PIN A3

void setup() {

Wire.begin(); // Join I2C bus as master

Serial.begin(9600);

void loop() {

int voltage = analogRead(ANALOG_PIN); // Read voltage

Wire.beginTransmission(SLAVE_ADDRESS);

Wire.write(voltage >> 8); // Send high byte

Wire.write(voltage & 0xFF); // Send low byte

Wire.endTransmission();

Serial.print("Voltage sent: ");

Serial.println(voltage);
delay(1000);

// Slave Code (Nano-2)

#include <Wire.h>

void setup() {

Wire.begin(8); // Join I2C bus with address 8

Wire.onReceive(receiveEvent); // Register event

Serial.begin(9600);

void receiveEvent(int bytes) {

int voltage = Wire.read() << 8 | Wire.read(); // Receive 2 bytes

Serial.print("Voltage received: ");

Serial.println(voltage);

void loop() {

// Empty loop

Explanation:

The master reads an analog voltage, sends it to the slave over I2C, and the slave displays it.

---
6b) SPI Communication between Two Arduinos

This example code demonstrates SPI communication between Master and Slave Arduino for data
exchange.

// Master Code

#include <SPI.h>

void setup() {

SPI.begin();

pinMode(SS, OUTPUT);

Serial.begin(9600);

void loop() {

digitalWrite(SS, LOW);

SPI.transfer(0x34); // Send 0x34 to Slave

digitalWrite(SS, HIGH);

delay(1000);

// Slave Code

#include <SPI.h>

void setup() {

pinMode(MISO, OUTPUT);

SPI.begin();

Serial.begin(9600);
}

void loop() {

if (SPI.available()) {

int received = SPI.transfer(0xCD); // Send 0xCD to Master

Serial.print("Received: ");

Serial.println(received, HEX);

Explanation:

Master sends 0x34 and the slave responds with 0xCD over SPI.

---

Answer to question no 7

7a) Control SG-90 Servo with HC-05 Bluetooth

Using Bluetooth to control a servo, based on received angle commands:

#include <Servo.h>

Servo myservo;
void setup() {

Serial.begin(9600);

myservo.attach(3);

void loop() {

if (Serial.available()) {

int angle = Serial.parseInt();

myservo.write(angle);

Serial.print("Servo angle set to: ");

Serial.println(angle);

Explanation:

Bluetooth module sends angle to set servo position.

---

7b) Generate a 4-Second Timer with TOV1 Polling

This code sets up a timer interrupt every 4 seconds using Timer1.

void setup() {

TCCR1A = 0;
TCCR1B = (1 << CS12) | (1 << CS10); // Prescaler 1024

TCNT1 = 0;

Serial.begin(9600);

void loop() {

if (TIFR1 & (1 << TOV1)) { // Check overflow flag

TIFR1 |= (1 << TOV1); // Clear flag

Serial.println("4 seconds passed");

Explanation:

Timer1 configured for 4 seconds with overflow polling.

---

Answer to question no 8

8a) DS18B20 Temperature Reading

Example code to read temperature from a DS18B20 sensor.

#include <OneWire.h>

#include <DallasTemperature.h>
#define ONE_WIRE_BUS 3

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

void setup() {

Serial.begin(9600);

sensors.begin();

void loop() {

sensors.requestTemperatures();

float tempC = sensors.getTempCByIndex(0);

Serial.print("Temperature: ");

Serial.println(tempC);

delay(1000);

Explanation:

Uses DallasTemperature library to read and display temperature.

---

8b) Taxi Meter Fare Calculation

This code calculates fare based on the problem’s requirements.


float calculateFare(float distance) {

if (distance <= 2.0) return 40.0;

return 40.0 + (distance - 2.0) * 12.0;

void setup() {

Serial.begin(9600);

void loop() {

float distance = 5.0; // Example distance

float fare = calculateFare(distance);

Serial.print("Total fare for ");

Serial.print(distance);

Serial.print(" km: Tk ");

Serial.println(fare);

delay(1000);

Explanation:

Calculates fare based on conditions.

---

8c) Extract Tokens Using strtok


void setup() {

Serial.begin(9600);

char myData[] = "1234, Forum, 37.54";

char *token = strtok(myData, ", ");

while (token != NULL) {

Serial.println(token);

token = strtok(NULL, ", ");

void loop() {

// Empty loop

Explanation:

Uses strtok to parse and display tokens from myData.

---

Let me know if any specific part needs further clarification!

Fall 22

Let's go through each question and provide the code along with detailed explanations.

---
### Question 2

#### Part (a)

*Objective*: Establish a Software UART (SUART) communication between Arduino UNO and Arduino
NANO to send a float value (12.75) from UNO to NANO using digital pins 7 and 8.

*Explanation of Code*:

- *UNO Code*:

- We are using SoftwareSerial to create a serial communication on pins 7 (TX) and 8 (RX) as a substitute
for the hardware serial.

- SUART.begin(9600); sets the baud rate for this serial connection.

- SUART.println(data); sends the floating-point value 12.75 as a string format.

- delay(1000); gives a 1-second delay between transmissions.

cpp

// Code for Arduino UNO

#include <SoftwareSerial.h>

SoftwareSerial SUART(7, 8); // Define SUART on pins 7 (RX) and 8 (TX)

void setup() {

SUART.begin(9600); // Initialize SUART at 9600 baud rate

void loop() {

float data = 12.75;

SUART.println(data); // Send the float value 12.75 to NANO

delay(1000); // Wait 1 second before sending again


}

- *NANO Code*:

- SUART.available() checks if data is available in the SUART buffer.

- SUART.parseFloat(); extracts the received float value.

- Serial.println(data); outputs the received data to the Serial Monitor on NANO, which helps in verifying
the communication.

cpp

// Code for Arduino NANO

#include <SoftwareSerial.h>

SoftwareSerial SUART(7, 8); // Define SUART on pins 7 (RX) and 8 (TX)

void setup() {

SUART.begin(9600); // Initialize SUART at 9600 baud rate

Serial.begin(9600); // Initialize Serial Monitor at 9600 baud rate

void loop() {

if (SUART.available()) {

float data = SUART.parseFloat(); // Receive float data

Serial.println(data); // Display received data on Serial Monitor

2(c)
Here's an Arduino sketch for the Nano to act as an I2C slave with address `0x23`. This sketch will
respond with the data `0x5678` whenever the master requests it.

```cpp

#include <Wire.h>

const uint8_t SLAVE_ADDRESS = 0x23; // I2C address of the Nano

const uint16_t DATA_TO_SEND = 0x5678; // Data to send to the master

void setup() {

Wire.begin(SLAVE_ADDRESS); // Initialize the I2C as a slave with address 0x23

Wire.onRequest(requestEvent); // Register the request event handler

void loop() {

// Nothing to do in the main loop

void requestEvent() {

// Split 0x5678 into two bytes

uint8_t highByte = (DATA_TO_SEND >> 8) & 0xFF;

uint8_t lowByte = DATA_TO_SEND & 0xFF;

// Send two bytes

Wire.write(highByte);

Wire.write(lowByte);

```
### Explanation:

- **Wire.begin(SLAVE_ADDRESS):** Initializes the Nano as an I2C slave with address `0x23`.

- **Wire.onRequest(requestEvent):** Sets up an interrupt handler that triggers whenever the master


requests data from the Nano.

- **requestEvent:** In this function, `0x5678` is split into two bytes (high and low) and sent to the
master.

This way, when the master requests data, the slave will respond with `0x5678`.

#### Part (b)

*Objective*: Calculate the relationship between temperature \( T \) and analogRead(A1) for an LM35
sensor.

*Explanation of Solution*:

1. *Relationship between \( T \) and \( V_{DT} \)*:

- Since the LM35 outputs 10mV per degree Celsius, we have:

\[

V_{DT} = 0.01T

\]

2. **Relationship between \( T \) and analogRead(A1)**:

- The analog reading for the ADC (assuming 5V reference and 10-bit resolution) is:

\[

\text{ADC\Value} = \frac{V{DT}}{5} \times 1023 = 2.046 \times T

\]

Therefore, we can convert an ADC reading to temperature as:

\[

T = \frac{\text{ADC\_Value}}{2.046}

\]
*Code for Temperature Calculation*:

cpp

// Code for Arduino UNO to read temperature from LM35

const int sensorPin = A1; // Pin connected to LM35 output

void setup() {

Serial.begin(9600); // Initialize Serial Monitor at 9600 baud rate

void loop() {

int adcValue = analogRead(sensorPin); // Read analog value

float temperature = adcValue / 2.046; // Convert ADC value to temperature

Serial.print("Temperature: ");

Serial.print(temperature);

Serial.println(" °C");

delay(1000); // Wait 1 second before reading again

---

### Question 3

#### Part (a)

*Objective*: Set up a 4-Wire SPI communication between Master (UNO) and Slave (NANO) and
exchange data (send 0x56 from Master and 0x23 from Slave).
*Explanation of Code*:

1. *UNO (Master) Code*:

- The UNO is set as an SPI master using SPI.begin();.

- digitalWrite(SS, LOW); enables communication with the slave.

- SPI.transfer(0x56); sends the value 0x56 to the slave.

- digitalWrite(SS, HIGH); ends the communication after sending the byte.

cpp

// Code for Arduino UNO as SPI Master

#include <SPI.h>

void setup() {

SPI.begin(); // Start SPI in master mode

pinMode(SS, OUTPUT); // Set SS pin as output

Serial.begin(9600); // Initialize Serial Monitor

void loop() {

digitalWrite(SS, LOW); // Enable slave

SPI.transfer(0x56); // Send data 0x56 to slave

digitalWrite(SS, HIGH); // Disable slave

delay(1000); // Wait 1 second before next transfer

2. *NANO (Slave) Code*:

- The NANO is set as an SPI slave.

- The SPI.attachInterrupt(); enables an interrupt service routine (ISR) on data reception.


- Inside the ISR, SPDR holds the received data, and we set SPDR = 0x23; to send 0x23 back to the
master.

cpp

// Code for Arduino NANO as SPI Slave

#include <SPI.h>

volatile byte receivedData;

void setup() {

SPI.begin(); // Start SPI in slave mode

pinMode(MISO, OUTPUT); // Set MISO as output for slave mode

SPCR |= _BV(SPE); // Enable SPI in slave mode

SPI.attachInterrupt(); // Enable SPI interrupt

Serial.begin(9600); // Initialize Serial Monitor

ISR(SPI_STC_vect) { // SPI interrupt service routine

receivedData = SPDR; // Read received data

SPDR = 0x23; // Prepare data to send back

void loop() {

Serial.println(receivedData); // Print received data to Serial Monitor

delay(1000); // Wait 1 second before printing again

---
#### Part (b)

*Objective*: Set up an external interrupt on the ATmega328P (e.g., Arduino UNO) using the INT1 pin
and trigger an ISR on a rising edge.

*Explanation of Code*:

- attachInterrupt(digitalPinToInterrupt(2), ISR, RISING); attaches an interrupt to the INT1 pin (digital pin
2 on UNO).

- The ISR() function is called whenever a rising edge is detected on the INT1 pin.

cpp

// Code for external interrupt on INT1 (pin 2 on Arduino UNO)

void setup() {

pinMode(2, INPUT); // Configure pin 2 as input for INT1

attachInterrupt(digitalPinToInterrupt(2), ISR, RISING); // Trigger ISR on rising edge

Serial.begin(9600); // Initialize Serial Monitor

void ISR() {

Serial.println("Rising Edge Interrupt Triggered!"); // Print message when interrupt occurs

void loop() {

// Main loop code continues to run until an interrupt occurs

This interrupt code allows the Arduino to respond instantly to a rising edge on INT1, which can be useful
for timing-critical applications.
Let’s solve each question step-by-step:

---

3c]

*Objective*: Write code to check the TOV1 flag (Timer Overflow Flag 1) every 2 seconds and then turn
on an LED connected to a pin at the 10-second mark.

#### Explanation

1. *TOV1 Flag*:

- The TOV1 flag is set when Timer 1 overflows, which means the timer counts from 0 up to its
maximum (0xFFFF for a 16-bit timer).

- We can configure Timer 1 to overflow at a specific interval by setting a suitable prescaler.

2. *Solution*:

- Using a prescaler value, we can set Timer 1 to overflow approximately every 2 seconds.

- Every time TOV1 goes high, we increment a counter.

- When this counter reaches 5 (2 seconds * 5 = 10 seconds), we turn on an LED connected to a specific
pin.

#### Code

cpp

const int ledPin = 9; // Pin connected to the LED

int overflowCounter = 0; // Counter to keep track of overflows

void setup() {

pinMode(ledPin, OUTPUT); // Set LED pin as output


TCCR1A = 0; // Set Timer1 to Normal mode

TCCR1B = (1 << CS12); // Set prescaler to 256

TCNT1 = 0; // Initialize Timer1 counter to 0

TIMSK1 = (1 << TOIE1); // Enable Timer1 overflow interrupt

sei(); // Enable global interrupts

ISR(TIMER1_OVF_vect) { // Timer1 overflow interrupt service routine

overflowCounter++; // Increment overflow counter

if (overflowCounter >= 5) { // 5 overflows ~ 10 seconds

digitalWrite(ledPin, HIGH); // Turn on LED

void loop() {

// Main code runs here

*Explanation of Code*:

- TCCR1A = 0; and TCCR1B = (1 << CS12); configure Timer1 in normal mode with a 256 prescaler.

- TIMSK1 = (1 << TOIE1); enables the Timer1 overflow interrupt.

- In the ISR(TIMER1_OVF_vect), we increment overflowCounter each time an overflow occurs.

- After 5 overflows (approximately 10 seconds), we turn on the LED by setting ledPin to HIGH.

---

4c)
*Objective*: Present the connection diagram and code to control an LED's brightness with a
potentiometer.

#### Connection Diagram

1. *Connections*:

- *Potentiometer*:

- Connect one end of the potentiometer to *5V*.

- Connect the other end to *GND*.

- Connect the middle (wiper) pin to *A0* on the Arduino UNO.

- *LED Circuit*:

- Connect *D9* (PWM pin) on the Arduino to one end of *R1* (resistor).

- Connect the other end of *R1* to the *anode (positive) of LED1*.

- Connect the *cathode (negative)* of LED1 to *GND*.

#### Code

*Explanation of Code*:

- We read the potentiometer value using analogRead(A0), which gives a value between 0 and 1023.

- We map this value to a range suitable for PWM (0-255) using map() to control the LED brightness.

- analogWrite(ledPin, brightness); sets the brightness of the LED based on the mapped value.

cpp

const int potPin = A0; // Pin connected to the potentiometer

const int ledPin = 9; // Pin connected to the LED through a resistor

void setup() {

pinMode(ledPin, OUTPUT); // Set LED pin as output

}
void loop() {

int potValue = analogRead(potPin); // Read potentiometer value (0-1023)

int brightness = map(potValue, 0, 1023, 0, 255); // Map to PWM range (0-255)

analogWrite(ledPin, brightness); // Set LED brightness

delay(10); // Short delay for stability

*Explanation of Mapping*:

- The map(potValue, 0, 1023, 0, 255); function linearly maps the potentiometer value from its 0-1023
range to the 0-255 range, suitable for PWM brightness control.

- This makes the LED's brightness increase as you rotate the potentiometer.

This code will allow you to smoothly adjust the brightness of LED1 by rotating the potentiometer.

6(a)// Pin definition

const int ledPin = 13; // LED connected to digital pin 13

void setup() {

// Initialize LED pin as an output

pinMode(ledPin, OUTPUT);

// Configure INT0 to trigger on the rising edge

EICRA |= (1 << ISC01) | (1 << ISC00); // Rising edge on INT0

EIMSK |= (1 << INT0); // Enable INT0 interrupt

sei(); // Enable global interrupts

void loop() {
// Main loop does nothing; waiting for interrupts

// Interrupt Service Routine (ISR) for INT0

ISR(INT0_vect) {

// Blink LED 5 times with 1-second interval

for (int i = 0; i < 5; i++) {

digitalWrite(ledPin, HIGH); // Turn LED on

delay(1000); // Wait for 1 second

digitalWrite(ledPin, LOW); // Turn LED off

delay(1000); // Wait for 1 second

Explanation of the Code

Pin Initialization: The ledPin (pin 13) is set as an output to control the LED.

Register Configuration:

EICRA is configured to trigger on a rising edge.

EIMSK enables the INT0 interrupt.

sei() enables global interrupts.

Interrupt Service Routine (ISR):

The ISR(INT0_vect) function executes when INT0 is triggered.

Inside the ISR, we blink the LED on ledPin five times, with each blink lasting 1 second on and 1 second
off.

Let's solve each question one by one.

---

### Question 6b
*Objective*: Write initialization code to configure an Arduino Nano as an SPI slave.

To set up an Arduino Nano as an SPI slave, we need to configure the *SPI registers* to allow it to receive
data from an SPI master device. The *SPI pins* on the Nano are:

- *MISO (Master In Slave Out)* - D12

- *MOSI (Master Out Slave In)* - D11

- *SCK (Serial Clock)* - D13

- *SS (Slave Select)* - D10

When configuring the Nano as an SPI slave, only the *MISO* pin will send data to the master, while
*MOSI, **SCK, and **SS* are inputs.

#### Initialization Code for Arduino Nano as SPI Slave

cpp

#include <SPI.h>

void setup() {

// Set MISO as OUTPUT, others as INPUT

pinMode(MISO, OUTPUT);

pinMode(MOSI, INPUT);

pinMode(SCK, INPUT);

pinMode(SS, INPUT);

// Enable SPI as Slave

SPCR |= (1 << SPE); // Set SPE (SPI Enable) bit in SPCR register

// Optional: Enable SPI Interrupt


SPCR |= (1 << SPIE); // Enable SPI interrupt if required

void loop() {

// SPI interrupt can handle incoming data, or you can use polling in the main loop

*Explanation*:

- *Set MISO as Output*: Since MISO is the only output in an SPI slave configuration, it’s set to OUTPUT.
The other pins are set as INPUT.

- *Enable SPI as Slave*: Setting the SPE bit in the SPCR register enables SPI in slave mode.

- *Enable Interrupts (Optional)*: Setting the SPIE bit enables the SPI interrupt, which can be used to
trigger specific actions when data is received. You would need an ISR(SPI_STC_vect) function if you use
the interrupt approach.

---

### Question 6c

*Objective: Write a sketch to blink an LED on an Arduino UNO at a 1-second interval, using the **TOV1
(Timer Overflow Flag 1)* interrupt of *Timer1 (TC1)*.

To achieve this:

1. We will configure *Timer1* to overflow every 1 second.

2. Use the *Timer1 overflow interrupt* (TOV1) to toggle an LED.

3. The LED will be connected to a specific pin, and it will turn on and off each time the overflow interrupt
triggers, effectively blinking at a 1-second interval.
#### Code to Blink LED with TOV1 Overflow Interrupt

cpp

const int ledPin = 13; // Pin connected to the LED (typically built-in LED on pin 13 for UNO)

void setup() {

pinMode(ledPin, OUTPUT); // Set the LED pin as output

// Configure Timer1

TCCR1A = 0; // Set Timer1 to Normal mode

TCCR1B = (1 << CS12) | (1 << CS10); // Set prescaler to 1024

TCNT1 = 0; // Initialize Timer1 counter to 0

// Enable Timer1 overflow interrupt

TIMSK1 = (1 << TOIE1);

// Enable global interrupts

sei();

ISR(TIMER1_OVF_vect) { // Timer1 overflow interrupt service routine

digitalWrite(ledPin, !digitalRead(ledPin)); // Toggle LED

TCNT1 = 0; // Reset Timer1 counter for precise timing

void loop() {

// Main code can run here (if any), but the LED toggling is handled by the interrupt

}
*Explanation*:

1. *Set Timer1 Prescaler*: The line TCCR1B = (1 << CS12) | (1 << CS10); sets a prescaler of *1024* for
Timer1.

- With a prescaler of 1024, Timer1 (16-bit) will overflow approximately every 1 second, assuming a
clock speed of 16 MHz on the Arduino UNO. (The exact overflow timing is slightly less than 1 second, but
close enough for blinking purposes.)

2. *Enable Timer1 Overflow Interrupt*: Setting TIMSK1 = (1 << TOIE1); enables the Timer1 overflow
interrupt.

3. *Interrupt Service Routine (ISR)*:

- The function ISR(TIMER1_OVF_vect) runs each time Timer1 overflows.

- Inside the ISR, we toggle the LED by changing its state.

- TCNT1 = 0; resets the counter to maintain consistent timing.

4. *Global Interrupt Enable*: sei(); enables global interrupts, allowing the Timer1 overflow interrupt to
function.

This code will blink the built-in LED on pin 13 every second using the Timer1 overflow interrupt. Each
time Timer1 overflows, the TOV1 flag triggers the ISR, toggling the LED.

Let's solve each question step-by-step.

Question 7a

// Define the pins for LED1 and LED2

const int led1Pin = 6; // LED1 connected to digital pin 6

const int led2Pin = 13; // LED2 connected to digital pin 13


// Variables to store the LED states

bool led1State = false;

bool led2State = true;

// Interval between blinks (3 seconds = 3000 milliseconds)

const unsigned long interval = 3000;

// Store the last time the LEDs were toggled

unsigned long previousMillis = 0;

void setup() {

// Initialize the LED pins as outputs

pinMode(led1Pin, OUTPUT);

pinMode(led2Pin, OUTPUT);

// Set initial states for the LEDs

digitalWrite(led1Pin, led1State);

digitalWrite(led2Pin, led2State);

void loop() {

// Get the current time in milliseconds

unsigned long currentMillis = millis();

// Check if 3 seconds have passed

if (currentMillis - previousMillis >= interval) {

// Save the current time as the last toggle time

previousMillis = currentMillis;
// Toggle the states of both LEDs

led1State = !led1State;

led2State = !led2State;

// Update the LEDs with the new states

digitalWrite(led1Pin, led1State);

digitalWrite(led2Pin, led2State);

### Question 7b

*Objective: Develop a sketch to generate a Fast PWM signal in **Mode 14* (Fast PWM mode with ICR1
as the top value) on *digital pin 10* with a frequency of 1 Hz and a duty cycle of 60%.

In *Mode 14* (Fast PWM with ICR1 as TOP) on *Timer1* of the Arduino UNO:

1. *Frequency: We control the frequency by setting the value of the **ICR1* register. The frequency \
( f \) can be calculated as:

\[

f = \frac{{\text{clock speed}}}{{\text{prescaler} \times (ICR1 + 1)}}

\]

2. *Duty Cycle: We set the duty cycle by adjusting the **OCR1A* value. For a duty cycle \( D \% \),
OCR1A can be calculated as:

\[

OCR1A = D \times (ICR1 + 1) / 100

\]
Using a clock frequency of 16 MHz and a prescaler of 1024, we can calculate values for ICR1 and OCR1A
to generate a 1 Hz PWM signal with a 60% duty cycle.

#### Code to Generate PWM Signal

cpp

void setup() {

// Set pin 10 as output

pinMode(10, OUTPUT);

// Set Timer1 to Fast PWM Mode 14 with ICR1 as TOP

TCCR1A = (1 << COM1B1) | (1 << WGM11); // Non-inverting mode on OC1B (pin 10)

TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12) | (1 << CS10); // Prescaler 1024

// Set the top value for 1 Hz frequency

ICR1 = 15624; // ICR1 = (16,000,000 / (1024 * 1)) - 1

// Set OCR1B for 60% duty cycle

OCR1B = (60 * (ICR1 + 1)) / 100; // 60% of 15624

void loop() {

// Nothing in the loop, PWM signal is handled by Timer1

#### Explanation of the Code


- *Set Pin 10 as Output*: Pin 10 (OC1B) will output the PWM signal.

- *Timer1 Mode 14 (Fast PWM with ICR1)*:

- TCCR1A = (1 << COM1B1) | (1 << WGM11); sets the Timer to Fast PWM, non-inverting mode.

- TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12) | (1 << CS10); configures the Timer to use ICR1
as the top value with a prescaler of 1024.

- *Frequency and Duty Cycle Calculation*:

- ICR1 = 15624; sets the PWM frequency to 1 Hz (16 MHz clock / (1024 prescaler * 1 Hz) - 1).

- OCR1B = (60 * (ICR1 + 1)) / 100; sets the duty cycle to 60%.

This will generate a 1 Hz PWM signal on pin 10 with a 60% duty cycle.

---

### Question 7c

*Objective: Define the terms **D drive, **T drive, and **C drive* in the context of a taxi cab's journey.

#### Definitions

1. *D Drive (Departure Drive)*:

- This represents the initial part of the journey when the taxi departs from its starting location. It
involves picking up the passenger and starting the trip. The *D Drive* typically covers the initial route,
including navigating through pickup areas and finding the shortest route to the passenger.

2. *T Drive (Transit Drive)*:

- The *T Drive* represents the main part of the journey where the taxi is in transit, taking the
passenger from the pickup location to the destination. This part of the journey involves following the
planned route, obeying traffic laws, and possibly adjusting the route in response to traffic conditions.
The *T Drive* focuses on reaching the destination efficiently.

3. *C Drive (Completion Drive)*:


- The *C Drive* represents the final part of the journey, where the taxi reaches the passenger’s
destination. This phase includes actions like stopping, letting the passenger out, and possibly preparing
for the next trip. The *C Drive* is the completion or termination stage of the journey, ending the service.

These terms (D, T, and C drives) help categorize different segments of a taxi journey, each with distinct
tasks and considerations.

8b)To store data in the flash memory of an *ATmega328P* (such as on an Arduino Uno) and then read it
back, we need to understand a few limitations:

1. *Flash memory on the ATmega328P* is generally used for storing program code, not variable data.
However, we can use special functions to write specific values to certain flash locations (such as a
dedicated section of flash memory).

2. Writing to flash memory from code running on the ATmega328P is not a typical operation since flash
memory is primarily meant for program storage and is only writable under certain conditions (such as
during bootloading).

3. Direct manipulation of flash memory requires some lower-level code, including assembly, to manage
page writes.

### Solution Using EEPROM (as Alternative)

The *EEPROM* on the ATmega328P is often used for storing small amounts of data that need to persist
even after power is removed, and it is more suitable for tasks like storing a single byte. EEPROM is easier
to work with in code compared to directly writing to flash memory.

Below, I'll provide a sketch to store 0x35 in the EEPROM and then read it back for verification.

### Code to Write and Read from EEPROM

cpp

#include <EEPROM.h>

void setup() {

Serial.begin(9600);
// Write 0x35 to EEPROM address 0

EEPROM.update(0, 0x35);

// Read back the stored value

uint8_t readValue = EEPROM.read(0);

// Verify by printing to Serial Monitor

if (readValue == 0x35) {

Serial.println("Verification successful: 0x35 stored and read correctly.");

} else {

Serial.print("Verification failed. Read value: 0x");

Serial.println(readValue, HEX);

void loop() {

// Nothing to do in loop

### Explanation of the Code

1. *Write to EEPROM*:

- EEPROM.update(0, 0x35); writes the value 0x35 to address 0 in EEPROM. We use update instead of
write to prevent redundant writes if the value at the address is already 0x35, which can extend EEPROM
life.

2. *Read from EEPROM*:


- EEPROM.read(0); reads the value from EEPROM address 0.

3. *Verification*:

- We check if the value read from EEPROM matches 0x35. If it does, a success message is printed to the
Serial Monitor. Otherwise, it displays the read value to indicate a failure.

### Flash Memory on ATmega328P

Directly writing to flash memory from within a running program on an ATmega328P requires
bootloader-level access, as the chip does not support self-programming in normal code execution. If you
specifically need to use flash memory, a custom bootloader or external programming tools are required,
and it goes beyond standard Arduino programming.

Using the *EEPROM* as shown above is a practical alternative when persistent storage is required.

8(c) // Define the pins for the UP and DOWN buttons

const int upButtonPin = 10; // UP button connected to digital pin 10

const int downButtonPin = 11; // DOWN button connected to digital pin 11

// Define the pins for the 7-segment display segments (common cathode configuration)

const int segmentPins[] = {2, 3, 4, 5, 6, 7, 8}; // Pins for segments a to g

const int dpPin = 9; // Decimal point pin

// 7-segment display digit patterns for numbers 0-9

const byte digits[10] = {

0b00111111, // 0

0b00000110, // 1

0b01011011, // 2

0b01001111, // 3

0b01100110, // 4

0b01101101, // 5
0b01111101, // 6

0b00000111, // 7

0b01111111, // 8

0b01101111 // 9

};

// Variable to store the current counter value

int counter = 0;

// Variables to handle button states and debounce

bool upButtonPressed = false;

bool downButtonPressed = false;

void setup() {

// Initialize the segment pins as outputs

for (int i = 0; i < 7; i++) {

pinMode(segmentPins[i], OUTPUT);

pinMode(dpPin, OUTPUT);

// Initialize the button pins as inputs with internal pull-down resistors

pinMode(upButtonPin, INPUT);

pinMode(downButtonPin, INPUT);

// Set the initial display

displayDigit(counter);

void loop() {
// Read the state of the UP and DOWN buttons

bool upState = digitalRead(upButtonPin);

bool downState = digitalRead(downButtonPin);

// Check if the UP button is pressed

if (upState && !upButtonPressed) {

upButtonPressed = true; // Record that the button was pressed

counter++; // Increment the counter

if (counter > 9) counter = 0; // Wrap around to 0 if counter exceeds 9

displayDigit(counter); // Update the 7-segment display

} else if (!upState) {

upButtonPressed = false; // Reset the button state if not pressed

// Check if the DOWN button is pressed

if (downState && !downButtonPressed) {

downButtonPressed = true; // Record that the button was pressed

counter--; // Decrement the counter

if (counter < 0) counter = 9; // Wrap around to 9 if counter goes below 0

displayDigit(counter); // Update the 7-segment display

} else if (!downState) {

downButtonPressed = false; // Reset the button state if not pressed

// Function to display a digit on the 7-segment display

void displayDigit(int num) {

byte segments = digits[num]; // Get the segment pattern for the number
// Set each segment based on the pattern

for (int i = 0; i < 7; i++) {

digitalWrite(segmentPins[i], (segments >> i) & 0x01);

Spring 22

### *Question 2:*

#### a) Refer to Fig-2(a), create a sketch to stop Pump-1 after 30 minutes or if the high-level switch (KH)
is activated.

- This can be achieved using an Arduino sketch. The logic is to check the run time and switch status.

Sample Arduino code:

cpp

const int pump1Pin = 8; // Pump-1 control pin

const int khPin = 7; // High-Level Switch KH pin

unsigned long startTime;

bool isRunning = false;

void setup() {

pinMode(pump1Pin, OUTPUT);

pinMode(khPin, INPUT);

startTime = millis(); // Start timer

isRunning = true;

void loop() {

if (isRunning) {

// Stop pump after 30 minutes or if KH is activated


if ((millis() - startTime >= 1800000) || digitalRead(khPin) == HIGH) {

digitalWrite(pump1Pin, LOW); // Stop Pump-1

isRunning = false;

} else {

digitalWrite(pump1Pin, HIGH); // Keep Pump-1 running

Let's break down and solve each part of this question.

Part (b)

You are required to write a sketch (program) to store specific information into the EEPROM of an
ATmega328P microcontroller. The information includes:

Name: "Asif Ali"

ID: "192005001"

GPA: "3.65"

The data needs to be stored in EEPROM starting at location 0x0120, and then you need to verify it by
reading it back and displaying it on the Serial Monitor.

Here’s an Arduino sketch that accomplishes this:

#include <EEPROM.h>
void setup() {

Serial.begin(9600);

// Write data to EEPROM at address 0x0120

int addr = 0x0120;

// Write name "Asif Ali" to EEPROM

char name[] = "Asif Ali";

for (int i = 0; i < sizeof(name); i++) {

EEPROM.write(addr++, name[i]);

// Write ID "192005001" to EEPROM

char id[] = "192005001";

for (int i = 0; i < sizeof(id); i++) {

EEPROM.write(addr++, id[i]);

// Write GPA "3.65" to EEPROM

char gpa[] = "3.65";

for (int i = 0; i < sizeof(gpa); i++) {

EEPROM.write(addr++, gpa[i]);

// Verify by reading back and displaying on Serial Monitor

addr = 0x0120;

Serial.print("Name: ");

for (int i = 0; i < sizeof(name); i++) {


Serial.print((char)EEPROM.read(addr++));

Serial.println();

Serial.print("ID: ");

for (int i = 0; i < sizeof(id); i++) {

Serial.print((char)EEPROM.read(addr++));

Serial.println();

Serial.print("GPA: ");

for (int i = 0; i < sizeof(gpa); i++) {

Serial.print((char)EEPROM.read(addr++));

Serial.println();

void loop() {

// Nothing to do here

Explanation:

1. The EEPROM.write() function is used to write each character to EEPROM starting at address 0x0120.

2. After writing the data, the code reads back the stored values from the EEPROM using EEPROM.read()
and prints them to the Serial Monitor.
3. The name, ID, and GPA are stored consecutively, each taking up space in EEPROM based on the
number of characters.

Part (c)

For this part, you need to present the ATmega328P assembly instructions that would replicate the
following C++ code:

byte y = 0x35;

This instruction involves storing the value 0x35 in a memory location using the X-pointer register.

In AVR assembly, you can do this as follows:

ldi r16, 0x35 ; Load the immediate value 0x35 into register r16

sts y, r16 ; Store the value of r16 into memory location 'y'

However, if you are required to use the X-pointer register specifically (which uses registers r26 and r27
in AVR), you can do it like this:

ldi r26, low(y) ; Load the low byte of address 'y' into r26

ldi r27, high(y) ; Load the high byte of address 'y' into r27

ldi r16, 0x35 ; Load 0x35 into register r16

st X, r16 ; Store the value of r16 into the address pointed by X (r26:r27)

Explanation:
1. ldi (Load Immediate) loads immediate values into registers.

2. sts (Store Direct to SRAM) directly stores the value in a register to a specific address.

3. st X, r16 stores the value of r16 at the address pointed to by the X register (which is a combination of
r26 and r27).

### *Question 3:*

#### a) Build sketches to receive data and send it over UART.

- This involves setting up serial communication between two Arduinos (UNO and NANO).

UNO (Master) code:

cpp

void setup() {

Serial.begin(9600);

void loop() {

if (Serial.available()) {

String data = Serial.readString();

Serial.write(data.c_str()); // Send data over UART

NANO (Slave) code:

cpp
String data;

void setup() {

Serial.begin(9600);

void loop() {

if (Serial.available()) {

data = Serial.readString(); // Receive data from UNO

// Process the received data here

Let's address each part of your question, starting with part *(b)* and then moving to part *(c)*.

---

### Part (b): LM35 Temperature Sensor Conversion

The LM35 temperature sensor outputs a voltage that is linearly proportional to the temperature in
degrees Celsius. When connected to an analog input of the Arduino (like A1), you can read this voltage
using analogRead(), which gives a value between 0 and 1023 (representing 0V to 5V).

#### Relationship between Room Temperature (T) and ADC Value

For the LM35 sensor:

- The output voltage (Vout) increases by 10 mV per degree Celsius.

- Thus, if the temperature is \( T \) in Celsius, then \( Vout = 10 \times T \) mV.

- In terms of Arduino's ADC, if \( V_{in} \) is the voltage measured, the digital value from analogRead() is:

\[
\text{ADC Value} = \frac{V_{in}}{5.0} \times 1023

\]

Where 5.0V is the reference voltage for the Arduino Uno.

#### Converting ADC Value to Temperature (T)

From the above, we can derive the temperature as:

\[

T = \left(\frac{\text{ADC Value}}{1023}\right) \times 5.0 \times 100

\]

The factor 100 comes from converting the voltage to Celsius because each 10 mV represents 1°C.

#### Arduino Code

Here’s the code to read the LM35 temperature and calculate the temperature in Celsius:

cpp

const int sensorPin = A1; // LM35 sensor connected to analog pin A1

float temperature = 0.0; // Variable to store temperature in Celsius

void setup() {

Serial.begin(9600); // Start serial communication at 9600 bps

void loop() {

int sensorValue = analogRead(sensorPin); // Read the analog value from LM35


// Convert the ADC value to voltage (0-5V) and then to temperature

temperature = (sensorValue / 1023.0) * 5.0 * 100;

// Print the temperature to the Serial Monitor

Serial.print("Temperature: ");

Serial.print(temperature);

Serial.println(" °C");

delay(1000); // Wait 1 second before reading again

### Explanation:

- analogRead(sensorPin): Reads the analog value from the LM35 sensor.

- temperature = (sensorValue / 1023.0) * 5.0 * 100;: Converts the analog reading to voltage and then to
temperature.

- Serial.print(...): Prints the temperature to the Serial Monitor every second.

---

### Part (c): I2C Communication between Master and Slave for Sending a Float Value

In this scenario:

- An Arduino (Master) will request the current value of a float variable I (representing current) from
another Arduino (Slave).

- The Slave will send the float I as four bytes to the Master over I2C.

- The Master will then convert these bytes back into a float and display it on a Serial Monitor (SM1) at a
1-second interval.
### Master Code (Arduino)

cpp

#include <Wire.h>

const int slaveAddress = 0x13; // I2C address of the slave

void setup() {

Serial.begin(9600); // Start Serial communication for SM1

Wire.begin(); // Join the I2C bus as Master

void loop() {

Wire.requestFrom(slaveAddress, 4); // Request 4 bytes from the slave

byte receivedBytes[4];

int index = 0;

// Receive the 4 bytes from the slave

while (Wire.available() && index < 4) {

receivedBytes[index++] = Wire.read();

// Convert received bytes back to a float

float current;

memcpy(&current, receivedBytes, sizeof(float));

// Print the current to the Serial Monitor


Serial.print("Current (I): ");

Serial.println(current);

delay(1000); // Wait 1 second before requesting again

### Explanation of Master Code:

1. Wire.begin(): Initializes the I2C bus in master mode.

2. Wire.requestFrom(slaveAddress, 4);: Requests 4 bytes from the slave device at address 0x13.

3. while (Wire.available() && index < 4): Reads each byte sent by the slave and stores them in
receivedBytes.

4. memcpy(&current, receivedBytes, sizeof(float));: Uses memcpy to convert the 4-byte array into a
float.

5. Serial.println(current);: Prints the current value to the Serial Monitor.

### Slave Code (Arduino)

cpp

#include <Wire.h>

float I = 1.23; // Example current value

void setup() {

Wire.begin(0x13); // Join the I2C bus as Slave with address 0x13

Wire.onRequest(requestEvent); // Register event for Master requests

}
void loop() {

// The loop can contain code to update `I` as required

// For simplicity, we're keeping I constant

// This function is called when the Master requests data

void requestEvent() {

byte floatBytes[4];

memcpy(floatBytes, &I, sizeof(float)); // Convert float I to 4 bytes

// Send each byte to the Master

for (int i = 0; i < 4; i++) {

Wire.write(floatBytes[i]);

### Explanation of Slave Code:

1. Wire.begin(0x13);: Initializes the Arduino as an I2C slave with the address 0x13.

2. Wire.onRequest(requestEvent);: Registers the requestEvent function to be called whenever the


Master requests data.

3. memcpy(floatBytes, &I, sizeof(float));: Converts the float I into a 4-byte array.

4. Wire.write(floatBytes[i]);: Sends each byte of the float to the Master in response to its request.

---

### Summary:
- *Part (b)*: The code reads the LM35 temperature sensor and calculates the temperature in Celsius.

- *Part (c)*: The Master requests a float value (I) from the Slave over I2C. The Slave sends this value as 4
bytes, which the Master then reassembles into a float and displays.

This setup enables the Master to display the float value on SM1 (Serial Monitor) at a 1-second interval.

#### *4a) Suppose you have stored 0x7D and 0x6E in the SPDR registers of Master and Slave
respectively. With a proper diagram, illustrate what data will be stored in the SPDR registers after 2, 4,
and 8 clock pulses. Also build a sketch to send 0x7D to the slave and receive 0x6E from the slave on an
interrupt basis.*

*Explanation:*

The Serial Peripheral Interface (SPI) communication involves the exchange of data between a master
and a slave device. In this scenario, we are using the SPDR (SPI Data Register) to send and receive data
between two devices. When using SPI, data is shifted out of the master’s SPDR and shifted into the
slave’s SPDR, and vice versa, one bit per clock pulse.

After:

- *2 Clock Pulses*: 2 bits will have been exchanged between master and slave.

- *4 Clock Pulses*: 4 bits will have been exchanged.

- *8 Clock Pulses*: Complete byte (8 bits) exchange will have taken place, with the master receiving 0x6E
and the slave receiving 0x7D.

*Sample Arduino Code for SPI Master (sending 0x7D and receiving 0x6E):*

cpp

#include <SPI.h>

volatile bool transferComplete = false;

void setup() {

SPI.begin(); // Initialize SPI as Master

SPCR |= _BV(SPIE); // Enable SPI interrupt

SPI.attachInterrupt(); // Attach interrupt


}

ISR(SPI_STC_vect) {

transferComplete = true; // Flag when transfer is complete

void loop() {

byte dataToSend = 0x7D; // Data to send to Slave

SPDR = dataToSend; // Start transmission by writing to SPDR

// Wait for transfer to complete

while (!transferComplete);

transferComplete = false;

byte receivedData = SPDR; // Read data received from Slave (should be 0x6E)

// Process received data as needed

delay(1000); // Delay before next transmission

*Sample Arduino Code for SPI Slave (receiving 0x7D and sending 0x6E):*

cpp

#include <SPI.h>

volatile bool dataReceived = false;

void setup() {

pinMode(MISO, OUTPUT); // Set MISO as output for Slave mode

SPCR |= _BV(SPE); // Enable SPI in Slave mode


SPCR |= _BV(SPIE); // Enable SPI interrupt

ISR(SPI_STC_vect) {

dataReceived = true;

void loop() {

byte dataToSend = 0x6E; // Data to send back to Master

SPDR = dataToSend; // Load data into SPDR to send

// Wait until data is received

while (!dataReceived);

dataReceived = false;

byte receivedData = SPDR; // Read data received from Master (should be 0x7D)

// Process received data as needed

---

#### *4b) Assume LED-1 and LED-2 are connected with Dpin-8 and Dpin-9 respectively. Build a sketch to
blink LED-2 with 1s interval in MLP (Main Loop Program). When IRQ1 signal arrives, blinking LED-2 will
be interrupted and LED-1 will blink for 5 times with 2s interval. Then it will return to MLP.*

*Explanation:*

This code sets up two LEDs on an Arduino, with LED-2 blinking every second in the main loop. When an
external interrupt on pin IRQ1 (Dpin-2) occurs, LED-2 stops blinking, and LED-1 blinks 5 times with a 2-
second interval, then resumes LED-2 blinking.
*Sample Arduino Code:*

cpp

const int led1 = 8; // LED-1 on Dpin-8

const int led2 = 9; // LED-2 on Dpin-9

volatile bool interruptFlag = false;

void setup() {

pinMode(led1, OUTPUT);

pinMode(led2, OUTPUT);

attachInterrupt(digitalPinToInterrupt(2), handleInterrupt, RISING); // Set up IRQ1 interrupt on Dpin-2

void loop() {

if (!interruptFlag) {

digitalWrite(led2, HIGH); // Blink LED-2

delay(1000);

digitalWrite(led2, LOW);

delay(1000);

void handleInterrupt() {

interruptFlag = true; // Set interrupt flag to stop LED-2 blinking

for (int i = 0; i < 5; i++) { // Blink LED-1 5 times with 2s interval

digitalWrite(led1, HIGH);

delay(2000);

digitalWrite(led1, LOW);

delay(2000);
}

interruptFlag = false; // Clear interrupt flag, resume LED-2 blinking

To help you with these questions, I’ll break down the coding tasks and explanations for each part. Here’s
a step-by-step solution and guidance for each question:

---

### Question 5

#### Part (a): Fast PWM Frequency Calculation

To compute the frequency of the Fast PWM:

1. *Equation for PWM Frequency*:

\[

f_{PWM} = \frac{f_{clk}}{N \times (1 + TOP)}

\]

where:

- \( f_{clk} \) is the clock frequency,

- \( N \) is the prescaler,

- \( TOP \) is the maximum count value (determined by ICR1 in this case for mode 14).

2. *Changing Frequency and Duty Cycle*:

- Adjust \( ICR1 \) to set the top value, which changes the frequency.

- Adjust the value in OCR1A or OCR1B to modify the duty cycle.


---

#### Part (b): Servo Control with ASCII Commands

To control an SG-90 Servo through Bluetooth:

1. *Setup Bluetooth Communication*: Use SoftwareSerial on pins 10 and 11 for Bluetooth


communication.

2. *Send ASCII Commands*: Write code to interpret ASCII commands from the Android phone to set
servo angles.

Example code:

cpp

#include <SoftwareSerial.h>

#include <Servo.h>

SoftwareSerial mySerial(10, 11); // RX, TX

Servo servo;

void setup() {

mySerial.begin(9600);

servo.attach(5); // Servo on DPin-5

void loop() {

if (mySerial.available() > 0) {

int angle = mySerial.parseInt();

if (angle >= 0 && angle <= 180) {

servo.write(angle);
}

---

#### Part (c): SPI Connection for BMP280 Sensor

1. *Connect BMP280 via SPI*: Use MOSI, MISO, SCK, and CS lines.

2. *Use a Level Shifter*: Connect 5V from Arduino to 3.3V for BMP280.

SPI Connection Example:

- *Arduino* ↔ *BMP280*

- MOSI (D11) ↔ SDI

- MISO (D12) ↔ SDO

- SCK (D13) ↔ SCK

- CS (D10) ↔ CSB (chip select)

---

### Question 6

Part (c)

Here's an Arduino code that uses a class to calculate the area of a rectangle given the length and width:

cpp

// Define a class for Rectangle

class Rectangle {

private:
float length;

float width;

public:

// Constructor to initialize the length and width

Rectangle(float l, float w) {

length = l;

width = w;

// Method to calculate the area

float calculateArea() {

return length * width;

};

void setup() {

// Start Serial communication

Serial.begin(9600);

// Create a Rectangle object with length=25 cm and width=15 cm

Rectangle myRectangle(25.0, 15.0);

// Calculate and print the area

float area = myRectangle.calculateArea();

Serial.print("The area of the rectangle is: ");

Serial.print(area);

Serial.println(" cm^2");

}
void loop() {

// Nothing needed in loop

### Explanation:

- The Rectangle class has two private member variables (length and width).

- It has a constructor that initializes these variables.

- The calculateArea() function returns the area of the rectangle by multiplying length and width.

- In setup(), an instance of Rectangle is created with the specified dimensions, and the area is calculated
and printed to the Serial Monitor.

### Question 7

#### Part (a): LED Control through Serial

Use Serial input to turn on/off an LED.

Example code:

cpp

const int ledPin = 13;

void setup() {

pinMode(ledPin, OUTPUT);

Serial.begin(9600);

void loop() {
if (Serial.available() > 0) {

String command = Serial.readString();

if (command == "Turn ON L") {

digitalWrite(ledPin, HIGH);

} else if (command == "Turn OFF L") {

digitalWrite(ledPin, LOW);

#### Part (b): Background Tasks for analogRead(A1)

1. The ADC reads the voltage on pin A1.

2. Converts the analog signal to a digital value (10-bit resolution by default on Arduino).

#### Part (c): Float to Byte Array using Union

Convert a float to a 4-byte array and send it over I2C.

Example code:

cpp

#include <Wire.h>

union {

float value;

byte bytes[4];

} floatUnion;
void setup() {

Wire.begin();

void loop() {

floatUnion.value = 15.73;

Wire.beginTransmission(0x23);

Wire.write(floatUnion.bytes, 4);

Wire.endTransmission();

delay(1000);

---

### Question 8

#### Part (a): Temperature Control for PWM

1. *Read Temperature*: Use DS18B20 to get temperature.

2. *Set PWM Output*:

- If temperature < 15°C, PWM on Dpin-5.

- Else, PWM on Dpin-10.

Example code:

cpp

#include <OneWire.h>

#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2

#define PWM_PIN_LOW 5

#define PWM_PIN_HIGH 10

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

void setup() {

sensors.begin();

pinMode(PWM_PIN_LOW, OUTPUT);

pinMode(PWM_PIN_HIGH, OUTPUT);

void loop() {

sensors.requestTemperatures();

float tempC = sensors.getTempCByIndex(0);

if (tempC < 15) {

analogWrite(PWM_PIN_LOW, 128); // 50% duty cycle

analogWrite(PWM_PIN_HIGH, 0);

} else {

analogWrite(PWM_PIN_LOW, 0);

analogWrite(PWM_PIN_HIGH, 128); // 50% duty cycle

delay(1000);

#### Part (b): INT0 Conditions


For the INT0 flag to generate an interrupt:

- The interrupt must be enabled.

- A rising, falling, or low-level condition should trigger the interrupt, as per the configuration.

#### Part (c): TC1 Internal Diagram

Illustrate the architecture showing:

1. *Clock Source*: External crystal.

2. *TC1 Prescaler*.

3. *TC1 Counter and Compare Registers*.

4. *Interrupt Logic*: Configure for generating interrupts.

---

This breakdown should help you understand each question and its corresponding solution code. Let me
know if you need further assistance with any specific part!

You might also like